invocations_ws WebSocket protocol. This article shows you how to choose a voice framework, expose the WebSocket endpoint from your container, and connect a client.
For background on hosted agents and the available protocols, see What are hosted agents?. For general container packaging and deployment steps, see Deploy a hosted agent.
When to use the WebSocket protocol
Real-time voice agents need bidirectional streaming: the client and the agent send and receive audio simultaneously over a persistent connection. Theinvocations_ws protocol provides a single full-duplex WebSocket between the caller and your container, with text and binary frames relayed end-to-end.
Use invocations_ws when you need to:
- Stream microphone audio (for example, 20 ms PCM frames at 16 kHz) to the agent and stream synthesized speech back.
- Run a speech-to-speech or cascaded speech pipeline (STT → LLM → TTS) inside the container.
- Carry interleaved control messages (JSON) and media (binary) on the same connection.
- Use WebSocket signaling to set up a WebRTC media connection that your application manages.
- Bridge a telephony provider (for example, Twilio) that streams call audio over WebSocket.
/invocations or /responses routes. A single container can expose all three protocols at the same time.
Endpoint and frame semantics
The container exposes one WebSocket route:/invocations shape; api-version is a required query parameter, and agent_session_id is optional):
<project> and <agent> path segments and the api-version query parameter at the APIM and Agents-service layers to route the upgrade. They don’t appear on the upgrade the container receives. Any other query parameters you add are forwarded unchanged.
The platform proxies the WebSocket upgrade transparently. Frames flow between the caller and your container as raw bytes—the platform doesn’t parse, transform, or buffer them at the application layer.
Frame size limit. The platform proxy enforces a 1 MB maximum frame size. Frames larger than 1 MB are rejected with WebSocket close code
1009. For audio, 20 ms PCM frames at 16 kHz mono (~640 bytes) are well under the limit.
Session resolution. The caller can pass ?agent_session_id=<id> on the upgrade URL. Inside the container, read FOUNDRY_AGENT_SESSION_ID from the environment, or fall back to the query parameter. If neither is set, generate your own UUID.
Authentication. Callers present a Microsoft Entra bearer token on the Authorization header during the upgrade. APIM and the Agents service validate the token; the container does not see it. Don’t depend on an Authorization header reaching /invocations_ws, and don’t accept an authorization query parameter.
Connection lifecycle
- Open. The caller sends
GET /invocations_wswith WebSocket upgrade headers. The platform resolves the session and version, proxies the upgrade, and the container responds101 Switching Protocols. - Exchange. Frames flow in both directions until either side initiates close.
- Close. Either side sends a Close frame; the peer echoes a Close frame and shuts down its send side.
- Abnormal close. If the underlying TCP connection drops, the peer observes close code
1006with no Close frame.
Maximum connection duration
The platform recycles infrastructure on a rolling basis with a shutdown grace period of 30 minutes. Individual WebSocket connections are capped at approximately 30 minutes. When the platform initiates shutdown, it sends close code1001 (going away). Clients must be prepared to reconnect with the same agent_session_id. The sandbox (and any in-process container state) persists across reconnects. The platform doesn’t replay missed frames; your container is responsible for any application-level resume protocol.
Close codes
Implement the WebSocket handler
Add the/invocations_ws route to your container using the same azure-ai-agentserver-invocations host that serves the HTTP /invocations route. The host exposes two decorators:
You can register one or both on the same
app object. The host calls await websocket.accept() before invoking your @app.ws_handler, runs Ping/Pong keep-alive (default 30 s), maps uncaught exceptions to close code 1011, and emits the structured close event and metrics listed in Observability.
/readiness endpoint, OTLP export, graceful shutdown, and the x-platform-server identity header are inherited from azure-ai-agentserver-core—you don’t need to wire them up yourself.
Your container should:
- Handle text and binary frames; honor continuation frames per RFC 6455.
- Keep frames at or below 1 MB.
- Persist session-relevant state so a client can reattach via the same
agent_session_id. - Propagate
traceparent,tracestate, andbaggagefrom the upgrade request as the parent context for any spans the connection emits.
invocations_ws voice agent samples.
Choose a voice framework
Hosted agents support any containerized voice framework. The following frameworks have validated samples:Voice pipeline architectures
You can run either pipeline style inside your container:- Cascaded (STT → LLM → TTS). Separate models for each stage. Use any text model from the Foundry model catalog and any TTS voice. Best for multilingual support and custom voices.
- Speech-to-speech. Realtime models such as GPT-4o Realtime handle audio in and audio out in a single model. Best for natural conversational dynamics (interruptions, backchanneling) where latency is critical.
Deploy a voice agent
Voice agents follow the same deployment flow as any hosted agent. The only difference is declaring theinvocations_ws protocol on the agent version.
Declare the protocol
When you create the agent version, includeinvocations_ws in protocol_versions. You can declare it alone or alongside responses and invocations.
Connect a client
Browser clients use the W3C WebSocket API. Other callers use standard libraries such as Pythonwebsockets or aiohttp. There’s no separate client SDK.
Use WebRTC media with WebSocket signaling
Some voice agents use WebRTC for browser-to-agent audio media because WebRTC handles packet loss, jitter buffering, and real-time audio transport well. Hosted agents don’t provide a managed WebRTC media service, TURN service, SFU, or WebRTC signaling protocol. Instead, useinvocations_ws as the authenticated signaling channel, and implement the WebRTC media path in your client and container.
A typical WebRTC pattern works like this:
- The browser opens an authenticated
invocations_wsconnection to the hosted agent. - The browser sends signaling messages as text frames, such as an ICE configuration request, SDP offer, and ICE candidates.
- The container creates or updates its WebRTC peer connection and responds with an SDP answer and candidate status messages.
- Audio media flows over the WebRTC peer connection. The WebSocket remains available for signaling, lifecycle events, and application control messages.
- Your application provides the TURN relay configuration and handles any WebRTC-specific reconnection or resume behavior.
/invocations_ws for actions such as ice_config, offer, ice_candidate, and disconnect. Audio media doesn’t use the WebSocket in that pattern; it flows over the WebRTC peer connection negotiated through the WebSocket.
Use this pattern when you want WebRTC media behavior in a browser or mobile client and are prepared to operate the client-side and server-side WebRTC stack. Use direct WebSocket audio streaming when you want a simpler transport, especially for prototypes, telephony bridges, or controlled networks.
For a complete implementation, see the Pipecat WebRTC sample.
Use Foundry models and tools
Voice agents have native access to the Foundry ecosystem. The agent container authenticates with its dedicated Microsoft Entra agent identity—no API keys or connection strings in your code.- Realtime models. GPT-4o Realtime and GPT Realtime for speech-to-speech pipelines.
- Text models. GPT-4o, GPT-4.1, and the GPT-5 series for cascaded pipelines.
- Speech models. Azure AI Speech for STT and TTS.
- Tools. Access Foundry-managed tools (Web Search, File Search, Code Interpreter, Azure AI Search, custom MCP servers, A2A) through the Toolbox MCP endpoint in your Foundry project. See Curate intent-based toolbox in Foundry.
Observability
The/invocations_ws upgrade and per-connection lifecycle should be instrumented with distributed trace spans, following the OpenTelemetry GenAI conventions used by the HTTP /invocations protocol.
Propagate traceparent, tracestate, and baggage from the upgrade request as the parent context for any spans emitted during the connection’s lifetime.
Recommended metrics to emit:
Traces and metrics appear in the linked Application Insights resource alongside model and tool invocation traces.
Limits and considerations
The platform doesn’t replay missed frames. Your container is responsible for any application-level resume protocol.
Telephony integration
To connect a traditional phone-based agent, use a telephony provider (for example, Azure Communication Services or Twilio) that bridges PSTN calls to your hosted agent’sinvocations_ws endpoint. The telephony provider handles SIP signaling, media transcoding, and DTMF processing.