Skip to main content
wss://silk-api.rumik.ai/v1/agent/connect?token=<access_token> a bidirectional json socket: you send microphone audio, the agent sends its audio back, plus events telling you when it starts and stops speaking. no webrtc, no SDK, no ICE — if your platform can open a websocket and move audio buffers, it can run an agent.

connect

mint a token with /v1/register-call, then open the socket with it. the token is single-use.
the call starts when the socket connects — that is the moment billing and concurrency begin, not when you registered.

audio format

both directions carry base64-encoded raw pcm:
24 kHz is fixed for this version. send whatever frame size is convenient — 20 ms is what we recommend and what we emit — but resample to 24 kHz before sending, and expect 24 kHz back.

lifecycle

1

connect

open the socket with your wct_ token.
2

wait for session.created

the first frame is always session.created. do not send audio before it — the agent is not in the room yet.
3

stream both ways

send input_audio_buffer.append continuously; read output_audio.delta and play it. voice activity and turn-taking are handled for you.
4

close

send session.close, or just close the socket. you get session.closed with a reason, then a normal close.

events you receive

object
the call is live. carries session_id, call_id, sample_rate and channels. call_id is the id register-call already gave you — what appears in conversations and your usage, and what your tools receive as {call_id}.
object
one 20 ms chunk of the agent’s speech, base64 pcm. play these back-to-back.
object
speech boundaries, with an ISO-8601 timestamp. useful for driving an animation or a “speaking” indicator.
object
the caller started speaking over the agent. a good cue to flush whatever audio you have buffered for playback.
object
what was said, with role (user or assistant) and text. transcript is a settled turn; transcript.delta is the turn so far.
object
the call is over, with a reasonclient_requested, ended, max_duration or error. the socket closes immediately after.
object
something went wrong, with a code and message. a malformed frame is reported and the call continues; a fatal one is followed by close 4000.
transcript, transcript.delta, agent_start_talking, agent_stop_talking and interruption are best-effort: treat them as enrichment, and never gate your audio pipeline on one arriving.

events you send

object
a chunk of microphone audio: { "type": "input_audio_buffer.append", "audio": "<base64 PCM>" }. send continuously while the caller talks. one frame may not exceed one second of audio.
object
marks the end of a turn. accepted for compatibility — the agent’s own voice activity detection decides turns, so you do not need it.
object
{ "type": "input_text.send", "text": "…" } — send text instead of speech.
object
end the call politely. you get session.closed back before the socket closes.

example

a complete call: register, connect, stream a microphone, play the reply.

connection errors

a failure before the call starts is still delivered on the socket: we accept the connection, send one error frame so you know why, and then close.
a 4000 close with concurrency_limit_exceeded is the socket equivalent of a 429. check /v1/agent/limits before connecting if you want to queue callers rather than turn them away.

ending and billing

the call ends when you send session.close, when the socket drops, when the agent hangs up, or when it hits the maximum session length. you are billed for the seconds it actually ran, and the transcript and recording appear in conversations shortly afterwards.