Skip to main content
The Telnyx Assistant Conversation WebSocket speaks a wire format intentionally close to the OpenAI Realtime API over WebSockets: JSON frames with a type field, base64 PCM16 audio in input_audio_buffer.append, assistant speech in response.output_audio.delta, and familiar event names throughout. Most migrations are a matter of changing the URL, moving session configuration onto the assistant, and deleting client code that Telnyx makes unnecessary. The one architectural shift to internalize before touching code:
With OpenAI, the socket is the product: you configure the session, manage the conversation, and request every response. With Telnyx, the AI Assistant is the product: instructions, model, voice, and tools live on the assistant, and the assistant owns turn-taking. The socket only carries the conversation.
This makes the Telnyx client simpler than the OpenAI client it replaces — most of the migration is deleting code.

Before you start

Create and configure an AI Assistant in the Portal (or via the Assistants API — see Assistants API in the sidebar). Everything you used to send in session.update becomes assistant configuration:
Nothing can be reconfigured over the socket mid-conversation — there is no session.update frame. If your application changes instructions or tools mid-session today, restructure that into assistant configuration (dynamic variables, memory) before migrating.

Connection and authentication

Audio is PCM16-only in both directions (g711_ulaw/g711_alaw are not available over this WebSocket). Input sample rate is one of 8000, 16000, 24000, 44100, 48000 Hz (default 16000). The output rate is determined by the assistant’s voice — read it from session.created instead of assuming 24 kHz:

Event mapping

Client → server frames

Server → client frames

Turn-taking: delete your response orchestration

On OpenAI, a manual-VAD or push-to-talk client drives the conversation: appendcommitresponse.create. On Telnyx the server drives it — you stream audio continuously and turns happen:
Consequences to plan for:
  • Turn detection is always server_vad. You cannot disable it (turn_detection: null) or use semantic VAD. Push-to-talk UIs still work — only send audio while the button is held — but the turn boundary is still decided by server VAD, tuned via Interruption Settings.
  • Automatic responses cannot be turned off. There is no create_response: false mode where you inspect the transcript before allowing a reply.
  • Text turns need no trigger. conversation.item.create with input_text gets an automatic spoken response — do not follow it with response.create.

Interruption handling

Barge-in is automatic: when the user speaks over the assistant, Telnyx cancels the response (final response.done has status: "cancelled") and starts a new turn. Your OpenAI truncation bookkeeping — tracking item_id, measuring played milliseconds, sending conversation.item.truncate — has no Telnyx equivalent and should be deleted. Keep exactly one client-side behavior: flush locally queued audio when speech starts.

Function calling

Tool definitions move from session.update payloads to the assistant’s tool configuration. At runtime, two OpenAI patterns collapse into one Telnyx pattern:
  • Tools your backend served (the common OpenAI pattern) usually become webhook or MCP tools: Telnyx calls your endpoint directly and the socket only shows informational response.tool_call.started / .completed frames. Your client-side function-calling code is deleted entirely.
  • Tools that must run in your client process become client-side tools. The round-trip resembles OpenAI’s, with two changes: the request arrives as a single conversation.item.created frame with complete arguments (no function_call_arguments.delta streaming, no digging through response.done output), and you don’t send response.create after the output.

OpenAI features without a Telnyx equivalent

Audit your application for these before migrating — they are not available over the Assistant Conversation WebSocket today:
  • Session reconfiguration — no session.update; configuration is fixed for the life of the connection.
  • Manual turn control — no turn_detection: null, create_response: false, input_audio_buffer.commit/.clear, or semantic VAD.
  • Out-of-band responses and custom context — no response.create, so no conversation: "none", per-response input arrays, response metadata, or per-response overrides (voice, modality, max_output_tokens).
  • Text-only output — responses are always spoken; use the transcript deltas for text. (For a pure text channel, use the Assistants chat API instead — see Assistants API in the sidebar.)
  • Conversation item manipulation — no conversation.item.truncate, .retrieve, or .delete, and no assistant-message injection into history.
  • Image inputinput_image content is not supported; conversation.item.create accepts input_text and function_call_output items only (anything else is rejected with invalid_item).
  • G.711 audio — PCM16 only, in both directions.
  • Rate-limit telemetry — no rate_limits.updated frames.
If one of these is load-bearing for your application, talk to your Telnyx point of contact before scheduling the migration.

Migration checklist

  1. Create an assistant and move session.update contents into its configuration (instructions, model, voice, tools, transcription, interruption).
  2. Swap the URL and API key; pick input_sample_rate via query parameter.
  3. Read the output sample rate from session.created instead of assuming 24 kHz.
  4. Delete: session.update, response.create, input_audio_buffer.commit/.clear, conversation.item.truncate, and truncation bookkeeping.
  5. Rewire function calling: backend tools → webhook/MCP tools (delete client code); in-client tools → handle conversation.item.created function_call items.
  6. Keep: audio append loop, playback-flush on speech_started, response.cancel for programmatic interrupts, transcript rendering from .delta frames.
  7. Update error handling to the Telnyx error codes, and treat a reconnect as a new conversation.
  8. Test barge-in, tool calls, and long-silence behavior (session_idle_timeout) end to end.

Learn more