Documentation Index
Fetch the complete documentation index at: https://docs.pipecat.ai/llms.txt
Use this file to discover all available pages before exploring further.
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 worker has anactive property. LLMWorker defaults to active=False, so in a handoff setup the LLM agents start inactive and the main agent activates the first one explicitly.
You control which agent is active with two methods:
| Method | What it does |
|---|---|
activate_worker(name, args=...) | Activate another agent |
deactivate_worker(name) | Deactivate another agent |
activate_worker(name, deactivate_self=True) | Hand off: deactivate self, activate target |
deactivate_self=True to activate_worker() is the most common form — 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. The main agent is a PipelineWorker wrapping that pipeline:
The
BusBridgeProcessor is what lets a transport-owning agent delegate its
LLM turn to other agents over the bus. For how it routes frames and how to
filter by bridge name, see Understanding the Bus
Bridge.2. LLM agents with bridged=()
Each LLM agent is anLLMWorker created with bridged=() so it receives frames from the bus. Subclass LLMWorker to add tools, then instantiate it with its own LLM:
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 callsactivate_worker() with deactivate_self=True:
LLMWorker, activate_worker() also accepts a messages parameter. These messages are injected and spoken by the current agent before the transfer happens — useful for announcing the handoff:
activate_worker("support", deactivate_self=True, ...):
- 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 anLLMWorker, pass LLMWorkerActivationArgs via args= to give the target agent context about why it was activated:
Activating the first agent
Before you can activate an agent, it needs to be ready (its pipeline must be started). The simplest place to kick off the conversation is the transport’son_client_connected handler, where you activate the first agent:
@worker_ready decorator instead. See Agent registry and discovery.
Putting it all together
Here’s the full flow:Runner starts
WorkerRunner creates the bus. You add every agent (the main agent and
the LLM agents) with runner.add_workers(...).User speaks
Audio flows: transport -> STT -> BusBridge -> bus -> greeter’s LLM -> bus ->
BusBridge -> TTS -> transport.
LLM decides to transfer
The greeter’s LLM calls
transfer_to_agent. The tool calls
activate_worker("support", deactivate_self=True, ...).What’s next
Handoff transfers a conversation between agents. But sometimes you need agents to do work in parallel. Next, let’s look at job coordination.Job Coordination
Dispatch work to multiple agents in parallel