Use the generated realtime reference for a message index or download the AsyncAPI contract.
WebSocket API
Connect to wss://converse.trelis.com/ws. Trusted non-browser clients may authenticate with Authorization: Bearer ck_…; all clients may include api_key in their first JSON frame.
Start frame
{
"type": "start",
"session_id": "your-unique-session-id",
"api_key": "ck_or_scoped_key",
"audio": { "sr": 16000 },
"mode": { "kind": "converse", "web_search": false },
"client": {
"user": "optional-stable-user-id",
"timezone": "Europe/Dublin",
"capabilities": []
}
}
| Field | Required | Description |
|---|---|---|
type | Yes | Must be start. |
session_id | Yes | Your 1–64 character correlation ID; must match a scoped key. |
api_key | If no auth header | Persistent or scoped credential. |
audio.sr | Yes | Input sample rate. Use 16000. |
mode | Yes | Conversation configuration. |
client | No | User metadata and implemented protocol capabilities. |
Audio frames
| Direction | Encoding | Recommended frame size |
|---|---|---|
| Client → Converse | Binary PCM16 little-endian, mono, 16 kHz | 20–100 ms, paced in real time |
| Converse → client | Binary Float32 little-endian, mono, 16 kHz | Play in arrival order |
JSON and binary frames share the same socket. A normal reply is turn, zero or more binary audio frames, utterance, then done. User transcripts arrive as asr.
Client control frames
| Frame | Purpose |
|---|---|
{"type":"reset"} | Clear conversation context. |
{"type":"set_voice","voice":"key"} | Change voice for the next reply. |
{"type":"tool_result","id":"…","content":{…}} | Resolve a tool call. |
{"type":"tool_progress","id":"…","note":"…"} | Report non-final tool progress. |
{"type":"tool_cancel","id":"…"} | Cancel tool work. |
{"type":"client_event","event":"playback_stopped",…} | Report actual speaker playback after an interruption. |
Playback obligation
Clients that play assistant audio must track queued and discarded audio. After interrupted, report how much audio was not heard:
{
"type": "client_event",
"event": "playback_stopped",
"remaining_ms": 150,
"discarded_ms": 420,
"barge_seq": 3
}
Advertise playback_pause_v1 in client.capabilities only if your player can hold and resume already-scheduled audio. Otherwise Converse uses immediate interruption events.
client.audio_frontend is optional diagnostic metadata describing the active microphone/AEC path; use unknown until it is known.
Echo barge_seq from the interruption. Converse may respond with a corrected utterance carrying the same sequence; replace the earlier assistant transcript for that interruption. The browser SDK handles this playback protocol automatically. Python and raw WebSocket clients must implement it when they perform real playback.
Client tools
Declare tools in mode.tools. Tools are available in Converse mode and may be combined with web_search. The model chooses whether to answer directly, search, or call one or more client tools.
"tools": [{
"name": "lookup_order",
"description": "Look up an order by its customer-visible ID.",
"parameters": {
"type": "object",
"properties": { "order_id": { "type": "string" } },
"required": ["order_id"]
},
"read_only": true,
"requires_permission": false,
"timeout": 30
}]
| Field | Default | Contract |
|---|---|---|
name | Required | Unique, non-empty tool name. |
description | "" | Tells the model when and how to use the tool. |
parameters | Empty object schema | JSON Schema for args. |
read_only | false | true lets Converse start the call early for speed. Use it only for harmless, cheap lookups. Leave it false for anything that changes data, sends something, spends meaningful money or accesses sensitive data. |
requires_permission | false | Hold the exact call until the user clearly approves it. Converse asks naturally, verifies the reply and executes nothing when approval or scope is unclear. |
timeout | 30 seconds | Result deadline; minimum 1 second, maximum 120 seconds. |
When requires_permission is true, the first call is held inside Converse and is not sent to your host. A clear approval releases the original name and arguments exactly once; refusal discards it; ambiguity remains pending for clarification. Changed arguments create a new permission request. Pending permission IDs are one-time, session-scoped and expire after five minutes by default. Permission questions and acknowledgements are generated naturally from the conversation.
Converse calls the host:
{"type":"tool_call","id":"turn3-fc1","name":"lookup_order","args":{"order_id":"A123"}}
Complete exactly once with a result or client cancellation:
{"type":"tool_result","id":"turn3-fc1","content":{"speak":"The order shipped.","data":{"status":"shipped"},"handle":"order-A123"}}
{"type":"tool_cancel","id":"turn3-fc1"}
For longer work, progress does not resolve the call or interrupt playback:
{"type":"tool_progress","id":"turn3-fc1","note":"checking the carrier"}
- Result
contentis limited to 16 KiB of compact UTF-8 JSON by default. Oversized results still resolve, but Converse replaces them with bounded content containingtool_result_truncated,original_bytesand a preview. - Progress notes are limited to 500 characters and 12 notes per call.
- A server
tool_cancelasks the host to stop promptly because the result is no longer usable. - Barge-in never cancels tool work. It stops the spoken reply; the tool may continue and its result remains available to the next turn. If users need to stop work, expose a separate effectful stop tool whose description tells the model when to use it.
- Keep verbose logs and artifacts in your own system. Return a short spoken summary, structured data and, when useful, a handle or URL.
Errors, reconnects and limits
detail | What to do |
|---|---|
unauthorized | Replace a missing, unknown, expired or revoked credential. |
invalid session_id | Use a safe non-empty identifier and match the scoped credential. |
insufficient credit | Add credit in API & Billing. |
too many concurrent sessions | Close the existing session or wait for it to end. |
server busy — try again shortly | Retry with exponential backoff. |
server restarting — try again shortly | Retry shortly. |
voice pipeline unavailable — try again shortly | Retry with backoff and surface a temporary-service message. |
- One concurrent session per account by default.
- Each connection is capped at two hours.
- Billing is $3.00 per connected hour, metered per second with partial seconds rounded up.
- An abnormal browser transport loss is retried automatically; the new connection starts a new conversation.
- A clean server close ends the session and is not automatically reconnected.
To validate a key without opening a billable session, connect and send {"type":"auth","api_key":"ck_…"}. A valid key receives {"type":"ok"} and the socket closes.
Platform support
| Platform | Status | What you provide |
|---|---|---|
| Desktop Chrome / Edge | Recommended and production validated | Browser SDK and scoped credential route. |
| Desktop Firefox | Protocol support; live validation pending | Browser SDK and scoped credential route. |
| Safari / iOS WebKit | Not yet a supported production target | Contact us before committing to this path. |
| Python service / telephony / custom hardware | Supported headless transport | Capture, pacing, playback and echo cancellation. |
| Raw WebSocket | Supported advanced integration | The complete media and session lifecycle. |
| Native desktop / mobile SDKs | Planned | Not available yet. |