Audio specs
Agent audio always arrives as a base64-encoded
audio JSON message — this endpoint never sends raw binary audio frames to the client (unlike /ws/tts).
Connection
Authorization: Bearer or X-API-Key header, or with ?api_key= where headers cannot be set. In a browser, pass a short-lived wst_ ticket, never your key (Authentication). The handshake is refused with 401 for a bad credential, 402 (plain text) when the balance cannot start a session, 404 agent.not_found for an agent_id that is not yours, and 429 auth.rate_limited past your account’s concurrent sessions.
Optional query parameters:
Query values override the same keys in the agent’s config.
Agent config
A session with anagent_id runs with that agent’s config, set in the dashboard. Keys documented elsewhere: web_search, google_calendar and the calendar settings, crm and timezone in Tool Calling. This one changes how the agent takes its turn:
Initialization
Send configuration as JSON messages after connecting, in this order:rates last: receiving it tells the server your configuration is complete and releases the first conversational turn. Each of voice/language/prompt/rates is acknowledged with a status message (voice_set, language_set, prompt_set, rates_set).
With an agent_id, every message except rates is optional: send only what you want to override. Without one, send at least prompt.
An unknown voice or language is answered with an error frame, {"type": "error", "data": {"code": "validation.invalid_voice", …}} (or validation.invalid_language), and no voice_set / language_set ack; the session keeps its previous value.
Language. A language (or the agent’s own) is kept for the whole session: the agent speaks it, and speech recognition listens for it, short replies included. Send an empty string, {"type": "language", "data": ""}, to let the agent follow the caller instead. It recognises the caller’s language from what they say and replies in it in the same voice. A short reply such as “yes” or a number is heard in the language the caller last spoke, and the agent switches when the caller does. With neither an agent_id nor a language message, the agent speaks English and recognition follows the caller.
Client to server
Send microphone audio as binary Int16 PCM frames (16 kHz, mono, ~20ms chunks). You can also send the same audio as{"type":"audio","data":"<base64>"} if binary frames aren’t convenient in your environment.
Other client → server messages: pitch (adjust pitch-shift), reset (clear conversation context), tool_result (return a client-executed tool’s result — see Tool Calling).
Server to client
Barge-in
When the user starts speaking over the agent, the server sendsstatus: listening and stops sending new audio for the reply, but the barge-in is only tentative: keep playing what you already have. status: interrupted follows once the interruption is real (the user kept talking for 400 ms, or their utterance is confirmed as speech rather than noise, a backchannel or an echo of the agent); stop playback and clear queued audio then. If it was a false alarm, the server sends status: speaking (or thinking, if the reply was still being generated) and the reply continues under the same generation. See Handling Interruptions.
An agent reply is sent as a transcript as soon as it is generated, which is before it has finished playing. When the user interrupts, a transcript_truncated follows with what they actually heard, and the agent’s own memory of the conversation is corrected the same way. If the user was only pausing and the agent had said no more than a word or two, the user’s two fragments become one turn (transcript_revised) and the agent answers the whole sentence.
A reply the user never heard any of — they started speaking again before it began to play — is not kept. It is either never sent as a transcript, or, if it already was, withdrawn with a transcript_truncated whose data is empty and emitted true. The agent forgets it too, and answers what the user goes on to say.
Silence
If the user says nothing for 10 seconds after the agent finishes speaking, the agent speaks once, unprompted: it asks whether they are still there or need anything else — or, if their last turn went unanswered, answers it. It arrives like any other reply (transcript, then audio under a new generation), at most once per silence; the next time the user speaks re-arms it. It never acts on the user’s behalf: no tool is called while they are silent, even if the agent’s last line offered to do something.
Idle sessions
A session in which nobody has spoken for 5 minutes ends: the agent says goodbye (as an ordinarytranscript and audio), and the socket closes with code 1000 and the reason nobody has spoken for 5 minutes. A session whose account balance runs out closes with 1008 and the reason account balance exhausted.
Related Pages
- WebSocket Protocol — full message reference
- Handling Interruptions — barge-in mechanism in detail
- Tool Calling —
tool_call/tool_resultflow and built-in tools