steep-balloon-41261
12/22/2025, 4:11 PMtall-airline-16756
12/22/2025, 4:11 PMtall-airline-16756
12/22/2025, 4:11 PMchat_ctx directly from an AgentSession. The session does not hold the chat context; the Agent does. Fix any access like session.chat_ctx to session.agent.chat_ctx or self.chat_ctx inside the Agent.
◦ If you need to modify context programmatically, call agent.update_chat_ctx(...) (or use session.agent.chat_ctx) after ensuring the Agent is initialized.
◦ Add a defensive check during shutdown to avoid accessing context after the Agent has been torn down.
• The "worker connection closed unexpectedly" warnings show the worker’s websocket to <wss://dpi-kccd98ec.livekit.cloud> is being closed and then the worker re-registers. Common causes:
◦ Network/firewall blocking or intermittent connectivity.
◦ Worker crash or overload causing abrupt close.
◦ Server-side timeout/auth issue or region-specific routing problems.
• TTS logs: one TTS attempt returned ttfb=-1.0 (failed/aborted), later one succeeded but with high TTFB (~13s). That points to occasional TTS service latency or interruptions.
Actionable next steps (please try and tell me results)
1. Search code for any session.chat_ctx usage and change to session.agent.chat_ctx or access via the Agent instance. If you’d like, paste the small snippet that accesses chat context and I’ll show the exact fix.
2. Ensure agents are fully initialized before session code touches chat context (verify session.start(agent=...) or equivalent is completed).
3. Add a try/except around context access during shutdown to avoid the race condition.
4. For the websocket disconnects:
◦ Verify network allows outbound WebSocket to the LiveKit host and there are no intermittent drops.
◦ Check worker logs around the disconnect for any crash/exception prior to the close.
◦ Confirm worker tokens/credentials haven’t expired.
◦ If you suspect region/routing, try running a worker in another region near your users.
1. For TTS latency, check the TTS provider health in the same timeframe and retry with a smaller payload to reproduce.
If you want, share:
• The code snippet where chat context is accessed (lines around session use).
• The worker logs just before a disconnect (to see if the worker crashed).
With one of those I can give the exact code change or point to the precise log cause.
Sources: Agent session | LiveKit docs | Agents (Python) | livekit/livekit_composite | DeepWiki | Agents (Node.js) | livekit/livekit_composite | DeepWikimost-vr-18651
12/22/2025, 4:13 PMtall-airline-16756
12/22/2025, 4:14 PMawait agent.save_chat_history(session.chat_ctx) during shutdown, but AgentSession does not expose chat_ctx. The chat context lives on the Agent (or inside the Agent instance), so accessing it from session causes the error when the session is torn down.
Simple fixes (pick one)
1) Use the Agent’s context directly
• Pass the Agent instance to save_chat_history:
await agent.save_chat_history(agent.chat_ctx)
2) Access session.agent.chat_ctx (if session.agent is guaranteed)
• Safer if you prefer to reference the session:
if getattr(session, "agent", None):
await agent.save_chat_history(session.agent.chat_ctx)
3) Defensive/shutdown-safe approach
• Avoid accessing context after teardown and wrap in try/except:
try:
chat_ctx = getattr(session, "agent", None) and session.agent.chat_ctx
if chat_ctx:
await agent.save_chat_history(chat_ctx)
except Exception as e:
logger.error(f"Error saving conversation: {e}")
Notes and small improvements
• Ensure the Agent is fully initialized before calling session.start(...) (you already construct Agent then start session — good).
• Add the defensive check because shutdown race conditions can remove the agent/session before callbacks run.
• If agent.save_chat_history expects a specific type, pass exactly that (e.g., agent.chat_ctx) rather than None.
Optional: If you paste the WAECExamAgent.save_chat_history signature or Agent class snippet, I’ll give the exact one-line replacement to use.most-vr-18651
12/22/2025, 4:17 PMtall-airline-16756
12/22/2025, 4:17 PMAgentSession does not expose chat_ctx. The chat context lives on the Agent instance. That call can fail (especially during shutdown) because session.chat_ctx is invalid or the session/agent was torn down.
Recommended minimal fix
• Replace the save call to use the Agent’s context directly:
await agent.save_chat_history(agent.chat_ctx)
Safer shutdown-safe version
• Use a guarded pattern to avoid race conditions if the agent/session has been cleared:
try:
chat_ctx = getattr(session, "agent", None)
if chat_ctx:
await agent.save_chat_history(session.agent.chat_ctx)
except Exception as e:
logger.error(f"Error saving conversation: {e}")
Notes and quick suggestions
• You already create and pass agent into session.start(...) — so agent.chat_ctx should hold the history you loaded.
• Keep the defensive guard in the shutdown callback because shutdown ordering can remove session/agent before callbacks run.
• If save_chat_history expects a specific object type, pass exactly agent.chat_ctx (not None).
If you’d like, paste the WAECExamAgent.save_chat_history signature and I’ll give the exact one-line replacement and the final callback body to drop into your code.