big-controller-60015
07/30/2025, 10:15 AM2025-07-29 00:19:42.102
2025-07-28 18:49:42,101 - DEBUG livekit.agents - session closed {"reason": "participant_disconnected", "error": null, "pid": 9187, "job_id": "AJ_oMbASsvxkiJn"}
2025-07-29 00:19:42.098
2025-07-28 18:49:42,097 - DEBUG livekit.agents - stream closed {"participant": "qa-participant-room-test_room_ngRdnB6T9m10399", "source": "SOURCE_MICROPHONE", "pid": 9187, "job_id": "AJ_oMbASsvxkiJn"}
basically session is closed and session events are not raised,
so the last sentence's
@session.on("conversation_item_added")
was not raised, can we delay when the session closes after the participant leaves the roomtall-airline-16756
07/30/2025, 10:18 AMtall-airline-16756
07/30/2025, 10:19 AM@session.on("conversation_item_added") are raised, you can use LiveKit's built-in departure timeout configuration.
Here’s how you can configure it:
1. Locate your LiveKit server configuration file.
2. Set the departure_timeout parameter under the room section. This parameter determines the number of seconds to keep the room open after the last participant leaves. For example:
room:
# number of seconds to keep the room open after everyone leaves
departure_timeout: 20
This ensures that the room remains active for the specified duration, allowing time for session events to be processed before the session is closed.
If you need further assistance or have additional questions, feel free to provide more details about your setup.
Sources: pkg/rtc/room_test.go | Worker lifecycle | LiveKit Docs | examples/voice_agents/session_close_callback.py | Rooms, participants, and tracks | LiveKit Docsbig-controller-60015
07/30/2025, 10:20 AMtall-airline-16756
07/30/2025, 10:21 AMclose_on_disconnect=False in the RoomInputOptions when starting your session. It's super easy, like this:
await session.start(
room=ctx.room,
agent=Assistant(tools=[...]),
room_input_options=RoomInputOptions(close_on_disconnect=False),
room_output_options=RoomOutputOptions(...)
)
1. Implement Custom Participant Tracking:
Now that automatic closure is off, you can add some smart logic to handle when participants disconnect. Think of it like setting up a little waiting room:
# Wait for either last participant to leave or a shutdown signal
room_empty_future: asyncio.Future[None] = asyncio.get_running_loop().create_future()
def _on_participant_disconnected(_: rtc.Participant, fut=room_empty_future) -> None:
if len(ctx.room.remote_participants) == 0 and not fut.done():
fut.set_result(None)
ctx.room.on("participant_disconnected", _on_participant_disconnected)
try:
# Add your delay logic here before waiting
await asyncio.wait(
[shutdown_future, room_empty_future], return_when=asyncio.FIRST_COMPLETED
)
finally:
ctx.room.off("participant_disconnected", _on_participant_disconnected)
await session.aclose()
1. Optional User Away Timeout:
Want an extra layer of control? You can set a user_away_timeout to manage user inactivity:
session = AgentSession(
user_away_timeout=12.5 # seconds
)
By putting these tips together, you'll have total control over your session closure, making sure everything wraps up smoothly and exactly when you want it to. Pretty cool, right?
Sources: Worker lifecycle | LiveKit Docs | examples/voice_agents/session_close_callback.py | Voice Assistants | livekit/livekit_composite | DeepWiki