Skip to content

feat(voice): send session_closed to the remote session when the session closes - #8099

Merged
u9g merged 10 commits into
mainfrom
feat/session-closed-event
Nov 5, 2026
Merged

u9g merged 10 commits into
mainfrom
feat/session-closed-event

Conversation

@u9g

@u9g u9g commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

What

SessionHost now sends a session_closed event (livekit/protocol#1888) to its RemoteSession client when the attached AgentSession closes. The event carries the session's CloseReason and its error, if there is one. RemoteSession emits it as session_closed.

Why

Today a client learns the call ended only when the agent leaves the room. #7986, stacked on this PR, keeps the host up for the whole job so the agent can still be asked for its on_simulation_end verdict after it hangs up. That keeps the agent in the room, so the simulator needs this event to know the call is over.

The event is safe to ship before the simulator reads it, because current clients ignore unknown events. Shipping it first means that by the time #7986 is released, the simulator already handles agents that stay in the room.

Blocked on

livekit/protocol#1888 being released in livekit-protocol. This PR will then raise livekit-protocol>= in livekit-agents/pyproject.toml to that version. It's a draft until then.

Verification

tests/test_session_host.py: the host subscribes to close, and _on_close sends session_closed with the mapped reason. ruff and mypy are clean. The tests were run against Python bindings generated locally from the protocol branch.

Parity: livekit/agents-js needs the same event (tracked with livekit/agents-js#2793).

Comment on lines +555 to +563
if job_ctx.simulation_context() is not None and self._room is job_ctx.room:
# the simulator asks for on_simulation_end over this room after the session
# closes; the job deletes it only once that wait is over
async def _delete_room_on_shutdown() -> None:
await job_ctx.delete_room(room_name=self._room.name)

job_ctx.add_shutdown_callback(_delete_room_on_shutdown)
job_ctx.shutdown(reason=ev.reason.value)
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we consolidate both path?

The delete after session close vs delete after job_ctx close?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tho mb it's a breaking change?

@CLAassistant

CLAassistant commented Nov 4, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

u9g added 8 commits November 4, 2026 16:33
…on closes

A client learns the call is over from the session itself rather than from
the agent leaving the room.
Split event unhooking out of aclose into unregister_session, let
register_session replace the attached session, and expose it. Request
handling captures the session once per request and finalize_simulation
moves into its own method. No behavior change.
…outlives the session

The SessionHost is now owned by the job rather than the AgentSession: the
primary session attaches on start and detaches on close, and the job
closes the host during shutdown. Under a simulation, shutdown keeps the
host serving until the simulator finalizes, leaves, or session_end_timeout
passes, so on_simulation_end still runs when the agent ends the call.

While no session is attached, session requests fail with
"no active session" instead of being dropped; finalize_simulation needs
only the job and is answered either way.
…s to send

A finalize_simulation reply that the transport can't deliver left
wait_for_simulation_finalized() pending, so job shutdown sat out the whole
session_end_timeout unless the simulator happened to leave the room.
@u9g
u9g marked this pull request as ready for review November 5, 2026 00:34
@u9g
u9g force-pushed the feat/session-closed-event branch from 4a9c292 to a9038ed Compare November 5, 2026 00:34
@u9g
u9g requested a review from a team as a code owner November 5, 2026 00:34
@u9g
u9g force-pushed the feat/session-closed-event branch from a9038ed to 47b70d0 Compare November 5, 2026 00:34
devin-ai-integration[bot]

This comment was marked as resolved.

A session restarted in another room reused the job's host, whose transport
is bound to the job's room, so nothing in the new room could reach it. The
job owns the host only so the simulator can finalize over the job's room;
a session anywhere else owns its own host.
@u9g
u9g merged commit 78d1245 into main Nov 5, 2026
25 of 26 checks passed
@u9g
u9g deleted the feat/session-closed-event branch November 5, 2026 00:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants