does the shutdown callback have a time limit?
# ask-ai
h
does the shutdown callback have a time limit?
✅ 1
t
Thanks for reaching out, James. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — good question about the shutdown callback. Yes — shutdown callbacks should finish quickly. By default the server waits 10 seconds for shutdown hooks to complete before forcefully terminating the process. If you need a different timeout, you can change it with the
shutdown_process_timeout
option in the agent server options. Would you like the exact config path or an example of setting
shutdown_process_timeout
for your setup? Sources: Job lifecycle | LiveKit Documentation, with interactive elements
h
yes gimme an example
t
Thanks — I’ll show a concise example. Below are two common styles: a short YAML config and a programmatic example (Node-like pseudocode). Pick whichever matches your setup. YAML example (agent server options)
Copy code
agent_server:
  # time in seconds the server will wait for shutdown callbacks to finish
  shutdown_process_timeout: 30
Programmatic example (server startup)
Copy code
// pseudocode / Node-style example
const options = {
  // other agent options...
  shutdown_process_timeout: 30 // seconds
};

const server = createAgentServer(options);
server.start();
Notes: • The value is in seconds. • The default is 10 seconds; set a larger value only if your shutdown hooks need more time. • Keep shutdown hooks fast and idempotent so the process can terminate reliably. If you tell me which runtime or config file you’re using (e.g., Docker Compose, systemd unit, Golang binary flags), I can provide a tailored example for that environment. , with interactive elements
h
okay separate question, would I be able to use a config.yaml file to change some room parameters when I'm deploying the project to livekit cloud using lk agent create?
t
Thanks — I’m responding to your question about using a
config.yaml
with
lk agent create
to change room parameters when deploying to LiveKit Cloud. You cannot use a
config.yaml
file to modify room-level parameters during an
lk agent create
deployment. There’s no support for passing room configuration that way. What you can do instead: • Include room configuration in the access token using the
RoomConfiguration
object (this supports fields like
max_participants
and agent dispatch rules via
RoomAgentDispatch
). • Use environment variables or the
livekit.toml
for agent/server-level configuration when deploying agents (these do not change room parameters). • Set room parameters programmatically at runtime via the SDKs or server APIs when creating or updating rooms. If you tell me which room parameters you want to change (for example: max participants, metadata, agent dispatch rules) and how you create rooms (via SDK, server API, or token-based creation), I can show the exact code or token fields to set those values. Sources: examples/drive-thru | livekit/livekit_composite | DeepWiki | server-sdk-kotlin | livekit/livekit_composite | DeepWiki, with interactive elements
h
Okay the parameter I want to modify is departure_timeout
t
Thanks — you want to modify the room-level parameter
departure_timeout
. I’m responding to that specifically and how to set it when using LiveKit Cloud. Short answer: • You cannot set
departure_timeout
via a
config.yaml
passed to
lk agent create
. • Set
departure_timeout
when creating the room through the Server SDK or the Room creation API (it's a field on the CreateRoomRequest). Examples — set departure_timeout when creating a room 1) Python (async example)
Copy code
from livekit import api

lk_api = api.LiveKitAPI(
    url="https://your-instance.livekit.cloud",
    api_key="your-api-key",
    api_secret="your-api-secret",
)

# create room with departure_timeout (seconds)
resp = await lk_api.room.create_room(
    api.CreateRoomRequest(
        name="my-room",
        max_participants=10,
        departure_timeout=60  # keep room open 60s after last participant leaves
    )
)
2) Node.js (pseudocode / typical pattern)
Copy code
const lk = new LiveKitAPI({ url: 'https://your-instance.livekit.cloud', apiKey: 'key', apiSecret: 'secret' });

await lk.rooms.createRoom({
  name: 'my-room',
  max_participants: 10,
  departure_timeout: 60 // seconds
});
Notes and best practices •
departure_timeout
is measured in seconds and controls how long the room remains open after the last participant disconnects. • This is a room creation parameter (CreateRoomRequest). It’s not part of agent-level config or agent deployment files. • If you create rooms via tokens or programmatically from your app server, include
departure_timeout
there. • If you tell me how you currently create rooms (Server SDK, REST API, token-based flow), I can give a precise code sample for that environment. Sources: Server-side | livekit/livekit_composite | DeepWiki | Python SDKs | livekit/livekit_composite | DeepWiki | Job lifecycle | LiveKit Documentation, with interactive elements
h
I'm using the livekit meet frontend. I set the following await roomService.createRoom({ name: roomName, departureTimeout: 120, metadata: metadataString, }); but after setting this I don't get any logs in the livekit agent backend which I deployed on the livekit cloud. without this line the connection works just fine. Is there something I'm missing? Is there any mandatory fields required in the metadata?
t
Thanks — I’m responding to your issue where adding
departureTimeout
to the LiveKit Meet frontend call stops the agent backend from producing logs (but the connection works when you omit it). Let’s narrow down what’s happening and get you a working setup. Quick checklist and likely causes • Parameter name/casing: The room creation API expects
departure_timeout
(snake_case) at the server/SDK level. Frontend helpers may use camelCase, but sometimes that field isn’t accepted from the client for security reasons. If the frontend call forwards this directly to the server SDK, it may be ignored or rejected. • Where the room is created: For LiveKit Cloud, rooms should normally be created from a trusted server (Server SDK or Room creation API) rather than from an untrusted client. If the Meet frontend is calling an internal API that attempts to create rooms with
departureTimeout
, that call may be blocked or not reach the agent. • Metadata: There are no mandatory fields required in
metadata
— it’s a free-form string. Invalid or very large metadata could cause issues, but that’s uncommon. • Silent failures: If the agent backend shows no logs when you include the field, the create-room request may not be reaching the agent (client validation, proxy/edge rejecting it, or the request failing earlier). Next steps — please provide a couple quick details so I can pinpoint the problem 1. How are you calling
roomService.createRoom
in detail? Is this function on your frontend directly calling the LiveKit REST/SDK, or is it hitting your app server which then calls LiveKit Server SDK? 2. Which exact SDK/method are you using? (e.g., LiveKit Meet frontend library, livekit-js, or a custom wrapper). Paste the minimal code snippet if possible. 3. What exact field name are you sending? You showed
departureTimeout
— can you confirm that’s the literal key sent to the API? 4. Do you see any HTTP error responses in the browser devtools network tab when you include the field? Any status code or response body? 5. Which LiveKit backend are you using — LiveKit Cloud (hosted) or self-hosted agent? You mentioned agent deployed on LiveKit Cloud; confirm that. 6. Do you have any agent logs at all when you attempt the create? If not, is there any other service (your app server) that logs the create-room request and response? Immediate workaround you can try • Create the room from your trusted server using the Server SDK and set
departure_timeout
(snake_case) there. Then generate tokens for clients to join that pre-created room. This avoids client-side room creation issues entirely. Example (server-side, Node-like)
Copy code
// server-side: use Server SDK to create room
await livekitApi.rooms.createRoom({
  name: 'my-room',
  departure_timeout: 120, // seconds, snake_case
  metadata: metadataString,
});
What I can do next • If you share how the create call is routed (frontend -> app server -> LiveKit) and the exact request shape, I’ll point out the exact field name and show a minimal working example for your stack. • If you prefer, paste the browser network request (headers + payload) when
departureTimeout
is included and I’ll inspect for mismatched fields or errors. You’re close — once I know how the create call is sent (client vs server) and the exact request payload, I’ll give a precise fix. , with interactive elements
h
When the user clicks the join button a fetch request is made to /api/connection-details. And in that I've the following const API_KEY = process.env.LIVEKIT_API_KEY; const API_SECRET = process.env.LIVEKIT_API_SECRET; const LIVEKIT_URL = process.env.LIVEKIT_URL; const AGENT_NAME = process.env.LIVEKIT_AGENT_NAME; const roomService = new RoomServiceClient(LIVEKIT_URL!, API_KEY!, API_SECRET!); await roomService.createRoom({ name: roomName, departureTimeout: 120, metadata: metadataString, }); const participantToken = await createParticipantToken( { identity:
${participantName}__${randomParticipantPostfix}
, name: participantName, metadata: metadataString, }, roomName, ); // Return connection details const data: ConnectionDetails = { serverUrl: livekitServerUrl, roomName: roomName, participantToken: participantToken, participantName: participantName, }; return new NextResponse(JSON.stringify(data), { headers: { 'Content-Type': 'application/json', 'Set-Cookie':
${COOKIE_KEY}=${randomParticipantPostfix}; Path=/; HttpOnly; SameSite=Strict; Secure; Expires=${getCookieExpirationTime()}
, }, }); function createParticipantToken(userInfo: AccessTokenOptions, roomName: string) { const at = new AccessToken(API_KEY, API_SECRET, userInfo); at.ttl = '5m'; const grant: VideoGrant = { room: roomName, roomJoin: true, canPublish: true, canPublishData: true, canSubscribe: true, }; at.addGrant(grant); if (AGENT_NAME) { at.roomConfig = new RoomConfiguration({ agents: [new RoomAgentDispatch({ agentName: AGENT_NAME })], }); } return at.toJwt(); }
t
Thanks — I’m responding to your backend code that calls
roomService.createRoom
with
departureTimeout
and then issues a participant token. Good detail; that helps narrow this down. Two likely issues and how to check/fix them 1) Field name / casing mismatch • The Server API expects
departure_timeout
(snake_case) on the CreateRoom request. Your code sends
departureTimeout
(camelCase). That can cause the field to be ignored or the request to be rejected depending on the client implementation. • Fix: send
departure_timeout
when calling the server SDK or use the SDK’s CreateRoomRequest/typed object rather than a plain object. Example (Node-style, using snake_case):
Copy code
await roomService.createRoom({
  name: roomName,
  departure_timeout: 120,
  metadata: metadataString,
});
Or, if the SDK provides a CreateRoomRequest class, construct that class and set
departure_timeout
on it. 2) Room creation should happen on the trusted server and is best done via the Server SDK (which you are doing) — but confirm the SDK method you’re calling actually maps fields properly • Verify which RoomServiceClient you’re using and whether it expects camelCase or snake_case in the payload. If you’re passing a plain JS object and the client serializes to the API directly, mismatch will occur. • Check the response from
createRoom
. Right now you return connection details without showing the createRoom response; the create call may be returning an error or validation failure that you’re not logging. Debugging steps to find the root cause 1. Log the createRoom response and any caught errors. ◦ Wrap the call in try/catch and console.log the result and error (status/message/body). 1. Inspect network or SDK logs: ◦ If createRoom fails, your agent might not receive anything — that explains the missing agent logs. A failed/invalid request will often return an HTTP error to your server. 1. Confirm agent behavior: ◦ Without
departureTimeout
, agent logs appear — so compare the successful vs failing request payloads. 1. Try creating the room server-side with snake_case explicitly (and minimal fields) to confirm:
Copy code
try {
  const resp = await roomService.createRoom({
    name: roomName,
    departure_timeout: 120,
    metadata: metadataString,
  });
  console.log('createRoom response', resp);
} catch (err) {
  console.error('createRoom error', err);
}
1. Verify token generation and roomConfig: ◦ Your token code sets at.roomConfig when AGENT_NAME is present. That’s fine. Note: roomConfig in the token is separate from CreateRoomRequest; ensure you aren’t relying on the token to set
departure_timeout
. About metadata • metadata is a free-form string. There are no mandatory fields required. Large or malformed strings could cause issues but that’s uncommon. Metadata isn’t the cause unless it contains something that triggers validation in your path. Immediate workaround • Create the room first server-side with
departure_timeout
(snake_case). If that succeeds, return tokens and join clients to the pre-created room. This avoids depending on the frontend to pass create-room options. If the above doesn’t fix it, please share: • The exact RoomServiceClient library/package name and version you’re using. • The error or response from the
createRoom
call (paste the console output from the try/catch). • Logs from your server (the handler for /api/connection-details) showing the request payload and any error stacks. I’ll walk through the next steps once I can see the createRoom response or the client library info. , with interactive elements
h
await roomService.createRoom({ name: roomName, departureTimeout: 120, metadata: metadataString, agents: AGENT_NAME ? [new RoomAgentDispatch({ agentName: AGENT_NAME })] : undefined, }); This works, but I can't seem to see the logs in lk agent logs anymore. why is this?
t
Thanks — I’m responding to your latest code and the issue you’re seeing: creating the room with
departureTimeout
,
metadata
, and
agents
succeeds, but the lk agent logs stop showing anything. Let’s walk through the likely reasons and focused debugging steps so we can find the root cause. Key things to check and why logs disappear • Silent or early failures: If the create-room request is rejected by the LiveKit control plane (validation error, bad payload shape, or permission problem), the agent never receives a job to run — so the agent will not produce logs. A successful createRoom call on your server doesn't guarantee the agent was dispatched; you must confirm the create call actually triggered the agent dispatch. • Field naming and payload shape: The Server API expects snake_case fields (e.g.,
departure_timeout
). Some SDK wrappers accept camelCase and map it, others do not. If the SDK you use accepts
agents
but not the exact typed objects you constructed, the request may be malformed in a way that still returns success but does not dispatch an agent. • Agent dispatch rules: When you set
agents
on the CreateRoomRequest, agent dispatch happens based on those dispatch rules. If the specified agent name is incorrect or not available, the room might be created without an agent assignment or with a dispatch that never reaches a running agent instance — leading to no agent logs. • Token roomConfig vs CreateRoomRequest: You are both creating the room with
agents
and adding
roomConfig
to the token via
at.roomConfig
. These are separate. If they conflict the effective dispatch may differ from what you expect. • Agent selection / scaling behavior of LiveKit Cloud: If your dispatch request targets a specific agent name that isn’t registered/online, the cloud controller may delay or fail to schedule that agent instance — again no logs on the agent. Concrete checks and quick debugging steps 1. Inspect the createRoom response ◦ Wrap the call in try/catch and log the full response and any error. ◦ Show the response body (it should include the room object and any agent dispatch info). Example:
Copy code
try {
     const resp = await roomService.createRoom({...});
     console.log('createRoom ok:', resp);
   } catch (err) {
     console.error('createRoom error:', err);
   }
1. Confirm the request payload shape sent to LiveKit ◦ Print the object you pass into createRoom just before sending it. ◦ Ensure you are using snake_case if the SDK requires it: ▪︎ use
departure_timeout
not
departureTimeout
if the SDK expects API fields. ▪︎
agents
should be an array of
RoomAgentDispatch
objects — verify the SDK’s typed constructor is used or that the plain object matches required shape. 1. Check agent dispatch result in the create response ◦ The response may include dispatch or room metadata showing which agent (if any) was assigned. If no agent assigned, the agent won’t have logs. ◦ If the response indicates a pending dispatch or an error, that explains no logs. 1. Verify the agent name and availability ◦ Ensure
AGENT_NAME
is exactly the name the agent registered with, and that the agent is running and registered in the LiveKit Cloud before creating the room. ◦ If you target a named agent that is not online, the Cloud may not start it automatically depending on configuration. 1. Compare behavior without
agents
◦ Create a room without the
agents
field (which you said works and shows logs). Compare the returned room object and any dispatch info to the one that does not produce logs. This will show what changed in dispatching. 1. Avoid conflicting settings between token and CreateRoomRequest ◦ Prefer setting agent dispatch via one place: either the CreateRoomRequest’s
agents
or the token’s
roomConfig
, not both. Conflicts can lead to unexpected dispatch behavior. 1. Check size/format of metadata ◦ Metadata is free-form. Extremely large metadata could cause the request to be truncated/ignored, but that’s uncommon. Still, test with a short simple metadata string to rule it out. Immediate troubleshooting actions for you to run 1. Re-run createRoom while logging the full response and any error. 2. If the response shows success, paste the returned JSON for the created room (sensitive keys redacted). I’ll inspect the agent dispatch fields. 3. Try creating the room with explicit snake_case keys:
Copy code
await roomService.createRoom({
     name: roomName,
     departure_timeout: 120,
     metadata: metadataString,
     agents: AGENT_NAME ? [ new RoomAgentDispatch({ agentName: AGENT_NAME }) ] : undefined,
   });
1. Try creating the room without
agents
but with
departure_timeout
to see if agent logs appear; then add
agents
back and compare responses. If you share these three things I’ll pinpoint the problem quickly: • The createRoom response JSON when you include
agents
. • The exact agent name you set in
AGENT_NAME
. • Which library/package and version you use for
RoomServiceClient
(so I can confirm expected field names). You’re very close — once I can see the createRoom response and the agent name, I’ll tell you why the agent logs stop and how to make sure your room gets dispatched to the agent so logs appear. , with interactive elements
h
Oh no,everything works fine, the agent connects correctly. But I just don't see any logs in lk agent logs
t
Thanks — I’m responding to your note that the agent connects correctly but you don’t see any logs in the lk agent logs. Let’s narrow down why the agent is silent and get you visible logging quickly. Possible reasons the agent produces no logs • Log level is too high: the agent may be running at a level that filters out informational or debug messages. • Logs are being written to a different sink (stdout vs a file, or a logging service) than where you’re looking. • The agent process is running but your deployment’s logging/streaming (Cloud UI, kubernetes pod logs, systemd journal, etc.) isn’t configured to capture its stdout/stderr. • The agent isn’t emitting any runtime logs for the specific actions you expect (some code paths are quiet unless debug logging is enabled). • Log rotation/retention or access permissions could hide recent logs in the location you’re checking. Targeted checks to run now 1. Confirm where you’re viewing logs ◦ Tell me how you’re checking logs (LiveKit Cloud Console logs, kubectl logs for a pod, cloud provider logs, systemd journal, file path). This helps me tailor the next step. 1. Check agent log level / verbosity ◦ If the agent supports a log level flag or env var (e.g.,
LOG_LEVEL
,
RUST_LOG
, or a server option), increase it to
info
or
debug
and restart the agent. Then reproduce the create-room action and watch logs. ◦ Example: set
LOG_LEVEL=debug
(or equivalent) and restart. 1. Confirm log output sink ◦ Verify the agent writes to stdout/stderr. If it writes to a file, confirm the file path and permissions. If your platform captures stdout only, file logs won’t appear there. ◦ If using Kubernetes, run: ▪︎
kubectl get pods
then
kubectl logs <agent-pod-name> -f
to stream logs live. 1. Reproduce with a simple action while streaming logs ◦ Stream logs (e.g.,
kubectl logs -f
or Cloud Console live tail) and then immediately trigger join/create from your frontend. Note timestamps and whether any new output appears. 1. Look for subtle log entries ◦ Some agents only log on specific events (error, warnings, lifecycle events). Search for terms like
agent
,
dispatch
,
session
,
join
, or timestamps around your test join to see quieter messages. 1. Ensure your agent instance is the one handling the room ◦ If the Cloud control plane dispatches to another agent instance, you might be watching logs for the wrong agent. Confirm which agent registered for that room (agent name/ID) and tail that instance’s logs. If you want, I can help further — please share: • How you’re currently viewing logs (Cloud Console, kubectl, systemd, file path). • The agent name/ID you set (so we can confirm which instance to inspect). • Any environment variables or flags you use to start the agent (especially anything related to logging). If you prefer, try this quick test and paste results: 1. Increase logging to debug (env var or startup flag). 2. Stream the agent logs live. 3. Trigger a new join/create for the room and paste any new log lines (redact secrets). I’ll help interpret the output and give the exact config tweak to make logging reliable. , with interactive elements
h
I've a separate question about livekit meet. Suppose I join a livekit meet and the agent joins and we talk. Then a second user joins. how does their audio get handled? Can The agent hear them?
t
Thanks — I’m responding to your question about what happens to audio when a second user joins a LiveKit Meet where an agent is already present. Short answer • By default the agent receives and processes audio from all standard participants in the room, including users who join after the agent. So when the second user joins, the agent can hear and process their audio. Details and options • Default behavior: The agent subscribes to published microphone tracks and will get audio from each participant unless you change subscription behavior. • Focus on one participant: If you want the agent to hear only one specific participant, you can configure the agent to process audio from a fixed participant (for example by passing the participant identity when creating RoomIO). In that mode the agent ignores other participants’ tracks. • Voice-activation / filtering: Many agent implementations (like the KITT demo) listen to all users but only respond when triggered by a wake word or other voice-activity logic. That’s useful to avoid the agent reacting to every speaker in multi-user sessions. Practical points • If you expect the agent to interact with a single user in a multi-user room, either: ◦ Configure the agent to target a specific participant, or ◦ Implement VAD/wake-word logic so the agent only responds when addressed. • Data messages (transcripts, agent state) are sent via LiveKit data channels and are independent of who the agent is listening to. If you want, tell me which behavior you want (agent hears everyone, hears only a named participant, or hears everyone but only responds on wake-word), and I’ll show the exact code snippet or configuration for that mode in your stack. Sources: Agents Framework | livekit/livekit_composite | DeepWiki | Live conversations with AI using ChatGPT and WebRTC | LiveKit | How to set a fixed participant for agent audio processing | Live conversations with AI using ChatGPT and WebRTC | LiveKit, with interactive elements
h
Is it possible to add a button which would prevent the users audio from reaching the agent and then turn it back on when necessary. I want the audio between the participants (not agents) to work just fine
t
Thanks — I’m responding to your request about adding a button that prevents a user’s audio from reaching the agent while keeping participant-to-participant audio working normally. Short answer • Yes. You can prevent a specific participant’s audio from reaching the agent without breaking audio between participants by changing either (A) the agent’s subscriptions so it does not subscribe to that participant’s track, or (B) the participant’s published track (mute/unpublish or replace with silent track) only for the agent. The simplest and most common approach is to toggle the agent’s subscription to that participant’s audio track. Two recommended approaches 1) Toggle the agent’s subscription to the participant’s audio track (recommended) • How it works: When the user clicks “disable agent audio,” your server instructs the agent (or the LiveKit server) to set subscription = false for that participant’s audio track on the agent’s connection. That stops the agent from receiving the audio, while other participants who remain subscribed still hear each other. • When toggling back on, set subscription = true for that track for the agent. • Why recommended: Keeps the participant’s published audio intact for everyone else and avoids republishing or audio track manipulation on the client. High-level steps 1. Identify the participant identity or track SID to target. 2. On the agent side (or via server API that can modify the agent’s subscriptions), call the API to set subscription for that participant’s audio track to false. 3. When re-enabling, set subscription back to true. Example patterns (conceptual) • If your agent runs code that listens for subscription changes: ◦ Use the Server SDK or Admin API to update subscription preferences for the agent connection. • If you control the agent process directly (RoomIO), call the SDK method that sets subscriptions for incoming tracks from a participant. Notes • This requires a mechanism to tell the agent (or LiveKit server controller) which participant to unsubscribe from. You already generate tokens with roomConfig/agents — you can include an app-level control channel (data messages) to tell the agent which participant to subscribe/unsubscribe to if you prefer agent-driven changes. 2) Client-side alternatives (if you prefer client control) • Disable the published audio track only for the agent by: a) Publishing two tracks: one intended for participants and one for the agent, and toggle the agent-intended track. b) Replace the published audio track with a silent track only for the agent connection (complex). • Why not ideal: Publishing separate tracks or selectively replacing tracks can be more complicated and may affect participant audio if not carefully scoped. Implementation guidance & suggestions • Use data messages to coordinate: ◦ When the user presses the button, the client sends a request to your server (or a data message to the agent) to toggle the subscription state for this participant on the agent side. • Keep UI state and server/agent state in sync: ◦ Confirm with the agent (via a data message ack) that subscription changed so the UI accurately reflects whether agent audio is blocked. • Edge cases: ◦ If the agent is configured to auto-subscribe to all new tracks, make sure to update that behavior so rejoining or republishing does not auto-enable audio to the agent again. ◦ If multiple participants can be blocked, maintain a per-participant flag on the server/agent. If you want, I can provide: • A concrete code snippet for your stack (LiveKit Meet frontend + Node server + agent). Tell me which side you want the toggle to be initiated from (client → server → agent, or client → agent via data message), and whether you control the agent code so it can receive data messages and change subscriptions., with interactive elements
h
In order for a new joinees audio to reach the agent should we add its corresponding login in on_participant_connected or does it work automatically?
t
Thanks — I’m responding to whether new participants’ audio is routed to the agent automatically or if you need to add logic in
on_participant_connected
. Short answer • New participants’ audio is delivered to the agent automatically by default. The agent subscribes to published microphone tracks when participants publish them, so you don’t strictly need to add a manual login in
on_participant_connected
for audio to reach the agent. When you might still use on_participant_connected • If you want custom behavior when someone joins, handle the event: ◦ Explicitly subscribe or unsubscribe the agent to that participant’s tracks. ◦ Apply per-participant rules (e.g., block this user from the agent, route only specific users). ◦ Send a welcome data message or trigger agent-side setup for that participant. • If your agent is configured to target a single participant (e.g., RoomIO with a specific
participant
), then you will need to handle selection logic when participants connect so the agent knows which identity to focus on. • If you implemented a button to prevent a user’s audio from reaching the agent (subscription toggle), you may need to update subscription state on participant connect/reconnect to maintain that setting. Practical notes • Default auto-subscribe behavior: When a participant publishes audio, agents will receive it unless subscription rules or explicit agent-side logic prevent it. • Use
on_participant_connected
when you need to enforce custom subscription rules, maintain per-user mute-for-agent state, or initialize participant-specific processing (transcription, diarization, etc.). • For robustness, if you rely on subscription toggles, ensure reconnects and new publishes re-apply the intended subscription state (you can re-apply in the participant-connected handler). If you’d like, tell me which behavior you want by default (agent hears everyone, agent hears selected users, or agent hears everyone but only responds on wake-word) and whether you’ve implemented the agent-side subscription toggle. I can then provide a short code example showing how to use
on_participant_connected
to set or re-apply subscription rules. , with interactive elements