Realtime frames

The WebSocket and SSE wire format between the SDK and the runtime, including auth, replay, switch, and close codes.

Endpoint wss://api.kletso.ai/v1/realtime, subprotocol kletso.v1. The first frame must be auth; the token never goes in the URL. Frames are JSON objects discriminated by t, at most 256 KB.

Client → server

tFieldsNotes
authtoken (kst_…), conversationId?, after? (default 0)Without a conversation the socket attaches to the user (notifications, conversation.created); with one, the runtime replays events with seq > after
messageclientId, text?, value?A user turn; clientId deduplicates retries
actionsurfaceId, componentId, actionId, clientId, value?A surface interaction (agent, submit {formId, values}, confirm {toolCallId, approve})
contextmerge? or replace?Update the session context
trackname, properties?Silent app event; evaluated against rules. The SDK sends kletso.chat_opened { conversationId, messages, userMessages, presentation } itself when the chat opens
screennameSilent screen view; evaluated against rules
switchconversationId, after?Re-attach to another conversation; the runtime answers with a fresh ready and replay
typingReserved
pingHeartbeat

Server → client

tFields
readyseq, conversationId?
eventevent: a kletso.events/v1 envelope
pong
errorcode, message, retryable?, retryAfterMs?

Example exchange:

→ { "t": "auth", "token": "kst_…", "conversationId": "conv_01J8DEMO000001", "after": 41 }
← { "t": "ready", "seq": 41, "conversationId": "conv_01J8DEMO000001" }
→ { "t": "message", "text": "I need a flight to Osaka", "clientId": "c_01J8CLIENT0002" }
← { "t": "event", "event": { "seq": 42, "type": "message.created", "data": { "role": "user", … } } }
← { "t": "event", "event": { "seq": 43, "type": "agent.typing", "data": {} } }
← { "t": "event", "event": { "seq": 44, "type": "tool.started", "data": { "name": "search_flights", … } } }

Close codes

CodeMeaningClient behaviour
1000normalnone
1001going away (deploy, tab closed)reconnect with backoff
4000heartbeat timeout (client-initiated)reconnect
4401auth failed or session revoked; also sent when no auth arrives within 10 sstop; do not retry with the same token
4403token expiredrefresh the session, then reconnect

SSE alternative

GET /v1/conversations/:id/events?after=N&stream=1 with Accept: text/event-stream and the session token. The stream sends event: ready, then event: event lines carrying envelopes (with id: <seq>), keepalive comments every 20 seconds, and event: error. Outbound frames become REST calls (/messages, /actions, /context, /events). SSE needs an existing conversation.

Last updated 2026-09-28 · Report an issue with this page