Pipeline Socket
The engine exposes real-time pipeline communication over three socket transports:
| Transport | Engine Port | Endpoint | Notes |
|---|---|---|---|
Socket.IO |
9011 |
|
Two events carry all traffic: |
Plain WebSocket |
9010 |
|
Text frames carry |
Twilio WebSocket |
9010 |
|
Twilio Media Streams JSON protocol (events: |
The {key} path segment identifies the agent/pipeline configuration — see
The Pipeline Key. On the Socket.IO transport it is passed as the
key handshake query parameter instead.
In a deployed environment both listeners are reachable on the deployment host over TLS: the
reverse proxy routes /socket/io/ and /socket.io/ to the Socket.IO listener and everything
else, including /socket/pipeline/ and /socket/twilio/, to the HTTP listener. The port
numbers above therefore only apply to a locally running engine.
A fourth, non-socket transport runs a conversation over a plain HTTP request — see HTTP Pipeline Channel.
Pipeline Configuration
All parameters can be supplied either as socket URL query parameters or as HTTP request headers. When both are present the query parameter takes precedence.
| Query Parameter | HTTP Header | Default | Description |
|---|---|---|---|
|
— |
(auto-generated UUID) |
Reuse an existing session by its UUID. If omitted a new session ID is generated. |
|
|
|
BCP 47 language tag(s) for the session (e.g. |
|
|
|
IANA time-zone identifier used for time-aware responses (e.g. |
|
|
(session ID) |
Stable device identifier. Allows the pipeline to associate multiple sessions with the same physical device. |
|
|
— |
Client device category. One of: |
|
|
|
Wire format for messages sent by the client. |
|
|
|
Wire format for messages sent by the pipeline. |
|
|
|
Output protocol version. Affects the JSON type name of some output elements; keep |
|
|
|
Audio input mode. |
|
|
|
Sample rate (Hz) of the raw audio sent by the client. |
|
|
|
Sample rate (Hz) requested for synthesized speech chunks. |
|
|
— |
Maximum size in bytes of each |
|
|
— |
Output audio container/codec type (e.g. |
|
|
|
Encoding of the raw audio sent by the client, also used when handing the audio to speech
recognition. One of: |
|
|
|
Enable server-side output speech processing using Audio2Face. Set to |
|
|
|
When |
|
|
|
When |
|
|
|
When |
|
|
|
Enables test mode marking all data like turns and LLM logs as testing (should be set to |
|
|
|
When |
|
|
|
Enable TTS audio caching, so repeated utterances are not synthesized again. Set to |
|
|
— |
Milliseconds of client audio to discard right after a turn ends. Prevents the agent from hearing the tail of its own speech through an open microphone. |
|
|
— |
Discard audio bursts shorter than this many milliseconds, suppressing clicks and other noise. |
|
|
— |
UUID of a stored realtime (speech-to-speech) configuration to run the session with, overriding the agent’s own setting. |
|
|
— |
Caller-defined reference stored on the session, for correlating it with a record in your system. |
|
|
— |
Used by automated testing only: ref of the agent under test when this session drives another agent. |
|
— |
— |
Reference identifier of the visual avatar to use for this session (can be used to enforce specific server-side avatar rendering - e.g. using LiveAvatar.com). |
|
|
— |
JWT bearer token. Alternatively passed as a standard |
Message Formats
All socket transports support three wire formats, selected per connection and independently for
each direction via inputFormat and outputFormat.
| Format | Description |
|---|---|
|
Human-readable command strings.
Commands use the |
|
Full JSON serialization of the |
|
The same object model encoded with MessagePack and exchanged as binary payloads. The most compact option, used by the mobile clients. |
The examples throughout this page show the TEXT and JSON forms. The complete encoding rules
of all three formats, together with the element type reference, are in
Wire Formats.
Typical Communication Flow
The table below shows the complete lifecycle of a session, from connection open through session end.
| Phase | Client | Engine / Interaction Pipeline |
|---|---|---|
Session Start (Preconnect) |
Client emits TEXT #ready JSON
|
Pipeline emits TEXT #ready JSON
|
Agent Introduction (optional) |
Client triggers the intro greeting by sending action TEXT #intro JSON
Note: client can directly proceed with audio or text input if user is starting interaction (e.g. by text input What’s the weather?) |
Pipeline streams the agent’s spoken introduction as |
Audio Input |
Client sends raw audio as binary WebSocket frames (or TEXT (Socket.IO / text-only transport) #binary:UklGRiQAAABXQVZFZm10IBAAAA... JSON
|
Pipeline sends interim Depending on the upstream model, Interim The pipeline may also indicate "barge-in", the detection of user starting to speak, with an empty transcript containing only a dot. TEXT — interim transcript #transcript:text=hel&isInterim=true JSON — interim transcript
Pipeline emits the final TEXT — final transcript #transcript:text=Hello, how can I help you today?&isInterim=false JSON
TEXT — speech reply chunk #speech-item:{"provider":"google","sampleRate":24000,"frameRate":0,\
"isLast":false,"blendShapeWeights":[],"visemes":[],\
"bytes":"<base64-encoded-PCM>","isRawAudio":true,\
"created":"2024-03-25T12:00:01Z"}
JSON
|
Text Input |
Client sends one or more token messages.
The final token must end with a sentence separator ( TEXT — single token What time is it? TEXT — multi-token (last token closes the sentence) What time is it? JSON
|
Pipeline emits a final TEXT #transcript:text=What time is it?&isInterim=false JSON
|
Turn End |
After the last speech chunk the pipeline signals the end of the turn with #exit JSON
|
|
Session End by Agent |
Before TEXT #sessionShouldEnd #exit JSON — session-should-end
|
|
Client acknowledges the session end by sending TEXT #end JSON
|
The connection stays open while the pipeline runs post-session operations (evaluation and
webhooks); it closes once they finish. Depending on what is configured for the project and agent,
an |
|
Session End by Client |
Client initiates session end at any time by sending IT IS STRONGLY RECOMMENDED TO USE SEND ACTION TEXT #end JSON
|
Input Elements
Input elements are messages sent from the client to the pipeline.
Text Token (plain text or command trigger)
TEXT
Hello, what's the weather today?
TEXT (pipeline-defined action such as #intro)
#intro
JSON
{"type": "token", "text": "Hello, what's the weather today?"}
JSON
{"type": "action", "name": "intro"}
Transcript (client-side STT result)
Used when the client performs its own speech recognition and sends the result to the pipeline.
TEXT — interim
#transcript:text=what's the weath&isInterim=true
TEXT — final (a sentence separator is appended automatically if missing)
#transcript:text=What's the weather today?&isInterim=false
JSON — final
{
"type": "transcript",
"text": "What's the weather today?",
"isInterim": false,
"isSynthetic": false,
"isAsynchronous": false,
"provider": "Client"
}
Binary (raw audio)
Send audio to let the pipeline perform server-side speech recognition.
WebSocket — send a binary frame containing raw audio bytes (no text prefix needed).
TEXT (Socket.IO or text-only transports) — base64-encoded audio:
#binary:UklGRiQAAABXQVZFZm10IBAAAA...
JSON
{"type": "binary", "bytes": "UklGRiQAAABXQVZFZm10IBAAAA...", "contentType": "audio/raw"}
URL
Pass a URL resource into the pipeline (e.g. for multimodal processing). The only supported content type is an image and is only supported on OpenAiRealtime.
TEXT
#url:https://example.com/image.png
JSON
{"type": "url", "url": "https://example.com/image.png"}
Commit
Explicitly commit the current turn input (flush accumulated input in pipeline PTT mode).
TEXT
#commit
JSON
{"type": "commit"}
Output Elements
Output elements are messages sent from the pipeline to the client.
Command
Generic pipeline command carrying a name and optional key=value parameters.
TEXT — no parameters
#ready
TEXT — with parameters
#transcript:text=Hello there.&isInterim=false
JSON
{
"type": "command",
"sessionId": "00000000-0000-0000-0000-000000000001",
"turnId": "00000000-0000-0000-0000-000000000001",
"name": "transcript",
"parameters": {
"text": "Hello there.",
"isInterim": "false"
}
}
Common command names:
| Name | Description |
|---|---|
|
Session initialized; client may now send input. |
|
STT result (interim or final). Parameters: |
|
The session is ending after this turn. The client should send |
|
Current turn completed; pipeline is ready for the next user input. |
|
An error occurred. See Wire Formats for the error fields. The connection is closed immediately after. |
Speech Item
An audio chunk of the agent’s synthesized reply.
Multiple chunks are emitted per turn; the last one has isLast: true.
TEXT
#speech-item:{"provider":"elevenlabs","sampleRate":44100,"frameRate":0,\
"isLast":true,"blendShapeWeights":[],"visemes":[],\
"bytes":"<base64-encoded-PCM>","isRawAudio":true,\
"created":"2024-03-25T12:00:02Z"}
JSON
{
"type": "speech-item",
"sessionId": "00000000-0000-0000-0000-000000000001",
"turnId": "00000000-0000-0000-0000-000000000001",
"item": {
"provider": "elevenlabs",
"sampleRate": 44100,
"frameRate": 0,
"isLast": true,
"blendShapeWeights": [],
"visemes": [],
"bytes": "<base64-encoded-PCM>",
"isRawAudio": true,
"created": "2024-03-25T12:00:02Z"
}
}
visemes contains lip-sync timing data when produced by a supporting TTS provider (e.g. Azure).
blendShapeWeights carries per-frame facial blend shape data for 3D avatar animation.
Visual State
Updates the client’s UI state (e.g. background, overlay, avatar pose).
TEXT
#visual-state:{emotions={boredom=0.357666015625, contemplation=0.2357177734375, calmness=0.2235107421875}, reflectiveStates={}, signals=[userNotSpeaking])}
JSON
{
"type": "visual-state",
"sessionId": "00000000-0000-0000-0000-000000000001",
"turnId": "00000000-0000-0000-0000-000000000001",
"state": {
"emotions": {
"boredom": 0.357666015625,
"contemplation": 0.2357177734375,
"calmness": 0.2235107421875
},
"reflectiveStates": {},
"signals": [ "userNotSpeaking" ]
}
}
Multimodal Interaction
Triggers a multimodal display element (image, video, form, etc.) on the client.
TEXT
#multimodal-interaction:{"ref":"product-card","data":{"title":"Widget X","price":49.99}}
JSON
{
"type": "MultimodalInteractionElement",
"sessionId": "00000000-0000-0000-0000-000000000001",
"turnId": "00000000-0000-0000-0000-000000000001",
"interaction": {
"ref": "product-card",
"data": {"title": "Widget X", "price": 49.99}
}
}
Navigation Specification
Announces that a navigation entry has just been unlocked for the user. Emitted when an evaluation
satisfies the entry’s condition, and carries the same object the project payload uses — see
Navigation API. Match it to the client’s stored
navigation by ref: replace the entry when the ref is known, insert it when it is not.
turnId is always null, and the delivered entry always arrives unlocked — its
disabledMessage is null.
TEXT
#navigation-specification:{"type":"route","ref":"onboardingAssistant",\
"parentRef":"assistants","image":null,"name":"Onboarding assistant",\
"description":"Starts a conversation with the onboarding assistant.","order":2,\
"disabledMessage":null,"route":"/a/onboardingAssistant"}
JSON
{
"type": "navigation-specification",
"sessionId": "00000000-0000-0000-0000-000000000001",
"turnId": null,
"time": 1774000000000,
"specification": {
"type": "route",
"ref": "onboardingAssistant",
"parentRef": "assistants",
"image": null,
"name": "Onboarding assistant",
"description": "Starts a conversation with the onboarding assistant.",
"order": 2,
"disabledMessage": null,
"route": "/a/onboardingAssistant"
}
}
Output Token
A streamed text token from the language model (used when streaming LLM output directly to the client).
TEXT
Hello
JSON
{
"type": "token",
"sessionId": "00000000-0000-0000-0000-000000000001",
"turnId": "00000000-0000-0000-0000-000000000001",
"text": "Hello"
}
Error
TEXT
#error:session.id=00000000-0000-0000-0000-000000000001&source=Socket&type=CommunicationException$Socket&message=Emitting input to pipeline failed&description=null&isRecoverable=false
JSON
{
"type": "error",
"sessionId": "00000000-0000-0000-0000-000000000001",
"turnId": null,
"source": "Socket",
"message": "Emitting input to pipeline failed",
"description": null,
"isRecoverable": false
}
The connection is closed by the server immediately after an error is emitted.