Is there any mechanism in livekit such that when p...
# ask-ai
f
Is there any mechanism in livekit such that when participant exit the room, i keep the agent there for a certain time period first? before making it leave the room? instead of exiting the room immediately and performing the clean up callback function? Or is there any mechanism for rejoining a room with the past context?
t
Thanks for reaching out, Mok. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
I'm glad you're interested in how LiveKit can help manage participant exits and rejoining with their previous context—it’s a really handy feature! Delaying Participant Exit: You have the option to set a
departure_timeout
when creating a room. This means the room stays open for a bit after someone leaves, giving them a chance to come back without losing their session details. For instance, you can set this up using the server SDK or API like this:
Copy code
// Using Node SDK
await roomService.createRoom({
  name: "my-room",
  departureTimeout: 300, // 5 minutes to rejoin
  emptyTimeout: 60
});
Rejoining with Past Context: LiveKit makes it easy by supporting automatic reconnection and restoring the participant’s session. It keeps track of their metadata, track states, and subscriptions, so when they rejoin, everything picks up right where they left off, ensuring smooth media continuity. If you’d like, I’m here to help you with more details or guide you through implementing these features—just let me know! Sources: src/room/Room.ts | packages/livekit-server-sdk/src/RoomServiceClient.ts | protobufs/livekit_room.proto | livekit-protocol/src/livekit.rs | livekit-rtc/livekit/rtc/room.py
f
But when do i create a room? Currently, I am generating a livekit access token, and passing it to the frontend and frontend uses the livekit url and this token to join a room
t
In LiveKit, rooms are created automatically as soon as the first participant joins with a valid access token. This makes things pretty smooth and usually means you don’t have to worry about creating rooms manually. That said, if you’d like to customize room settings like
departure_timeout
,
empty_timeout
, the maximum number of participants, or add metadata, it’s best to create the room explicitly ahead of time using the server SDK or API. Here’s a quick example:
Copy code
// Using Node SDK
await roomService.createRoom({
  name: "custom-room",
  departureTimeout: 300, // 5 minutes
  emptyTimeout: 60
});
If you’d like, I’m here to help you set up explicit room creation or answer any questions you might have. Just let me know! Sources: Docs::Home | Rooms, participants, and tracks | LiveKit Docs | CreateRoom() is Taking Too Long | packages/livekit-server-sdk/src/RoomServiceClient.ts
f
in that case, can I create the room, and then generate the access token to enter that room? and frontend uses that token to access the room?
t
Absolutely, you can start by creating a room and then generate an access token for it. This token will allow your frontend to join the room you’ve already set up. Here’s a simple way to do it: 1. Create the Room:
Copy code
// Using Node.js SDK
const svc = new RoomServiceClient(livekitHost, 'api-key', 'secret-key');
svc.createRoom({
  name: 'my-room',
  departureTimeout: 300, // Optional settings
  emptyTimeout: 60
}).then((room) => {
  console.log('Room created:', room);
});
2. Generate the Access Token:
Copy code
// Generate token for the created room
const at = new AccessToken('api-key', 'secret-key', {
  identity: 'participant-name',
});
at.addGrant({ roomJoin: true, room: 'my-room' });
const token = at.toJwt();
Then, your frontend can use this token along with the LiveKit URL to join the room smoothly. If you have any questions or need a hand with anything else, just let me know—I’m here to help!
f
what is the difference between this room, and the room with roomOptions? In the backend, when I do connect the agent session with the room, i pass in RoomOptiond which does not have departureTimeout? i am using python
t
I’m happy to help clarify this for you! There’s no functional difference between creating a room with
RoomOptions
and specifying an explicit
departureTimeout
. The
departureTimeout
simply defines how long the room stays open after the last participant leaves, so anyone can rejoin within that time frame. If you’re working with Python and
RoomOptions
doesn’t include
departureTimeout
, you can easily set it when creating the room using the
create_room
method like this:
Copy code
room_info = await room_service.create_room(
    name="my-room",
    departure_timeout=300  # 5 minutes
)
Please feel free to reach out if you’d like me to walk you through this further or if you have any other questions about your Python setup—I’m here to help! Sources: cmd/lk/room.go | packages/livekit-rtc/src/room.ts | pkg/service/roomallocator.go | livekit/livekit_models.pb.go
f
when participant leaves the room, will the agent perform clean up? or will it stay in the room until departure time has reached, and the room is closed, only then will the agent perform thr callback mechanism?
t
When a participant leaves a room, the agent doesn’t clean up right away. Instead, the room stays open for the set
departureTimeout
period (which is 20 seconds by default) to give participants a chance to reconnect. During this time, the agent remains in the room. Once the
departureTimeout
expires and the room closes—assuming no one has rejoined—the cleanup and callback processes kick in. If you’d like, I’m here to help explain this further or assist you with setting up this behavior just the way you need it. Sources: Avoiding Room ID Reuse When Re-Creating Rooms With the Same Name | Anatomy of an Agent | LiveKit Docs | Anatomy of an Agent | LiveKit Docs | pkg/rtc/room_test.go
f
i see, so there is 20 seconds of departureTimeout set. But what happens when someone were to rejoin during this? The agent is inactive when I rejoin, where it doesn't react to my voice, why is that so?
t
I'd love to help you figure out why the agent becomes inactive when you rejoin during the
departureTimeout
. Could you please share a bit more about your setup? • Are you using room-level or participant-level agent dispatch? • Does the agent worker scale down to zero when it's inactive? • Have you noticed any particular logs or events during the reconnection process? Getting these details will really help us understand what's going on with the agent lifecycle or reconnection, so we can find the best solution together. Sources: Events and error handling | LiveKit Docs | SIP Integration | livekit/livekit_composite | DeepWiki | Deploying to production | LiveKit Docs | pkg/rtc/room.go | Docs::Home
f
i am using participant level agent dispatch, where i am using agent dispatch via the participant access token. I am unsure if agent worker scale down to zero, and there is no logs or events during reconnection. During reconnection, I can see that the agent is there where i can recieve the published text data, but agent is responsive. After I leave the room again, after 20seconds only then does the room perform exit
t
I understand how it can be a bit confusing when the agent becomes unresponsive during reconnection. What’s happening is that LiveKit treats the reconnection like everyone, including the agent, leaves and then rejoins the room. Because of this, the agent temporarily steps out of active states (like listening or speaking) and takes a moment to become fully responsive again once the media tracks are back in place. To help smooth this out, here are a few things you can try: • Keep an eye on reconnection events (
reconnecting
and
reconnected
) in your app, so you can gently inform users with messages like "Agent is reconnecting." • Make sure your setup avoids delays when initializing agents (like cold starts) by running multiple agent instances or tweaking your scaling settings. • Take advantage of frontend SDK features to monitor the agent’s state and show helpful status updates (such as "thinking" or "initializing") during those reconnection moments. If you’d like, I’m here to walk you through implementing any of these steps or answer any other questions you might have! Sources: Web and mobile frontends | LiveKit Docs | Getting Help | livekit/livekit_composite | DeepWiki | Deploying to production | LiveKit Docs | agent-console/lib/event-definitions.tsx | Connecting to LiveKit | LiveKit Docs
f
how long will the moment take? can u also how me the frontend code to check status of agent? what happens when agent rejoins? does it run the entrypoint function again?
t
Thank you for reaching out! Here’s the information you requested to help you along: 1. How long does agent reconnection take? The reconnection time can vary a bit, but typically frontend setups use timeouts between 10–20 seconds to check if the agent is available. If agents are scaling from zero (a cold start), it might take a little longer. I hope this helps set your expectations! 2. Frontend code to check agent status: Here’s a handy way to keep an eye on the agent’s status using the
useVoiceAssistant()
hook in React:
Copy code
function isAgentAvailable(agentState) {
  return agentState === 'listening' || agentState === 'thinking' || agentState === 'speaking';
}

useEffect(() => {
  if (sessionStarted) {
    const timeout = setTimeout(() => {
      if (!isAgentAvailable(agentState)) {
        room.disconnect();
      }
    }, 10000); // Feel free to adjust this timeout to what fits your use case
    return () => clearTimeout(timeout);
  }
}, [agentState, sessionStarted, room]);
3. Does the agent re-run the entrypoint function on rejoin? Great question! The entrypoint function runs only once per job assignment and doesn’t run again when the agent reconnects. But don’t worry—you can handle participant rejoins during an active session using
add_participant_entrypoint
. Here’s an example:
Copy code
def entrypoint(ctx: JobContext):
    async def on_participant_join(job: JobContext, participant: RemoteParticipant):
        await job.room.local_participant.publish_data("Welcome back!")

    ctx.add_participant_entrypoint(on_participant_join, kind=ParticipantKind.HUMAN)
If anything isn’t clear or you’d like a hand implementing these, just let me know—I’m here to help! Sources: Deploying to production | LiveKit Docs | AI voice agents | LiveKit Docs | Anatomy of an Agent | LiveKit Docs | Infrastructure & Deployment | livekit/livekit_composite | DeepWiki | lib/controllers/app_ctrl.dart
f
i see, does that mean becuase i dont have add_participant_entrypoint, when the participant rejoins, the agent isnt connected? i would need to put .connect() within the add_participant_entrypoint() function? for agent to connect
t
Hi there! Just to clarify, the
add_participant_entrypoint
function doesn’t actually handle agent reconnection. It’s mainly used to set up what happens when a participant joins the room, like initializing behaviors specific to that participant. It doesn’t change the agent’s connection status. To make sure your agent connects properly, you’ll want to explicitly call
ctx.connect()
inside the
entrypoint
function—unless you’re using
AgentSession
, which takes care of connecting automatically when you call
session.start()
. Here’s a quick example:
Copy code
async def entrypoint(ctx: JobContext):
    await ctx.connect()  # Connect the agent to the room
    # Additional setup logic here
If you’re looking to handle participants rejoining,
add_participant_entrypoint
is great for defining what happens when they join, but it won’t reconnect the agent itself. Please feel free to ask if you’d like me to walk you through more examples or explain anything further—I’m here to help! Sources: examples/primitives/participant_entrypoint.py | Job lifecycle | LiveKit Docs | agents/src/job.ts | Connecting to LiveKit | LiveKit Docs | Docs::Home
f
I am using AgentSession, will that handle the reconnection automatically? I realise I am doing both ctx.connect() and agentSession, how should I change my code?
t
AgentSession
is designed to make things easier by automatically handling reconnection when room I/O is enabled, so in most cases, you don’t need to call
ctx.connect()
manually. When you use
session.start()
, it takes care of calling
ctx.connect()
internally to set up the connection for you. If you happen to be calling
ctx.connect()
yourself alongside
AgentSession
, I’d recommend removing that manual call to avoid any redundancy. Your code would look something like this:
Copy code
async def entrypoint(ctx: JobContext):
    session = AgentSession(ctx)
    await session.start()  # Automatically handles connection and reconnection
    # Additional logic here
Please feel free to reach out if you’d like me to explain anything further or help you optimize your code. I’m here to help! Sources: README.md | examples/src/drive-thru/drivethru_agent.ts | Building an Automated IVR Menu Caller | LiveKit Docs | Job lifecycle | LiveKit Docs | Connecting to LiveKit | LiveKit Docs
f
i see is it because i didnt do session.start(), thats why the agent didnt reconnect?
t
I totally understand where you're coming from! If you didn't call
session.start()
, the
AgentSession
wouldn't have been set up properly, which means the agent wouldn't reconnect automatically. The
session.start()
method is actually what takes care of managing the connection, reconnection, and handling room I/O. To make sure your agent reconnects smoothly, just double-check that your code includes this part:
Copy code
async def entrypoint(ctx: JobContext):
    session = AgentSession(ctx)
    await session.start()  # This initializes and manages the agent's connection
    # Additional logic here
If you have any questions or want me to walk you through it, please don’t hesitate to ask. I’m here to help!
f
Currently when I create AgentSession, i do not pass in ctx? session = AgentSession( userdata={"ctx": ctx}, llm=google.LLM(model="gemini-2.0-flash"), stt=google.STT( model="latest_long", spoken_punctuation=False, ), tts=google.TTS( language="en-US", voice_name="en-US-Chirp3-HD-Despina", ), vad=ctx.proc.userdata.get("vad"), turn_detection=MultilingualModel(), preemptive_generation=True, ) This is how i create the AgentSession, do i need to pass in ctx to AgentSession?
t
Hey there! You actually don’t need to pass
ctx
directly to the
AgentSession
constructor. Instead, it’s best to pass specific values you get from
ctx
, like
ctx.proc.userdata.get("vad")
, just like you’re already doing in your code. That said, when you start the session, make sure to pass
ctx.room
to the
session.start()
method. This step is important to connect your session to the LiveKit room. Here’s a quick example:
Copy code
await session.start(
    agent=...,  # Your agent configuration
    room=ctx.room,  # Pass the room object from ctx
    ...
)
If anything feels unclear or you want a hand with this setup, just let me know—I’m here to help! Sources: examples/voice_agents/langgraph_agent.py | pipeline-tts/playai_tts.py