Skip to content

Inkbox Voice AI

Handling a phone call normally means running a WebSocket server: Inkbox dials or answers, connects to your 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: provision a number, flip one setting, and the number answers. 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_url and the media stream. Everything documented elsewhere in the Phone docs.

Pick per call (outbound), or per identity or per number (inbound). The two tiers never mix on a single call.

The Inkbox Voice AI surface is available in the API, the SDKs, and the CLI from SDK 0.4.22. Authority modes, voicemail-detection control, and safe tool activity require SDK 0.5.8 or later.

Answering calls

Set the identity's incoming-call action to hosted_agent. It's the only answering action with zero prerequisites — no WebSocket URL, no webhook URL:

The same value is accepted when configuring a single number (PATCH /phone/numbers/{phone_number_id}, or inkbox number update --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) replaces the whole inbound-call config — omitted URLs are cleared, so 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 with mode="hosted_agent" and a plain-language reason describing what the call is for.

The 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.

Outbound calls detect voicemail by default and end the call when it is detected. Disable that behavior when the agent should leave a message:

Omit the setting to retain the default. Voicemail detection is independent of the call's authority mode and works for both Voice AI and client-driven calls.

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.

Configuring the agent

Each identity carries an optional Voice AI configuration: a voice, a model, and free-form instructions (up to 8,000 characters) that steer how the agent behaves on that identity's calls. All three are nullable — a null field means the platform default applies, and the defaults are sensible, so most identities need no configuration at all.

Under the hood this is GET/PUT /phone/hosted-agent-config. Reads also report the current authority_mode. Writes are full-replace for voice, model, 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:

ModeScope
contact_scopedThe agent can work only with the current caller or outbound recipient and that contact's history.
yoloThe agent can work across the identity's contacts, email, SMS, iMessage, and historical calls, including records and recipients unrelated to the current call.

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

New identities start with contact_scoped. 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:

The body accepts exactly 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, model, or instructions does not change the authority mode.

Choose the mode for one outbound call

Omit hosted_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:

An explicit 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.

With 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:

  • 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.

With 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.

With 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 yolo call in the Inkbox Console to see each tool's running, completed, or failed state. The same safe, 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. Once a write is accepted, Inkbox continues it even if the call ends; a briefly running item can therefore finish after hangup.

What it can't do

contact_scoped cannot read or contact anyone other than the person on the call. yolo widens that data scope, but it does not bypass channel availability, consent, contact rules, delivery behavior, or usage limits.

A Voice AI agent cannot place another phone call 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 single call.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.

outcomeMeaning
completedThe call connected and ran to a normal end. A call that reaches voicemail also reports completed — the transcript shows what happened
no_answerThe call was never answered — an outbound call rang out, or an inbound caller hung up before the agent picked up
declinedThe call was rejected, or the line was busy
failedThe Voice AI session hit an error and the call was torn down, or the call could not be completed at all — e.g. an undeliverable destination

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:

JSONJSON

Each item carries a 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:

  • Place call — the mode, reason, hosted_agent_authority_mode, and voicemail_detection request fields
  • Incoming calls — the hosted_agent action
  • Call-ended webhook — the full payload, including outcome and post_call_action_items
  • Webhooks guide — subscribing and handler examples