Back to App Store

AgentPhone

AgentPhone · io.pilot.agentphone
A real phone number for your agent — voice calls, SMS/iMessage, and conversations over REST.
CommunicationsLive on catalogue
Install
pilotctl appstore install io.pilot.agentphone
v0.3.1
Version
53
Methods
8.5 MB
Size
shareable
Sandbox
macOS · Linux
Platforms

About AgentPhone

AgentPhone gives your agent its own real US/Canada phone number: place and receive voice calls, send and receive SMS & iMessage, and hold threaded conversations with real people — all over plain REST. This is the managed Pilot front door: you bring nothing (no signup, no API key). Pilot holds one AgentPhone master key behind the broker and gives each Pilot user a $5 budget; calls and texts debit against it, and once it's spent the paid endpoints return 402 Payment Required (reads stay free).

What you can do

  • Call people. agentphone.place_call with a systemPrompt runs an autonomous voice call — the phone rings in ~1–2s and the AI holds the conversation. Book a reservation, chase a shipment, return a missed call, or call another agent.
  • Text people. agentphone.send_message delivers over iMessage when both sides support it (unlocking threaded replies, tapback reactions, send effects, typing indicators, group chats) and transparently falls back to SMS/MMS otherwise — same call either way.
  • Answer & follow up. Poll agentphone.list_number_messages / agentphone.list_conversation_messages for inbound texts and agentphone.get_call for call transcripts — no websockets required.
  • Manage your setup. Buy/release numbers, create and tune agents (voice, model tier, system prompt, ambience), keep an address book of contacts, and attach numbers to agents.

First run: agentphone.setup (no signup, no agent)

Because this is the managed app there is no signup — but there is also no agent or number: the AgentPhone account is shared behind the broker and every Pilot user starts empty. So the first thing to do is call agentphone.setup once. It creates your agent and attaches a phone number (buying one costs $3/mo — setup asks you to confirm with confirm_spend:true before spending). After that, agentphone.send_message / agentphone.place_call work from the agent_id it returned. agentphone.status tells you at any time whether you're ready. Just call the /v1 methods below; the broker authenticates you as your Pilot identity, injects the master key, meters your spend, and forwards to https://api.agentphone.ai.

Your data is yours (per-user isolation)

Even though every Pilot user shares one AgentPhone account, the broker isolates you completely: you only ever see and act on your own agents, numbers, messages, calls, conversations, and contacts — never another user's, whatever the method. References to a resource you don't own return 404, and list methods return only your own rows (and your own counts). Billing is per-user at the broker, not AgentPhone: your remaining budget rides on the X-Pilot-Credits-Remaining header of every metered response (account-wide usage aggregates are deliberately not exposed).

Async, poll-based (no streaming): 1. agentphone.place_call → returns a call id immediately; the call runs in the background. 2. Poll agentphone.get_call every few seconds until status is completed or failed, then read transcripts[] (or agentphone.get_transcript). 3. For inbound SMS, poll agentphone.list_number_messages with the after cursor and filter direction == "inbound".

Critical gotchas (read once)

  • You cannot call 911, N11 numbers, or crisis lines — they're blocked. If your human has an emergency, tell them to dial directly.
  • Released numbers are gone forever — no refund for the unused month. Confirm before agentphone.release_number.
  • Always use E.164: +14155551234 ✓ — never (415) 555-1234 or 415-555-1234. Assume +1 for a bare US number and confirm if it matters.
  • Inbound calls need hosted mode OR a webhook. Create agents with voiceMode: "hosted" explicitly (the backend defaults to webhook, which fails inbound if no webhook is set).
  • iMessage-only features (reactions, send effects, typing, backgrounds, contact cards) are silently ignored on SMS — check the response channel.
  • Don't spam. Unsolicited bulk calls/texts are illegal and get the account suspended.

Cost & the $5 budget

Reads are free. Spending operations debit your per-user $5 Pilot budget: buying a number ($3.00/mo), placing a call (per-minute), and sending a text (~$0.01–0.02). When a call would overdraw, the broker returns 402 before anything is charged, and every response carries your remaining balance in the X-Pilot-Credits-Remaining header (micro-dollars).

Every method's parameters, kind, and latency class are discoverable at runtime via agentphone.help.

Methods · 53

agentphone.setup
START HERE (managed model). Idempotent: create your agent + attach a number (buying costs $3, gated by confirm_spend). Returns {ready, agent_id, number_id, phone_number}. Run before send/call.
example{"confirm_spend": true}
agentphone.status
Are you ready to call/text? Free read: reports whether you own an agent with an attached number; if not, points you to agentphone.setup.
agentphone.usage
Account status: plan, phone-number hold limit (used/limit/remaining), and message/call/webhook stats. Call this first to orient in a session. Read-only; no charge.
agentphone.usage_by_number
Usage broken down per phone number. Read-only.
agentphone.usage_by_agent
Usage broken down per agent over a period. Read-only.
agentphone.list_voices
List available text-to-speech voices (voice_id, voice_name, provider, gender, accent, preview_audio_url) across ElevenLabs, Cartesia, OpenAI, and platform voices. gender/accent/preview may be null — do not crash on missing fields. Use voice_id when creating/updating an agent. Read-only.
agentphone.list_agents
List the agents you own. Managed model: you start with NONE — run agentphone.setup first. You only ever see your own agents, never other users'.
agentphone.create_agent
Create an agent (phone persona). For AI-driven use pass voiceMode:"hosted" explicitly (the backend defaults to "webhook", which needs a configured webhook or inbound calls fail). systemPrompt is required for hosted. Pick a voice from agentphone.list_voices. Free (no telephony spend).
agentphone.get_agent
Get one agent's full config and its attached numbers. Read-only.
agentphone.update_agent
Update an agent — only the fields you send change. Any create field is updatable (systemPrompt, voice, modelTier, …). Free.
agentphone.delete_agent
Delete an agent. Irreversible — clears the agent's references on its numbers/conversations/calls (those are NOT deleted). Confirm with your human first. Free.
agentphone.attach_number
Attach an existing number to an agent so the agent can call/text from it. Free.
agentphone.detach_number
Detach a number from an agent (the number is kept, just unassigned). Free.
agentphone.list_agent_conversations
List an agent's conversation threads, newest activity first (data[], hasMore, total). Read-only.
agentphone.list_agent_calls
List an agent's calls (data[], hasMore, total). Read-only.
agentphone.list_numbers
List your active phone numbers (id, phoneNumber, country, status, agentId). Read-only.
agentphone.buy_number
Provision a new US/CA phone number. COSTS $3.00 from your $5 Pilot budget (402 if it would overdraw). The provisioned number is saved to this host's ~/.pilot/.agentphone so you can recall it later with agentphone.mynumber — no need to store it yourself. Optionally attach to an agent and request an area code.
agentphone.get_number
Get one phone number by id (any status, including released). Read-only.
agentphone.release_number
Release (delete) a number. IRREVERSIBLE — the number returns to the carrier pool; no refund for the unused month. Confirm with your human first. Free to call.
agentphone.list_number_messages
List messages on a number (inbound + outbound), newest first, cursor-paginated. THE non-websocket way to detect SMS replies: poll with the `after` cursor and filter direction=="inbound". Read-only.
agentphone.list_number_calls
List calls on a number. Read-only.
agentphone.get_contact_card
Get the iMessage contact card shown on a number (firstName, lastName, displayName, hasAvatar). iMessage only. Read-only.
agentphone.set_contact_card
Create/replace the iMessage contact card on a number (name + avatar shown to recipients). iMessage only. Free.
agentphone.delete_contact_card
Remove the iMessage contact card from a number. Free.
agentphone.send_message
Send an SMS/iMessage. COSTS MONEY (~$0.01–0.02, debited from your $5 budget → 402 if over). Auto-delivers over iMessage when both sides support it, else SMS/MMS — the response `channel` (sms|mms|imessage) tells you how it went. E.164 for `to_number` (or a group id grp_… for an iMessage group). iMessage-only extras (send_style, reply_to_message_id) are silently ignored on SMS.
agentphone.react
Send a tapback reaction to a message. iMessage ONLY — returns 400 on SMS. Free.
agentphone.list_calls
List calls for the account (filter by status/direction). Read-only.
agentphone.place_call
Place an OUTBOUND voice call. COSTS MONEY (per-minute, ~$0.05+, debited from your $5 budget → 402 if over). With `systemPrompt` the AI runs the call autonomously (recommended); without it, each turn is POSTed to the agent's webhook. Returns a call id IMMEDIATELY (async) — the phone rings in a second or two. Then POLL agentphone.get_call every few seconds until status is completed/failed to read the transcript. Cannot call 911 / N11 / crisis lines (blocked).
agentphone.get_call
Get a call and its embedded transcripts[]. THE poll target for a call outcome (no websockets): call every few seconds until status is completed or failed (in-progress means partial/empty transcript). Also carries durationSeconds, startedAt, endedAt. Read-only.
agentphone.end_call
Terminate an in-progress call. status/endedAt settle shortly after via the provider — keep polling agentphone.get_call until terminal. Free.
agentphone.get_transcript
Get the full ordered transcript of a call as plain JSON (user utterance + agent response per turn). This is the REST/polling alternative to the SSE live-transcript stream — the adapter never uses the stream. Read-only.
agentphone.list_conversations
List conversation threads (one per external contact or iMessage group), sorted by lastMessageAt desc (data[], hasMore, total). Read-only.
agentphone.get_conversation
Get one conversation with its recent messages (participant, isGroup, group roster, messageCount, metadata). Read-only.
agentphone.update_conversation
Update a conversation's `metadata` (attach custom AI context/state to the thread). Free.
agentphone.list_conversation_messages
List a conversation's messages, cursor-paginated (data[], hasMore). Poll with `after` to catch new inbound replies in a thread. Read-only.
agentphone.typing
Show a typing indicator before you reply. iMessage only, best-effort, auto-expires (no stop call). Free.
agentphone.set_background
Set a chat background image for a conversation. iMessage only. Free.
agentphone.clear_background
Clear a conversation's chat background. iMessage only. Free.
agentphone.list_contacts
List saved contacts (data[], hasMore, total); `search` filters by name/phone. Read-only.
agentphone.create_contact
Save a contact so you can look them up by name later. phoneNumber is normalized to E.164; returns 409 if the phone already exists. Free.
agentphone.get_contact
Get one contact by id. Read-only.
agentphone.update_contact
Update a contact — only the fields you send change (phone is re-normalized; 409 on conflict). Free.
agentphone.delete_contact
Delete a contact. Confirm with your human first. Free.
agentphone.get_webhook
Get the account-level webhook config. Read-only. (Polling is the default event model for this adapter; webhooks are optional.)
agentphone.set_webhook
Set the account-level webhook URL (returns a signing `secret`; a new one each call). NOTE: on the shared Pilot AgentPhone account this is a GLOBAL setting — prefer per-agent webhooks or polling. Free.
agentphone.delete_webhook
Remove the account-level webhook. Global on the shared account — use with care. Free.
agentphone.list_webhook_deliveries
List recent webhook delivery attempts (items[], total). Read-only.
agentphone.webhook_delivery_stats
Aggregated webhook delivery stats over the last N hours (success/failed/pending, byEventType, byHour). Read-only.
agentphone.test_webhook
Send a synthetic test event to verify your endpoint is reachable and verifying signatures. Free.
agentphone.get_agent_webhook
Get an agent-specific webhook (overrides the account default for that agent). Read-only.
agentphone.set_agent_webhook
Set an agent-specific webhook URL (overrides the account default for THIS agent only — safer than the account-level webhook on a shared account). Free.
agentphone.delete_agent_webhook
Delete an agent-specific webhook (the agent falls back to the account default). Free.
agentphone.mynumber
Recall the phone number(s) THIS daemon provisioned (local, no backend call, free). Reads ~/.pilot/.agentphone, populated automatically by agentphone.buy_number. Returns {entries:[{id,phoneNumber,status,agentId,...}]} — empty if this host hasn't provisioned one yet. Use it to find 'my number' without listing the shared account.

Full usage demo

When your agent needs to place a real phone call or send an SMS/iMessage to a person — bookings, reminders, follow-ups, chasing a shipment or a missed call.

Run this first — Orient — check your account and $5 budget (free read)$0.00 (read)
Call
pilotctl appstore call io.pilot.agentphone agentphone.usage '{}'
{"plan":"managed","numbers":{"used":0,"limit":1},"stats":{...}}

Worked examples

Set up: create an agent + attach a number (free read)$0.00 (read)
Call
pilotctl appstore call io.pilot.agentphone agentphone.list_agents '{}'
{"data":[{"id":"agent_...","name":"Assistant","voiceMode":"hosted"}]}
Place an autonomous voice call$0.10
Call
pilotctl appstore call io.pilot.agentphone agentphone.place_call '{"agentId":"agent_123","toNumber":"+14155551234","systemPrompt":"Confirm the 7pm reservation for two under Alex."}'
{"id":"call_...","status":"queued"}

Returns immediately; poll agentphone.get_call for the transcript.

Poll the call transcript (free read)$0.00 (read)
Call
pilotctl appstore call io.pilot.agentphone agentphone.get_call '{"call_id":"call_..."}'
{"status":"completed","durationSeconds":42,"transcripts":[...]}
Send a text (iMessage → SMS fallback)$0.02
Call
pilotctl appstore call io.pilot.agentphone agentphone.send_message '{"agent_id":"agent_123","to_number":"+14155551234","body":"On my way, 5 min out."}'
{"id":"msg_...","channel":"imessage"}

What it costs

$5.00 per Pilot userfree budget · billed in micro-USD (1000000 = $1.00)
OperationPriceNotes
agentphone.place_call$0.10per call (per-minute, ~$0.05+ for a short call)
agentphone.send_message$0.02per SMS/iMessage
agentphone.buy_number$3.00per month; released numbers are gone forever, no refund
agentphone.usage / list_* / get_call / get_transcript$0.00all reads are free

This demo spends $0.12 of your $5.00 budget (1 call + 1 text; the two reads are free).

Check balance
pilotctl appstore call io.pilot.agentphone agentphone.usage '{}'

Good to know

  • Always use E.164 numbers (+14155551234) — never (415) 555-1234.
  • You cannot dial 911, N11, or crisis lines — they are blocked.
  • 402 Payment Required means your $5.00 budget is spent — reads still work.
  • place_call/send_message need an agent with a number attached — list_agents / list_numbers first.
  • Calls are async: place_call returns a call id, then poll get_call until status is completed/failed.
  • iMessage-only extras (reactions, send effects) are silently ignored on SMS — check the response channel.

Next

  • io.pilot.agentphone agentphone.help '{}'

What’s New

v0.3.1Latest
  • Add agentphone.setup / agentphone.status: one-call onboarding for the managed model (no signup, no agent) — creates your agent and attaches a number; send_message/place_call point you to setup on a cold start.
  • Per-user isolation: drop /v1/usage/daily and /v1/usage/monthly (shared-account aggregates that leaked other users' activity). Per-user budget is the broker ledger (X-Pilot-Credits-Remaining).
v0.3.0
  • Managed Pilot front door — no signup, no API key: the broker holds one master key and gives each user a $5 budget (402 on overdraw; reads free).
  • Full non-streaming REST surface (53 methods): numbers, agents, voice calls, SMS/iMessage, threaded conversations, contacts, and usage.
  • Local recall: agentphone.buy_number captures the number to ~/.pilot/.agentphone; agentphone.mynumber reads it back with no backend call.

Platform Compatibility

macOSApple Silicon
4.5 MBSupported
macOSIntel
5.1 MBSupported
Linuxarm64
4.9 MBSupported
Linuxamd64
4.4 MBSupported
You might also like

More in Communications