colossal-xylophone-68609
05/15/2026, 11:55 AMtall-airline-16756
05/15/2026, 11:56 AMtall-airline-16756
05/15/2026, 11:56 AMshutdown_callback at call end, or the LiveKit livekit-egress webhook.
The shutdown_callback runs first (it executes inside your agent when the session shuts down). The livekit-egress webhook (for example egress_ended) is sent later by the LiveKit server once the recording/egress process fully finishes. The webhook delivery is independent of your agent process and can arrive seconds after your shutdown callback completes.
If you need guaranteed ordering for any post-processing, would you prefer guidance on coordinating them (e.g., having the shutdown callback wait for an egress status or handling idempotent webhook processing)?
Sources: Job lifecycle | LiveKit Documentation | Backup Egress Recordings, with interactive elementscolossal-xylophone-68609
05/15/2026, 12:00 PMtall-airline-16756
05/15/2026, 12:00 PMshutdown_callback to wait for the egress webhook (egress_ended) before finishing. That isn’t automatic, but you can coordinate them. Two patterns:
• Preferred: Have your webhook handler signal completion and only run final shutdown work from there.
a. Webhook receives egress_ended → mark session egress complete (DB flag, cache, or in-memory store).
b. Webhook then invokes your cleanup logic (or triggers the agent shutdown flow) so ordering is guaranteed.
• Alternative: Have the shutdown_callback wait for the webhook signal.
a. Webhook handler sets a shared flag/DB record or releases an async event when egress_ended arrives.
b. In your shutdown_callback, poll or await that flag/event before proceeding.
c. Ensure the shutdown timeout is long enough (default is 10s); increase shutdown_process_timeout if needed.
Minimal example (conceptual):
# shared place: in-memory or persistent store keyed by session_id
egress_done = EventStore()
# webhook handler
def handle_egress_webhook(payload):
session_id = payload["session_id"]
egress_done.set(session_id)
# shutdown callback
async def shutdown_hook(ctx):
session_id = ctx.session_id
await egress_done.wait(session_id, timeout=30) # wait for webhook signal
await do_cleanup()
Notes:
• Use a persistent store (DB or Redis) if webhook and agent run on different machines/processes.
• Make your cleanup idempotent in case of retries or race conditions.
• If you control the webhook endpoint, have it return success only after your cleanup has been triggered/queued to reduce race windows.
Which pattern fits your architecture — letting the webhook trigger cleanup, or having the shutdown hook wait? Tell me whether webhook and agent run on the same host/process and I’ll give code tailored to your stack.
Sources: Job lifecycle | LiveKit Documentation | Why is my Agent insights data missing? | LiveKit, with interactive elements