OpenAI Realtime engine: expose the WebSocket close code and reason to subclasses
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 35/100
Research direction
Start with livekit/agents/llm/_realtime/openai.py, especially the receive loop at lines 1176–1190, and inspect how _is_fatal_error classifies error events. Trace how the WebSocket close code and reason are discarded and how errors are retried; done means subclasses can use close details to classify fatal versus retryable closures. An open linked pull request (#8078) is already addressing this issue.
Written by the indexing model from the issue text.
Description
Feature Type
Would make my life easier
Feature Description
The shared OpenAI Realtime engine (livekit.agents.llm._realtime.openai) discards the WebSocket close code and reason. When the server closes the socket, _recv_task raises a generic, retryable APIConnectionError("… connection closed unexpectedly"), whatever the close frame said (openai.py#L1176-L1190).
OpenAI-compatible providers built on this engine often use close codes to signal that the session is over for good. For example, a provider closes with 4001 for bad credentials or 1008 for a policy violation, where reconnecting can't help. Since the code and reason are lost, the engine retries these until max_retry is used up, and a plugin can't tell a fatal close from a transient one.
It would help if the close code and reason were available to subclasses, for example:
- carried on the raised error (e.g.
APIConnectionError.body = {"code": ..., "reason": ...}), or - passed to an overridable hook such as
_on_ws_closed(code, reason) -> APIError, which decides whether the error is retryable.
Workarounds / Alternatives
The ElevenLabs realtime plugin in #8075 wraps the aiohttp WebSocket returned by _create_ws_conn to record the close frame's code and reason. Its _run_ws override then catches the APIConnectionError and raises a mapped APIError with the right retryable flag. It works, but it depends on internals of the receive loop, and every OpenAI-compatible provider would need to repeat it.
Additional Context
The same engine already lets subclasses classify errors that arrive as error events (_is_fatal_error). This would give close frames the same treatment.
🤖 Generated with Claude Code
- Dominant language
- Python
- Stars
- 14.6k
- Forks
- 3.9k
- Avg merge
- 3d 21h
- Merged PRs (30d)
- 197
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from livekit/agents
-
Assistant markup is stripped from chat history when expressive mode is offPossibly taken @ShivamSharma43 claimed this 15 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
docs: openai.LLM vs openai.responses.LLM for HTTP OpenAI-compat hostsMay be free again @AbarnaaSree claimed this 55 days ago, and no pull request is open. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
livekit/agents#7022 · 1 comment ·
Maintainers usually reply within 1 day
-
Anthropic plugin ignores parallel_tool_calls=False unless tool_choice is also setPossibly taken @sarankumar1325 claimed this today. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 30/100
Maintainers usually reply within 1 day
-
enhancement
Difficulty 4/5 3-5 days Newbie friendliness 38/100
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 55/100
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
aws-samples/sample-per-model-bedrock#464 ·
Maintainers usually reply within 1 day
-
lesson-submission pending-review
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
Ikalus1988/MisakaNet#3789 ·
Maintainers usually reply within 1 day
-
Python Volcengine provider returns failures instead of raising themPossibly taken @Ricardo-M-L claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
agent-infra/sandbox#248 ·
-
[Bug] cloud JSON directory loading assumes a Key field in fsspec listingsPossibly taken @Ricardo-M-L claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
hiyouga/LlamaFactory#10910 ·
Maintainers usually reply within 1 day
-
Bundled uv is never updated and trusts the compromised eMudhra certificatesPossibly taken @FabienDanieau claimed this today. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100