In livekit-agents, what is calling the `shutdown` ...
# ask-ai
m
In livekit-agents, what is calling the
shutdown
function of a job? I mean what conditions trigger it and who is reponsible. What are the reasons why it might not happen on room.on("disconnected")?
✅ 1
t
Thanks for reaching out, Hugo. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’ll explain what calls
shutdown
, who’s responsible, and why
room.on("disconnected")
may not trigger it. What calls
shutdown
• Agent code or framework logic explicitly calls
ctx.shutdown()
/
session.shutdown()
(for example via an EndCall tool or other agent logic). • A session timer or background task can call
ctx.shutdown()
when the session ends. • The agent runtime calls shutdown during graceful process termination (SIGTERM/SIGINT) to drain active jobs. • Developers can also call shutdown programmatically (e.g.,
session.shutdown(drain=True)
). Who’s responsible • Primary responsibility is the agent (your code) or the agent runtime — not the Room SDK event by itself. The runtime handles shutdown during process-level draining; your job logic should decide when to invoke shutdown for application-level conditions. Why
room.on("disconnected")
might not call
shutdown
•
room.on("disconnected")
is a client-side SDK event that reports the local connection ended; it does not automatically invoke job shutdown unless you wire it to do so. • Job lifecycle is independent of a single participant’s connection. A job can remain active after disconnection until your code or runtime calls shutdown. • If the process crashes or is killed abruptly (unhandled exception, forced kill) shutdown hooks may never run, so
shutdown
won’t be called. • Relying on room disconnect alone can miss cases (intermittent network, reconnection attempts, or background timers) — explicit shutdown logic (timers, tools, signal handlers) is more reliable. If you want, share the part of your agent code where you handle room events and job lifecycle and I’ll point out exactly where to add or ensure a
ctx.shutdown()
call. Sources: EndCallTool | LiveKit Documentation | Build a salary negotiation coach with a LemonSlice avatar | LiveKit | Deployment reliability on LiveKit Cloud | LiveKit | Job lifecycle | LiveKit Documentation | Why is my Agent insights data missing? | LiveKit, with interactive elements
m
Should you disconnect the room or call shutdown explicitly instead? If you want to manually end the call / or a tool call
t
Good question — call
shutdown
explicitly to end a call or a tool-invoked session. Why: •
ctx.shutdown()
(or
session.shutdown()
) ends the job lifecycle cleanly: it runs shutdown callbacks, allows draining logic, and tells the agent runtime the job is finished. •
room.disconnect()
only drops the SDK connection. The job can remain active after disconnect unless you also call
shutdown
, so cleanup, post-processing, or job termination won’t necessarily run. Recommended pattern 1. For a manual “end call” or tool-triggered end (e.g., EndCallTool): call
ctx.shutdown()
(or
session.shutdown(drain=True)
) from your agent logic. 2. Optionally call
room.disconnect()
as part of your shutdown sequence if you want to immediately close the LiveKit connection, but treat that as the transport-level step — not a substitute for shutdown. 3. Ensure you register shutdown callbacks via
ctx.add_shutdown_callback()
for any cleanup that must run. Edge cases • For graceful process termination, rely on signal handlers in the runtime which should call shutdown to drain jobs. • Don’t rely solely on
room.on("disconnected")
to terminate jobs; network blips or reconnection attempts can cause false positives. If you share the code path for your EndCall tool or the agent handler, I can show the exact place to call
ctx.shutdown()
and how to sequence
room.disconnect()
if you want both. , with interactive elements
m
What if we have some extra work in the job after the call finishes
t
Good question — here’s how to handle extra work after the call finishes. Short answer • Keep the job alive, perform your post-call work, then call
ctx.shutdown()
(or
session.shutdown()
) when that work is complete. Don’t rely on
room.on("disconnected")
alone to terminate the job. Recommended pattern 1. End the call via your tool (e.g., EndCallTool) but do not immediately shutdown if you have post-call work. 2. Perform post-call tasks inside the same job: ◦ Run them inline after the call ends, or ◦ Start background tasks and await their completion before shutdown. 1. When post-call work is finished, call
ctx.shutdown()
(or
session.shutdown(drain=True)
) to run shutdown callbacks and mark the job finished. 2. Optionally call
room.disconnect()
during shutdown to close the transport, but treat it as a transport step—not a substitute for
shutdown
. 3. Register any cleanup or finalization with
ctx.add_shutdown_callback()
so critical cleanup runs on shutdown. Notes and edge cases • If you want the agent runtime to drain rather than force-stop, use
drain=True
so in-flight cleanup completes. • Handle process signals (SIGTERM/SIGINT) to ensure graceful shutdown triggers your callbacks if the host initiates termination. • Avoid relying on
room.on("disconnected")
to run post-call work; network disconnects or reconnections can be transient. If you share the code for your EndCall tool or post-call workflow, I can show exactly where to run the extra work and place the
ctx.shutdown()
call. , with interactive elements