fresh-painting-88343
07/25/2025, 6:41 PMtall-airline-16756
07/25/2025, 6:41 PMtall-airline-16756
07/25/2025, 6:42 PMRoomInputOptions.close_on_disconnect
setting.
Here’s how you can implement this:
from livekit.agents import AgentSession, RoomInputOptions
async def entrypoint(ctx: JobContext):
session = AgentSession(
stt=deepgram.STT(),
llm=openai.LLM(),
tts=cartesia.TTS(),
vad=silero.VAD.load(),
)
# Disable automatic session closing when participant disconnects
room_options = RoomInputOptions(close_on_disconnect=False)
await session.start(agent=MyAgent(), room=ctx.room, room_options=room_options)
You can also implement custom logic to handle user inactivity and control when the agent should leave the room. For example, you can configure a timeout and check for user presence:
async def entrypoint(ctx: JobContext):
session = AgentSession(
vad=silero.VAD.load(),
llm=openai.LLM(model="gpt-4o-mini"),
stt=deepgram.STT(),
tts=cartesia.TTS(),
user_away_timeout=12.5, # Configure timeout in seconds
)
inactivity_task: asyncio.Task | None = None
async def user_presence_task():
# Try to ping the user 3 times, if no answer, close the session
for _ in range(3):
await session.generate_reply(
instructions=(
"The user has been inactive. Politely check if the user is still present."
)
)
await asyncio.sleep(10)
await asyncio.shield(session.aclose())
ctx.delete_room()
@session.on("user_state_changed")
def _user_state_changed(ev: UserStateChangedEvent):
nonlocal inactivity_task
if ev.new_state == "away":
inactivity_task = asyncio.create_task(user_presence_task())
return
# Cancel inactivity task when user becomes active again
if inactivity_task is not None:
inactivity_task.cancel()
await session.start(agent=Agent(instructions="You are a helpful assistant."), room=ctx.room)
By default, the room will automatically close when the last non-agent participant leaves. However, with the above configurations, you can control this behavior and decide when the agent should leave the room.fresh-painting-88343
07/25/2025, 8:29 PMtall-airline-16756
07/25/2025, 8:30 PMclose_on_disconnect=False
, the server has its own rules. So if you're the last one in the room, the agent might wave goodbye.
2. Other Session Close Reasons
There are a few other reasons your agent might suddenly exit:
• You might have ended the conversation.
• Someone might have programmatically closed the session.
• The room got deleted (oops!).
• An unexpected error popped up.
3. Different Disconnect Reasons
Sometimes, if the disconnection reason isn't on the standard list, your close_on_disconnect
setting might not work as expected. It's like a special exception to the rule.
Proper Configuration
To keep your agent hanging around, make sure you're setting things up right:
input_options = RoomInputOptions(close_on_disconnect=False)
await session.start(agent=MyAgent(), room=ctx.room, input_options=input_options)
Just a heads up - this setting isn't a magic solution. It helps prevent disconnection in some cases, but the server and other factors can still cause your agent to leave.
Need more help? I'm here for you! Let's figure this out together.
Sources: livekit-agents/livekit/agents/voice/room_io/room_io.py | Anatomy of an Agent | LiveKit Docs | Events and error handling | LiveKit Docsfresh-painting-88343
07/25/2025, 8:44 PMBVCTelephony
for best results
noise_cancellation=noise_cancellation.BVC(),
close_on_disconnect=False,
),
)
await ctx.connect()
await session.say(agent_config.get_intro_sentence(), allow_interruptions=True)
And i get this:
2025-07-25 224155,702 - INFO voice-agent - User state changed: speaking {"pid": 55868, "job_id": "AJ_VQyoKUpA2omj"}
2025-07-25 224200,686 - DEBUG livekit.agents - received user transcript {"user_transcript": "Entering the museum. Uh, which exhibit can I see today?", "language": "en-US", "pid": 55868, "job_id": "AJ_VQyoKUpA2omj"}
2025-07-25 224200,882 - INFO voice-agent - User state changed: listening {"pid": 55868, "job_id": "AJ_VQyoKUpA2omj"}
2025-07-25 224215,984 - DEBUG livekit.agents - stream closed {"participant": "museum-visitor", "source": "SOURCE_MICROPHONE", "pid": 55868, "job_id": "AJ_VQyoKUpA2omj"}
2025-07-25 224238,623 - INFO livekit.agents - process exiting {"reason": "", "pid": 55868, "job_id": "AJ_VQyoKUpA2omj"}
2025-07-25 224238,622 - DEBUG livekit.agents - shutting down job task {"reason": "", "user_initiated": false, "pid": 55868, "job_id": "AJ_VQyoKUpA2omj"}
2025-07-25 224238,626 - WARNING livekit.agents - rotate_segment called while previous segment is still being rotated {"pid": 55868, "job_id": "AJ_VQyoKUpA2omj"}
2025-07-25 224238,630 - DEBUG livekit.agents - session closed {"reason": "job_shutdown", "error": null, "pid": 55868, "job_id": "AJ_VQyoKUpA2omj"}
2025-07-25 224238,630 - DEBUG livekit.agents - http_session(): closing the httpclient ctx {"pid": 55868, "job_id": "AJ_VQyoKUpA2omj"}tall-airline-16756
07/25/2025, 8:45 PMjob_shutdown
. No need to worry - this is actually a normal part of how LiveKit manages its processes. Think of it like a gentle system reset happening behind the scenes.
What's Going On:
• Worker Shutdown: Sometimes your worker process needs a quick refresh, like during updates or system maintenance.
• Resource Cleanup: The system is just tidying up, making sure everything's running smoothly.
• Graceful Termination: It's basically the system's way of saying, "Okay, time to wrap things up nicely!"
Here's a Quick Fix:
Want to handle this smoothly? You can add a simple listener in your agent code:
@session.on("close")
def on_close(ev: CloseEvent):
print(f"Agent Session closed, reason: {ev.reason}")
if ev.reason == CloseReason.JOB_SHUTDOWN:
# Handle job shutdown specific logic
pass
This little snippet will help you keep track of what's happening and let you add any custom cleanup steps you might need.
Got questions? I'm here to help! Just shoot me a message if you want to dig deeper into this.
Sources: tests/test_ipc.pyfresh-painting-88343
07/25/2025, 8:47 PMtall-airline-16756
07/25/2025, 8:48 PMimport asyncio
from livekit.agents import AgentSession, JobContext
async def entrypoint(ctx: JobContext):
session = AgentSession(
# your session configuration
)
# Start a task to disconnect after 1 minute
async def disconnect_after_duration():
await asyncio.sleep(60) # 1 minute
await session.aclose()
ctx.delete_room()
# Start the disconnect task
asyncio.create_task(disconnect_after_duration())
# Start the agent session
await session.start(agent=Agent(instructions="Your instructions"), room=ctx.room)
Cool Alternative Ways:
• Using Room Disconnect: Want a straightforward way to say goodbye after a minute?
• Using Agent Shutdown: Another neat trick is using `ctx.shutdown()`:
These methods are like setting a friendly countdown for your AI agent. Super easy, right? If you need any more help or want to chat through the details, I'm totally here for you! 😊
Sources: AI Agents Framework | livekit/livekit_composite | DeepWiki | Job lifecycle | LiveKit Docs | livekit-protocol/src/livekit.rs | examples/voice_agents/inactive_user.py