refined-smartphone-96649
03/22/2026, 4:40 AMtall-airline-16756
03/22/2026, 4:40 AMtall-airline-16756
03/22/2026, 4:41 AMctx.shutdown() or an intentional sleep-based shutdown after 300s).
• A frontend or signaling issue causes the connection to drop and the room then closes when the last non-agent participant leaves.
Useful facts and quick checks you can run
1. Check your agent code for any explicit timers or shutdown logic (look for ctx.shutdown(), asyncio.sleep(300), or similar).
2. Inspect logs or the LiveKit dashboard to see the room closure reason (e.g., participant left vs. server-initiated). That will show whether the closure is CLIENT_INITIATED / PARTICIPANT_LEFT or caused by your code.
3. Verify your client/browser keepalive and WebRTC reconnection settings to rule out network disconnects.
4. If you want the agent to stay running after a user leaves, set the room option close_on_disconnect=false (or the equivalent in your SDK) so the room isn’t removed when the last non-agent participant leaves.
Plan-specific notes
• The Build plan includes free agent session minutes (good for PoCs) but does not force rooms to close after 5 minutes.
• Upgrading increases quotas (concurrent sessions, monthly session minutes, WebRTC minutes) but does not add a short fixed session timeout.
If you want, I can help with targeted debugging — which would you prefer?
• I can guide you where to look in your agent entrypoint and common places people accidentally add a 5‑minute timer.
• Or you can share (paste) any relevant snippets from your agent’s initialization/entrypoint or the client connection logic and I’ll point out what to change. Sources: Deploy and scale agents on LiveKit Cloud | LiveKit | Pricing | LiveKit | Agents on LiveKit Cloud | Deploy voice AI on global infrastructure | LiveKi... | Pricing | LiveKit | Agent session | LiveKit Documentation, with interactive elementsrefined-smartphone-96649
03/22/2026, 4:44 AMtall-airline-16756
03/22/2026, 4:44 AMleave(), disconnect(), room.disconnect(), room.localParticipant.leave(), or ctx.shutdown() and for timers like setTimeout(..., 300000) / asyncio.sleep(300) that may run after 5 minutes.
1. Inspect any reconnection logic or error handlers
◦ Your console shows “Unexpected disconnect — rejoining room...”; check what your reconnect handler does and whether it immediately triggers a cleanup if reconnection attempts fail.
1. Verify PeerConnection lifecycle on the client
◦ The message “could not createOffer with closed peer connection” indicates the PeerConnection was already closed when negotiation ran. Make sure you aren’t creating offers after a prior disconnect.
1. Check server/agent teardown or middleware
◦ If you have an agent process or middleware watching session age, confirm it’s not programmed to terminate sessions after a fixed period.
1. Use dashboard/logs to confirm who initiated the leave
◦ The LiveKit dashboard or server logs typically show whether the leave was CLIENT_INITIATED vs server-initiated. That will confirm the client triggered it.
If you’d like, I can help further — two options:
• Tell me which SDK/language you’re using (browser JS, React components, or a custom wrapper) and I’ll point to the exact places to search for a 5‑minute timer.
• Paste the relevant parts of your connection/cleanup code (client entrypoint, reconnect handler, and any timeouts) and I’ll review them and suggest changes.
You’re on the right track — this looks like application logic rather than a platform limit, and we can find the spot that’s calling the disconnect.
Sources: Server-side | livekit/livekit_composite | DeepWiki | Agents on LiveKit Cloud | Deploy voice AI on global infrastructure | LiveKi... | LiveKit Platform | Build, run, and observe voice AI agents | LiveKit | Server lifecycle | LiveKit Documentation | Agent session | LiveKit Documentation, with interactive elementsrefined-smartphone-96649
03/22/2026, 4:51 AMtall-airline-16756
03/22/2026, 4:52 AMagent: true is not a standard LiveKit grant field for video/room permissions. Including custom/unrecognized claims in the token can interfere with how your application interprets participant roles or lifecycle logic.
• Removing it avoids unexpected side effects; only include claims the server or your own application explicitly checks for.
Why set disconnectOnPageLeave: false
• The default behavior (disconnectOnPageLeave = true) will disconnect the participant when the page unloads or is navigated away from, which can trigger room cleanup if no other non-agent participants remain.
• Setting disconnectOnPageLeave: false prevents the client from automatically disconnecting on page leave/refresh, improving session continuity and avoiding unintended departure events.
How these changes address the 5‑minute disconnect
• Your logs showed disconnect reason 10 (CLIENT_INITIATED) exactly five minutes after connect, which means the client/app explicitly left. Removing a non-standard token claim and disabling automatic page-leave disconnect will eliminate two common causes of client-initiated leaves.
• If some app logic (a timer or cleanup) was conditioned on an agent flag or page unload, these changes will stop that behavior.
Additional checks to be safe
• Search your code for explicit calls like room.leave(), room.disconnect(), localParticipant.leave(), or any setTimeout(..., 300000) / asyncio.sleep(300) and remove/adjust them if they’re unintended.
• Confirm reconnect/cleanup handlers don’t immediately call leave if reconnection fails. Your logs show “could not createOffer with closed peer connection” — ensure offers aren’t attempted after a disconnect.
• If you rely on server-side logic for agents, ensure any server-side lifecycle code isn’t shutting rooms down after a fixed interval.
Suggested next steps
1. Remove agent: true from the token grant. Keep only the needed grants:
◦ roomJoin, room, canPublish, canSubscribe, roomCreate (as required).
1. Set disconnectOnPageLeave: false in the <LiveKitRoom> options.
2. Test again and monitor logs. If you still see reason 10 disconnects, paste the relevant client connection/reconnect/teardown snippets and I’ll review them for timing or lifecycle calls.
If you want, paste your token-generation snippet and the parts of your client reconnect/cleanup code and I’ll point out the exact lines to change.
Sources: Avoiding Room ID Reuse When Re-Creating Rooms With the Same Name | server-sdk-kotlin | livekit/livekit_composite | DeepWiki | Server-side | livekit/livekit_composite | DeepWiki | Pricing | LiveKit | Pricing | LiveKit, with interactive elementsrefined-smartphone-96649
03/22/2026, 5:13 AMtall-airline-16756
03/22/2026, 5:13 AMrefined-smartphone-96649
03/22/2026, 5:39 AMtall-airline-16756
03/22/2026, 5:39 AMrefined-smartphone-96649
03/22/2026, 5:41 AMtall-airline-16756
03/22/2026, 5:41 AMrefined-smartphone-96649
03/22/2026, 6:18 AMtall-airline-16756
03/22/2026, 6:19 AMrefined-smartphone-96649
03/22/2026, 7:11 AMtall-airline-16756
03/22/2026, 7:11 AMrefined-smartphone-96649
03/22/2026, 7:34 AMtall-airline-16756
03/22/2026, 7:34 AMrefined-smartphone-96649
03/22/2026, 9:45 AMtall-airline-16756
03/22/2026, 9:45 AMrecord=False) or disable Observability at the project level.
Planned improvements and monitoring
• Automatic export of Observability data to customer-managed storage is planned (“coming soon”). I’ll notify you at jay@enluma.health when that feature or an Australia (Sydney) observability region becomes available.
If you want, I can:
• Provide a small script example to download session artifacts from the dashboard/API and upload them to Azure Blob or GCS (so you can automate interim exports).
• Walk you through configuring self-hosted recordings to write directly to an Australia bucket.
• Confirm specifically how to disable Observability for sessions so no US‑based audio is stored.
Which of those would be most helpful right now?
, with interactive elements