The activation model
In a multi-agent system, only one agent is active at a time (per bridge). The active agent receives frames from the bus. Inactive agents exist but don’t process frames. Every agent has anactive property that defaults to True. In handoff scenarios, voice agents should start with active=False so only one is active at a time — the parent then activates the first one explicitly.
You control which agent is active using three methods:
handoff_to() is the most common — it’s a single call that transfers control from the current agent to another.
Building a handoff system
Let’s walk through how the two-agent handoff works. You need three pieces:1. A main agent with a bus bridge
The main agent owns the transport (audio I/O) and places aBusBridgeProcessor in its pipeline instead of an LLM. The bridge routes frames to whichever LLM agent is active:
2. LLM agents with bridged=()
LLM agents setbridged=() to receive frames from the bus. Each one runs its own LLM and defines its own system prompt:
bridged=() means the agent receives frames from all bridges. You can filter by bridge name with bridged=("voice",) if you have multiple bridges.3. Handoff via tools
The LLM decides when to transfer by calling a tool. The tool callshandoff_to():
LLMAgent, handoff_to() also accepts a messages parameter. These messages are injected and spoken by the current agent before the transfer happens — useful for announcing the handoff:
handoff_to("support", ...):
- The greeter is deactivated — it stops receiving frames from the bus
- The support agent is activated with the provided arguments
- The support agent’s
on_activated()fires, injecting the reason message into its LLM context - The support agent starts responding to the user
Activation arguments
When activating anLLMAgent, you can pass LLMAgentActivationArgs to give the target agent context about why it was activated:
Waiting for agents to be ready
Before you can activate an agent, it needs to be ready (its pipeline must be started). Use the@agent_ready decorator to declare a handler that fires when a specific agent registers:
Putting it all together
Here’s the full flow:1
Runner starts
AgentRunner creates the bus and starts the main agent’s pipeline.2
Client connects
The main agent creates child LLM agents and adds them via
add_agent().3
Agent becomes ready
The
@agent_ready handler fires on the parent. The main agent activates the greeter.4
User speaks
Audio flows: transport -> STT -> BusBridge -> bus -> greeter’s LLM -> bus -> BusBridge -> TTS -> transport.
5
LLM decides to transfer
The greeter’s LLM calls
transfer_to_agent. The tool calls handoff_to("support", ...).6
Handoff completes
Greeter deactivates, support activates with context. Audio now flows through the support agent.
What’s next
Handoff transfers a conversation between agents. But sometimes you need agents to do work in parallel. Next, let’s look at task coordination.Task Coordination
Dispatch work to multiple agents in parallel