client_websocket_url, and streams audio both ways (see Media Stream). Inkbox Voice AI removes the socket entirely. Inkbox runs an opinionated realtime voice agent on the platform side — it answers (or places) the call, knows who it’s talking to, can work with the communication history its authority mode allows, records action items, and hands your agent a structured package when the call ends.
Zero setup: new numbers use hosted_agent to answer incoming calls by default. No code, no socket, and no webhook required — the call.ended webhook is optional output, never required input.
There are exactly two ways to put a brain on a call:
- Inkbox Voice AI — zero setup, run by Inkbox, opinionated, with a fixed built-in toolset. This page.
- Bring your own — full control over the audio via
client_websocket_urland the media stream. Everything documented elsewhere in the Phone docs.
on_voicemail and voicemail_message require SDK 0.7.2 or later.
Voice AI calls on a dedicated phone or dedicated iMessage line can transfer to
another person or add a conference guest. Shared iMessage lines do not support
transfers or conferences. SDK 0.7.19 adds connection history and per-turn
phone numbers; existing clients can still read calls and webhooks without upgrading.
Contact visibility
Ordinary hosted calls follow the identity’s contact permissions. Profile is required for contact data, and Memories can be disabled separately, so the agent can have a person’s notes and addresses without their stored memories. Hosted voice in YOLO mode can read all contacts, fields, identifiers, and contact memories in its organization regardless of per-contact restrictions. This does not change communication rules or existing access to citation sources. The identity’s ordinary API, SDK/CLI, MCP, and webhook views remain scoped, even when its default voice mode is YOLO. YOLO contact updates edit profile fields. Changing an existing contact’s email addresses or phone numbers requires admin credentials or the Console. Creating a new contact may include identifiers, but does not grant communication permission or modify an existing matching suggestion.Answering calls
The default incoming-call action ishosted_agent. It requires no WebSocket or webhook URL. To select it explicitly:
PATCH /phone/numbers/{phone_number_id}, or inkbox number update PHONE_NUMBER_ID --incoming-call-action hosted_agent). The number-level PATCH merges: any stored client_websocket_url or incoming_call_webhook_url is kept but ignored while the action is hosted_agent. The identity-level action set (the snippet above) clears omitted WebSocket and webhook URLs, while omitted forwarding fields preserve their saved values. If you later switch back to auto_accept or webhook, supply the URL again in that call.
Inbound protections run before the agent picks up: contact rules and usage quotas apply exactly as they do for every other action — the voice agent only answers calls that would have been deliverable anyway.
Placing calls
Give the agent an errand: place a call withmode="hosted_agent" and a plain-language reason describing what the call is for.
reason becomes the agent’s task brief for the call: it introduces itself, works the errand, records what happened as post-call action items, and ends the call politely. A failed errand is never silent — whatever happens, you get the post-call package.
Reaching voicemail
An outbound call rings for up to 60 seconds; if nobody picks up, the errand ends with theno_answer outcome. When voicemail answers instead, on_voicemail decides what happens next:
Pass
voicemail_message (up to 1,000 characters) to control what the agent says after the beep. It delivers the message in its own voice rather than reading it word for word. Omit it and the agent composes a short message from reason:
on_voicemail to keep the default. leave_message and voicemail_message are only valid on Voice AI calls; hang_up and ignore work for both Voice AI and client-driven calls, independent of the call’s authority mode. The older voicemail_detection setting remains accepted as a deprecated alias — "enabled" is hang_up and "disabled" is ignore — and every call still reports it alongside on_voicemail.
Two shape rules, enforced with a 422: mode="hosted_agent" requires a non-empty reason (up to 2,000 characters) and must not carry a client_websocket_url; reason is only valid with mode="hosted_agent". Everything else about placing a call — origination, caller ID rules, rate limits — is unchanged; see the place call reference. When Voice AI capacity is momentarily saturated, the API returns 503 hosted_agent_at_capacity; retry shortly.
mode works with any origination, so the voice agent can call over a dedicated number or the identity’s iMessage line alike.
Outbound Voice AI calls inherit the identity’s saved authority mode. You can
override one call when it needs narrower or wider access; see
Choosing an authority mode.
Navigating phone menus
Voice AI can follow automated phone menus and press0-9, *, and # when prompted. For an outbound call, include any known extension, account menu, or navigation goal in the reason you send through the API, an SDK, the CLI, or MCP:
REST
dtmf event.
Call transfers and group calls
During an active Voice AI call on a dedicated phone or dedicated iMessage line, the agent can:- Transfer the call entirely — connect the caller to another phone number. Once connected, the agent leaves and the conversation continues without it.
- Start a conference or group call — add one other person while the agent stays. This creates a three-way call: the original caller, the guest, and the agent.
Configuring the agent
Each identity has an optionalvoice and free-form instructions (up to 8,000 characters) for Voice AI calls. Omit them or set them to null to use the defaults.
Inkbox selects a compatible model for each voice. The deprecated model field, SDK argument, and CLI --model flag remain accepted but do not change call behavior. Responses keep model as null. Treat effective_model (effectiveModel in TypeScript) as an opaque compatibility value, not a model to select or send as an override.
Choosing a voice
UseGET /api/v1/phone/hosted-agent-voices to discover supported voices and their current availability. Authenticate with an admin API key or a claimed agent-scoped API key. No agent_identity_id parameter is required. You can also choose a voice in the Inkbox Console, under incoming-call settings or when making a call.
The catalog currently lists 19 voices:
cURL
200 response contains:
Use the API’s returned order,
available values, and default_voice when building a voice picker. Refresh the catalog before presenting a choice. Availability and the default can change.
Select a voice with available: true. Selection access is separate from call and minute allowances. A disallowed voice change returns 403. A selected voice that is currently unavailable for calls returns 503 hosted_agent_unavailable when you place a Voice AI call.
Apollo (apollo) is no longer listed for new selections; choose Orion (orion) from the catalog instead. Selecting Apollo for an identity that does not already use it returns 422. Existing Apollo configurations remain supported, including calls and updates that retain the saved voice.
An explicitly saved voice stays selected when the default changes. An omitted or null voice follows default_voice. Selection access is checked when the effective voice changes. You can still update instructions while retaining the same effective voice, even if selecting it is no longer allowed.
Sample URLs are accessible without authentication headers and may be missing or null. A sample’s presence does not establish availability, and sample audio does not guarantee call audio quality.
Save an available voice ID using the configuration methods below or the CLI’s --voice flag. Changes affect future inbound and outbound calls for the identity. The examples use ara; choose an available ID from the current catalog. Configuration writes replace both voice and instructions, so include every value you want to keep.
GET/PUT /phone/hosted-agent-config. Reads also report the current authority_mode. Writes are full-replace for voice and instructions: every omitted or null field resets to the platform default, while the authority mode is unchanged. Identity-scoped API keys resolve their own identity; with an admin API key, or when managing from the Inkbox Console, pass agent_identity_id.
Custom instructions are layered on top of everything the agent already knows, so they can steer tone, boundaries, and priorities without you restating the basics. The agent treats them as standing orders from you, applied on every call — with one carve-out: on an outbound errand, the call’s reason takes precedence if the two conflict, so a standing quirk can’t hijack the task the call was placed for.
Choosing an authority mode
Every Voice AI call has one of two authority modes:
Unconfigured identities use
yolo. Use contact_scoped when the call should stay focused on the person on the line. Use yolo when the caller needs the voice agent to act as a general assistant for the identity — for example, to look up another contact, review a different conversation, or send a follow-up to someone else.
Set the identity’s default
An identity without a saved Voice AI configuration defaults toyolo. This
default applies to:
GET /phone/hosted-agent-config, which reportsauthority_mode: "yolo".- The first
PUT /phone/hosted-agent-configsave, which storesyolo. - Incoming Voice AI calls.
- Outbound Voice AI calls placed without a
hosted_agent_authority_modeoverride.
contact_scoped, and
doesn’t rewrite them to yolo. Editing voice or instructions doesn’t change a
saved mode. To keep contact-scoped behavior for an identity, save
contact_scoped explicitly.
You can change the saved mode from the Inkbox Console, or send a request with
an admin API key. Future incoming Voice AI calls and outbound Voice AI calls
without an override inherit this setting:
agent_identity_id and authority_mode. A successful response returns the identity’s current Voice AI configuration, including the new authority_mode. An invalid identity or mode returns 422, and an unknown identity returns 404.
This endpoint is separate from the full-replace Voice AI configuration above, so changing voice or instructions does not change the authority mode.
Choose the mode for one outbound call
Omithosted_agent_authority_mode to inherit the identity’s saved mode. To
narrow one call, explicitly set contact_scoped; any credential that can place
the call can do this. To request yolo, include it as an override:
yolo reuses a saved yolo grant with any credential that can
place the call. If the identity’s saved mode is contact_scoped, requesting
yolo widens access and requires an admin API key or the Inkbox Console.
yolo is valid only when mode is hosted_agent. Each
call object records the authority mode that
applied to that call.
What the agent knows
Every Voice AI session is briefed at answer time with the current call:- Its own identity — the agent’s display name, handle, email address, and which line the call is on.
- Who it’s talking to — the counterparty’s contact card (name, company, notes, known numbers and emails), resolved by the number on the call. Unknown callers work fine; the agent simply greets them neutrally.
- Their connection state — whether the caller is opted in to SMS, and whether they’re connected over iMessage — so the agent offers follow-ups on channels that will actually work, and can walk them through connecting where they aren’t.
- The local time — the call clock runs in the counterparty’s timezone, inferred from the phone number (stated as approximate), so “tomorrow morning” means what the caller means.
- The task brief — on outbound Voice AI calls, your
reason.
contact_scoped, the agent can read the identity’s history with that person across calls, SMS, iMessage, and email. With yolo, it can also look across the identity’s other contacts, conversations, messages, and historical calls as the task requires.
What the agent can do
Voice AI uses a built-in capability set. Sends go through the same pipeline as any other Inkbox send: SMS opt-outs, contact rules, and delivery tracking all apply exactly as if your own code had sent the message. On every call, the agent can:- Transfer calls or add a participant on a dedicated line — hand the call over entirely, or stay for a three-way conference call.
- Navigate automated phone menus — press
0-9,*, and#when prompted. - Record work for your agent — register, refine, or withdraw post-call action items during the call; the open items become the post-call package.
- Answer “what is Inkbox?” — it can consult the public Inkbox docs and offer to text a relevant link rather than reading URLs aloud.
- Check live state and end the call — re-check the caller’s connection state mid-call (e.g. to confirm “your message just came through”), and hang up once the caller signals they’re done.
contact_scoped, it can:
- Recall history with the person on the call — past calls and transcripts, SMS, iMessage, and email threads, plus keyword search across that history.
- Text, iMessage, or email that person mid-call — using the identity’s corresponding channel.
yolo, it can also:
- Work with contacts across the identity — find, create, and update contact records.
- Read and send across communication channels — search and read email, SMS, and iMessage conversations and send to an explicit recipient accepted by that channel.
- Review historical calls across the identity — list past calls with any counterparty and read their transcripts.
Tool activity
Open a Voice AI call in the Inkbox Console to see each tool’s running, completed, or failed state. Activity is recorded for bothcontact_scoped and yolo calls; older calls may have no recorded activity. The same paginated activity is available from GET /phone/calls/{call_id}/tool-invocations and from calls.tool_invocations() in Python, calls.toolInvocations() in TypeScript, or calls().tool_invocations() in Rust.
The activity view omits tool arguments and returns only a small result summary. On yolo calls, an accepted write can continue after the call ends. A running item can therefore finish after hangup.
What it can’t do
contact_scoped limits separate contact messages and history to the original
inbound caller or outbound recipient. On a dedicated line, it can transfer the
call or add a guest. The shared call transcript can include the guest’s speech
and phone number; joining the call does not grant access to that guest’s separate
messages or other conversation history. yolo widens that data scope, but it does not bypass channel availability, consent, contact rules, delivery behavior, or usage limits.
Transfers and conferences extend the current call; the agent cannot start a separate phone conversation while it is already on a call. It can review historical calls and transcripts, but not the active call’s transcript through the historical-call interface.
It also doesn’t run custom tools. If your agent needs to hit your systems mid-call, that’s the bring-your-own tier: take the call over client_websocket_url and drive it yourself. For everything that can wait until the call ends, post-call action items cover it — the voice agent records the work, and your agent executes it from the call.ended delivery.
The post-call package
Every Voice AI call ends in a singlecall.ended delivery carrying the whole story: the call record (now with mode and reason), the transcript, an outcome, and the recorded post_call_action_items — atomically, in one event. A Voice AI call reports back on every terminal state, inbound and placed alike — even when nobody picked up, outcome says what happened — so an errand can’t fail silently.
outcome is null on client_websocket calls — it describes Voice AI sessions only, and it rides the call.ended payload as data.outcome.
Action items arrive as an ordered list on the same event, as data.post_call_action_items:
JSON
seq (its 1-based order), an action title, optional details, and a status of "open". Actions the agent canceled mid-call are dropped — only open items ride the payload. The call.ended event is the one atomic delivery of the whole package (outcome lives only there); like every webhook it carries a stable ID and is replayable, so a missed delivery can be re-fetched rather than lost. The open action items are additionally readable straight off the call object as post_call_action_items, so they can be looked up any time without replaying the event.
Watching and stopping a live call
You keep two levers while a Voice AI call is in progress:- Live view — transcript segments land while the call runs. Poll
GET /phone/calls/{call_id}/transcripts, or watch the call live in the Inkbox Console. - Kill switch —
POST /phone/calls/{call_id}/hangupends any live call from the outside, Voice AI or not. Teardown runs the normal lifecycle, so you still receive the full post-call package.
Related
- Place call — the
mode,reason,hosted_agent_authority_mode,on_voicemail, andvoicemail_messagerequest fields - Incoming calls — the
hosted_agentaction - Call-ended webhook — the full payload, including
outcomeandpost_call_action_items - Webhooks guide — subscribing and handler examples

