GET /v1/sessions/{id}.
A termination reason gives you the specific cause. Anam Lab shows it as a
chip on the sessions page only for the reasons
listed below. When a reason is not listed, the session shows its exit status
alone.
LiveKit
| Reason | Exit status | What it means |
|---|---|---|
Room closed (ROOM_CLOSED) | OK | The avatar left because the LiveKit room ended normally: the room was deleted or closed, the avatar participant was removed, or the disconnect was client initiated. This is the expected end when you delete the room or remove the avatar. If the room should still have been running, check what deleted it or removed the avatar participant. |
Room emptied (TIMEOUT_EMPTY_ROOM) | Timed out | Every regular participant left the LiveKit room and none rejoined within the departure timeout (10 seconds by default), so the avatar left too. Agent and egress participants do not count as occupants. This is the normal end when participants hang up. To allow longer reconnects, set a longer departure_timeout on the room; the avatar uses the room’s value when one is set. |
Nobody joined (TIMEOUT_INITIAL_JOIN) | Never joined | No regular participant joined the LiveKit room within 30 seconds of the session starting, so the session ended. Agent and egress participants do not count as occupants. Start the Anam session when a participant is about to join, or have the participant join first. A shorter empty_timeout on the room lowers this limit; it cannot raise it. |
Duplicate identity (livekit_duplicate_identity) | Client configuration error | LiveKit removed the avatar because another participant joined the room with the avatar’s identity. This usually means the session was started twice for the same room, or a participant identity or token was reused. Start one Anam session per room and give every participant a unique identity. |
Room not found (livekit_room_not_found) | Client configuration error | The avatar could not join because the LiveKit room named in its token does not exist: it was never created, was already closed, or the token’s room grant names a different room. Create the room (or let the first participant create it) before starting the Anam session, and check that the room name in the session request matches. |
Token rejected (livekit_auth_rejected) | Client configuration error | LiveKit rejected the token Anam was given for the avatar (HTTP 401 invalid authorization token), so the avatar could not join. The token was signed with an API key or secret that the LiveKit project behind the session’s LiveKit URL does not recognise, has expired, is malformed, or lacks a roomJoin grant. Mint the avatar token with the same API key and secret as that project, give it a roomJoin grant for the room, and check its expiry. |
Join forbidden (livekit_join_forbidden) | Client configuration error | The LiveKit endpoint refused the avatar’s join with HTTP 403 Forbidden. A self-hosted LiveKit server answers token and permission problems with 401, so a 403 usually comes from a reverse proxy, firewall, WAF, CDN, or hosting-provider policy in front of it that blocked Anam’s request: allow Anam’s requests to the LiveKit /rtc path, WebSocket upgrade included, on that layer. On LiveKit Cloud a 403 can also mean the project is pinned to regions Anam could not connect to; check the project’s region settings. |
Daily
| Reason | Exit status | What it means |
|---|---|---|
Room closed (ROOM_CLOSED) | OK | The last remote participant left the Daily room, so the avatar left too. Daily reports a deliberate leave and a dropped connection the same way, so this also covers a participant whose connection dropped. If sessions end while participants are still present, check that everyone joined the same room. |
Agora
| Reason | Exit status | What it means |
|---|---|---|
User left (USER_LEFT) | OK | The Agora session was closed without a more specific reason: the client ended it, or Anam tore the session down without a recorded cause. This is the normal end for an Agora session. If it happens sooner than expected, check whether your integration stops the session or the user leaves the channel. |
Turnkey
| Reason | Exit status | What it means |
|---|---|---|
User left (USER_LEFT) | OK | The client ended the session or its connection to Anam closed: the SDK stopped streaming, the page was closed, or the signalling WebSocket dropped and was not recovered. This is the normal end for a Turnkey session, and also the fallback recorded when the engine has no more specific reason. If it happens sooner than expected, check whether your integration stops the client or the user navigates away. |
Stopped via API (api_requested_stop) | OK | The session was force-terminated by a call to the stop-session endpoint (POST /v1/sessions/:id/stop). This is the expected end when your backend stops a session deliberately. If you did not expect it, check which of your services calls the stop endpoint. |
Client never connected (user_never_connected_to_websocket) | Never joined | The client never opened its signalling WebSocket within a minute of the session being created. This usually means the session token was created but the SDK never started streaming, or the client could not reach Anam. Check that your client starts streaming after obtaining the session token, and that the network allows WebSocket connections. |
WebRTC connection failed (user_never_established_webrtc_connection) | Never joined | The client opened its signalling WebSocket, but the WebRTC media connection was not established within a minute. Anam already falls back to a TURN relay over TLS on port 443, so a blocked UDP path alone is rarely the cause. This usually means the network also blocks outbound TLS to the TURN relay, or a browser policy or extension disables WebRTC. Check that the network allows WebRTC and outbound TLS on port 443, and test with the SDK’s iceTransportPolicy set to relay. |
No microphone audio (user_audio_never_received) | No microphone audio | The client established its WebRTC connection but never sent any microphone audio, so the session ended after about 20 seconds without input. This usually means the microphone permission prompt was denied or left unanswered, the microphone was muted or disabled with disableInputAudio before the session started, or no audio input device was available. Make sure the user grants microphone access before the session starts, and check the SDK’s microphone permission state. |
ElevenLabs Agents
| Reason | Exit status | What it means |
|---|---|---|
ElevenLabs agent configuration rejected (elevenlabs_agent_config_rejected) | Client configuration error | ElevenLabs closed the conversation (WebSocket 1008) because the session asked for something the agent’s settings do not allow, e.g. an override (prompt, first message, language, custom-LLM extra body) that the agent’s security settings block. Allow the override in the ElevenLabs agent’s security settings or stop sending it. |
ElevenLabs quota exceeded (elevenlabs_quota_exceeded) | Client configuration error | ElevenLabs refused the conversation because the ElevenLabs account behind the agent is over its quota (“This request exceeds your quota limit.”). Add credits or raise the plan on the ElevenLabs account. |
ElevenLabs custom LLM failed (elevenlabs_custom_llm_error) | Client configuration error | ElevenLabs ended the conversation because the custom LLM configured on the agent failed (“custom_llm_error: LLM Cascade Error”). Check the custom LLM endpoint, key and model on the ElevenLabs agent. |
ElevenLabs concurrency limit reached (elevenlabs_concurrency_limit_reached) | Client configuration error | ElevenLabs refused the conversation (close 4300) because the agent is already running its maximum number of concurrent conversations. Raise the agent’s concurrency limit on the ElevenLabs plan or start fewer sessions at once. |
ElevenLabs billing issue (elevenlabs_billing_issue) | Client configuration error | ElevenLabs refused the conversation because the ElevenLabs workspace behind the agent has an unresolved payment issue. Update the workspace’s billing on ElevenLabs. |
ElevenLabs signed URL rejected (elevenlabs_signed_url_rejected) | Client configuration error | ElevenLabs refused the conversation because the signed URL supplied for the agent was invalid or had expired. Generate a fresh signed URL for each session. |
ElevenLabs daily call limit reached (elevenlabs_daily_call_limit_reached) | Client configuration error | ElevenLabs refused the conversation (close 4300) because the agent has reached its daily call limit. Raise the agent’s daily limit on ElevenLabs or wait for it to reset. |
ElevenLabs guardrail triggered (elevenlabs_guardrail_triggered) | OK | A guardrail configured on the ElevenLabs agent stopped the conversation (WebSocket 1008). If it fires more often than expected, review the agent’s guardrail settings on ElevenLabs. |
ElevenLabs dynamic variables missing (elevenlabs_missing_dynamic_variables) | Client configuration error | ElevenLabs refused the conversation (WebSocket 1008) because the agent’s first message or tools use dynamic variables that the session did not provide. Pass every required variable in dynamicVariables in the session’s ElevenLabs agent settings, or give the variables defaults on the ElevenLabs agent. |
ElevenLabs LLM timed out (elevenlabs_llm_timeout) | Provider error | ElevenLabs ended the conversation because the language model on the ElevenLabs agent took too long to respond. If it recurs, check the ElevenLabs status page, or try a faster model or a shorter prompt on the agent. |
ElevenLabs server error (elevenlabs_server_error) | Provider error | ElevenLabs ended the conversation with an internal server error (WebSocket 1011). If it recurs, check the ElevenLabs status page. |
All integrations
| Reason | Exit status | What it means |
|---|---|---|
User asked to end (USER_REQUESTED_END) | OK | The persona ended the conversation with the end_call system tool after the user confirmed they wanted to finish. This is the expected end for personas that have the end_call tool attached. Remove the tool from the persona if you do not want the persona to end conversations. |
Anam duration limit (session_max_duration_reached) | Max duration reached | The session reached Anam’s platform-wide maximum session length, currently two hours, and was ended. This limit applies to every session regardless of persona settings. Start a new session to continue. |
User inactive (user_inactivity_timeout) | Timed out | The user stayed silent past the persona’s silenceBeforeSessionEndSeconds window (60 seconds by default), so the persona ended the session. A spoken warning precedes the end when the window is at least 10 seconds. Raise the window in the persona’s voice detection options, or set it to 0 to disable the automatic end. |
Related
LiveKit configuration
Configure LiveKit rooms, credentials, and avatar sessions.
Session performance
Understand the latency indicators shown for your sessions.
Get a session
Retrieve a session’s exit status and other details through the API.

