bulky-wall-61623
05/26/2026, 8:41 AMtall-airline-16756
05/26/2026, 8:42 AMtall-airline-16756
05/26/2026, 8:42 AMWebSocket.close() returns errors or is never called?
Answering these will let me recommend exact places to add cleanup (client-side event handlers, server-side webhook handlers, per-room socket lifecycle, or ensuring close() is called). If you prefer, paste the relevant code and I’ll point out the minimal changes to reliably close the Soniox connection when the LiveKit session ends.
, with interactive elementsbulky-wall-61623
05/26/2026, 8:50 AMsoniox_stt_options = soniox.STTOptions(
model="stt-rt-v4",
language_hints=...,
enable_language_identification=True,
context=...,
client_reference_id=user_id,
)
stt = soniox.STT(params=soniox_stt_options)
session = AgentSession(
stt=stt,
llm=...,
tts=...,
turn_detection=...,
vad=...,
)
await session.start(room=ctx.room, agent=agent, ...)
6. How is the LiveKit session termination detected?
On the server side, in voice mode, the agent checks ctx.room.remote_participants every 5 seconds. If the room has zero remote participants for LIVEKIT_EMPTY_ROOM_GRACE_SECONDS, default 30 seconds, it calls session.aclose().
On the client side, disconnection is handled by setting the LiveKitRoom connect prop to false. Text chat has an onDisconnected log, but that is not directly wired to Soniox close handling.
7. Desired behavior for closing Soniox
Based on the current implementation, voice mode is designed to close the agent session, including Soniox/STT, when the last remote participant has left and the grace period has elapsed. It does not close when a specific participant leaves. Explicit room cleanup is configured via session.start(... delete_room_on_close=True), so room deletion is tied to session close.
8. Are there logs showing Soniox remains connected after LiveKit disconnects? Does WebSocket.close() return an error?
I did not find logs in the repository that directly show Soniox remaining connected after LiveKit disconnects. There is also no app-level code that calls WebSocket.close() for Soniox.
So this is not a case where WebSocket.close() is returning an error. Rather, the application code is not directly calling WebSocket.close(); the Soniox connection lifecycle is managed internally by the LiveKit Agents Soniox plugin.tall-airline-16756
05/26/2026, 8:50 AMsoniox.STT(...), passing it into AgentSession, and calling session.start(...). There’s no app-level WebSocket open/close.
• The agent detects an empty room and calls session.aclose() after the configured grace period (default 30s).
• Proper cleanup (including closing STT connections) happens when session.aclose() or session.shutdown(drain=True) runs. If the process exits before those calls, connections may remain.
Recommended next steps to ensure Soniox closes when the LiveKit session ends
1. Confirm session teardown is actually being called:
◦ Add short-lived debug logs around the empty-room detection and immediately before/after await session.aclose() to confirm it runs every time the room becomes empty.
1. Add a shutdown callback to guarantee cleanup on job shutdown:
◦ Ensure your job registers a shutdown hook that calls await session.aclose() so cleanup runs on orchestrated shutdowns:
async def on_shutdown():
await session.aclose()
ctx.add_shutdown_callback(on_shutdown)
1. Enable/inspect agent debug logs for STT teardown:
◦ Turn on debug logs and look for messages that indicate STT/soniox teardown and session report uploads (these confirm resource cleanup).
1. Verify you’re on a recent plugin version:
◦ If session.aclose() logs show teardown but Soniox connections still persist, upgrade livekit-plugins-soniox (check GitHub for fixes against lingering WS connections).
1. Reproduce and capture evidence:
◦ Reproduce an end-to-end flow: start session → let grace period elapse → confirm session.aclose() logs → then check Soniox connection state (plugin logs or Soniox dashboard). Capture logs showing teardown or persistence.
1. If process is being killed hard:
◦ Ensure your process/container runtime isn’t forcibly killing the agent (SIGKILL) before cleanup. Use graceful stop so the shutdown hook runs.
If you’d like, paste the specific snippet where you perform the empty-room check and call session.aclose() and I’ll point out exactly where to add logging and a shutdown callback.
Sources: Soniox STT plugin guide | LiveKit Documentation | Job lifecycle | LiveKit Documentation | Agent session | LiveKit Documentation | Why is my Agent insights data missing? | LiveKit, with interactive elements