I'm running into the below error during inbound ca...
# ask-ai
c
I'm running into the below error during inbound calls, where one agent completes a specific task and then hands off to another agent:
Copy code
unhandled exception while running the job task
Traceback (most recent call last):
  File \"/usr/local/lib/python3.10/site-packages/opentelemetry/util/_decorator.py\", line 71, in async_wrapper
    return await func(*args, **kwargs)  # type: ignore
  File \"/usr/local/lib/python3.10/site-packages/livekit/agents/ipc/job_proc_lazy_main.py\", line 286, in _traceable_entrypoint
    await self._job_entrypoint_fnc(job_ctx)
  File \"/opt/deployment/voice-agents-backend/main.py\", line 355, in entrypointx
    await agentToRun.entrypoint(ctx)
  File \"/opt/deployment/voice-agents-backend/screening_assistant.py\", line 2205, in entrypoint
    await session.start(
  File \"/usr/local/lib/python3.10/site-packages/livekit/agents/voice/agent_session.py\", line 595, in start
    raise RuntimeError(
RuntimeError: Only one `AgentSession` can be the primary at a time. If you want to ignore primary designation, use session.start(record=False).", "exc_info": "RuntimeError: Only one `AgentSession` can be the primary at a time. If you want to ignore primary designation, use session.start(record=False).
this is happening after upgrading livekit sdk from v1.0.12 to v1.0.20
t
Thanks for reaching out, Bharath. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I see the RuntimeError is raised during agent handoff after upgrading from v1.0.12 → v1.0.20: "Only one
AgentSession
can be the primary at a time." I'll help you resolve it. Short answer • Start the new session with recording disabled: use
await session.start(..., record=False)
. That prevents the session from becoming the primary recorder and avoids the conflict during handoffs. Why this works • The newer SDK enforces a single primary
AgentSession
when recording/observability is enabled. Disabling recording for the handoff session prevents duplicate primary designation. Next steps I recommend 1. Update the handoff code where you call
session.start(...)
to pass
record=False
. Example:
Copy code
await session.start(agent=your_agent, room=ctx.room, record=False)
1. If you require recording/observability for these sessions, consider: ◦ Only allowing one session to start with
record=True
(the intended primary), or ◦ Disable project/agent-level Agent Observability in the LiveKit dashboard for flows where multiple agents may be active. Quick question to help further • Do you need recording for these handoff sessions, or is it acceptable to disable recording during handoffs? If you need recording, tell me how you expect primary ownership to be handled so I can suggest specific patterns. If you want, paste the
session.start
call you currently use and I’ll show the exact change. Sources: Streamline Troubleshooting with Agent Observability
c
I need the recording for both the agents. So if I only start the first agent with record True and pass record False for the second agent, will the recording of the second agent also continue?
t
Thanks — I’m responding to your question about whether the second agent will be recorded if only the first agent’s session is started with
record=True
. Short answer • Yes. Recording is session-scoped, not agent-scoped. If you start the AgentSession with
record=True
, recording continues across the handoff and both agents will be recorded. Important details • Handoffs switch the active agent within the same `AgentSession`; they do not start a new session. • You cannot stop recording for the second agent by passing
record=False
during the handoff — that parameter applies when the session is started and persists for the session lifetime. • There’s no supported way to dynamically disable recording mid-session; recording stops only when the session ends. If you need per-agent separate recordings, tell me whether you can: • end the first session and start a new session for the second agent (so each session can have its own
record
setting), or • keep a continuous session and accept a single combined recording. Tell me which option you prefer and I’ll suggest the exact code changes. Sources: https://blog.livekit.io/streamline-troubleshooting-with-agent-observability/#/portal/signup| | https://blog.livekit.io/streamline-troubleshooting-with-agent-observability/#/portal|
c
Give me a solution for the first approach: end the first session and start a new session for the second agent (so each session can have its own
record
setting),
t
Thanks — I’ll walk you through ending the first session and starting a new one so each agent can have its own
record
setting. 1) Gracefully end the first session • Call
await session.shutdown(drain=True)
to let pending speech finish, then close any room connections if needed (e.g.,
await session.disconnect()
or your cleanup flow). 2) Create a new AgentSession for the second agent • Initialize a fresh
AgentSession
with the same audio/LLM/TTS config but the
record
value you want for the second agent. 3) Start the new session in the same room • Start the new session pointing at the same room reference so call continuity is preserved. Minimal Python example (adapt to your code structure):
Copy code
# end first session
await first_session.shutdown(drain=True)
# optional: await first_session.disconnect()

# create new session (record=True for second agent)
second_session = AgentSession(
    stt=..., llm=..., tts=..., vad=...,
    record=True
)

# start second session in same room
await second_session.start(agent=second_agent, room=ctx.room)
Key notes • Recording is session-scoped. Ending the first session and starting a new one gives each session its own
record
behavior. • Use
shutdown(drain=True)
to avoid cutting off speech. • Ensure you reuse the same room object/reference so the caller stays in the same room/connection. If you want, paste your current
session.start
/ shutdown code and I’ll show the exact edits. Sources: Agents (Node.js) | livekit/livekit_composite | DeepWiki | Job lifecycle | LiveKit docs
c
okay now what if I should have a single recording for both the sessions? how do I achieve this?
t
You can get a single continuous recording across multiple agent handoffs by recording the room (egress) instead of relying on session-level recording. Start a RoomComposite egress when the call/room starts and stop it when the call ends—that egress captures everything in the room regardless of which AgentSession is active. Quick steps 1. Start room-level egress at call start (or enable AutoEgress on your SIP dispatch rule). 2. Let agents hand off normally (they can be separate AgentSessions or single session handoffs). 3. Stop the egress only when the call/room ends. Minimal examples • Start egress (TypeScript SDK example):
Copy code
const info = await egressClient.startRoomCompositeEgress('room-name', {
  file: new EncodedFileOutput({ filepath: 'recordings/session-123.mp4', output: { case: 's3', value: new S3Upload({ /* ... */ }) } })
}, { layout: 'speaker' });
• Stop egress:
Copy code
await egressClient.stopEgress(info.egressId);
Notes and best practices • Recording is room-scoped: as long as the egress runs, all agent handoffs are recorded in one continuous file. • Do not stop/restart egress during handoffs (that creates separate recordings and gaps). • Use AutoEgress for fully automated start-on-call if you’re using SIP dispatch rules. • If you need per-agent metadata inside the single recording, emit markers/events to your logging system or include timestamped metadata; the recording itself is a continuous stream. If you want, tell me: • Which SDK/language you use for egress (Node/TS, Python, or REST) and whether you use SIP dispatch rules; I’ll give exact code/config snippets for your setup. Sources: RoomComposite Egress | LiveKit Docs | Agents and handoffs | LiveKit docs | Egress API | LiveKit docs | sip | livekit/livekit_composite | DeepWiki | Auto egress | LiveKit docs