Multi-Agent and Handoff: Dividing Tasks Across Agents
When a single AI agent is made responsible for a complex business process, structural bottlenecks quickly appear in production. A prompt that has to unify twenty different tools, thirty exception rules, and five different subject domains loses reliability due to instruction dilution. The model gets overloaded with excess context, picks the wrong functions, or ignores subtle constraints. The solution to this scaling problem lies in specialization: breaking a large task down into autonomous, focused agents that hand off work, status, and context to each other through structured handoffs.
In this article, we analyze how handoff mechanisms work, which architectural patterns are available, how context and status safely migrate between agents, and which specific risks arise in distributed agent systems. For a fundamental overview of how individual agents reason and call functions, the guide on prompt patterns for agents offers essential background knowledge on tool orchestration and loop structures.
The Limits of the Monolithic Agent
A single monolithic agent seems attractive at the start of a project because of the minimal orchestration overhead. Only one system prompt is needed, all available tool definitions are passed along in a single API call, and the language model independently decides which steps to take. In production environments, however, this setup runs into hard operational and cognitive limits.
First, the chance of picking the wrong function increases exponentially as the function catalog grows. When a model has to choose among dozens of JSON schemas with overlapping parameter structures, semantic confusion and faulty arguments arise. Second, a monolithic setup consumes a disproportionate number of tokens. At every iterative step in a reasoning loop, the full function list and system prompt must be reprocessed through the context window. This not only increases the cost per interaction but also significantly slows down response time (Time To First Token).
Third, a monolithic agent introduces substantial security risks. Tools with far-reaching privileges, such as modifying a database or executing a payment, exist in the same execution space as tools that parse untrusted user input. By splitting the system modularly into domain-specific components — such as a triage agent, a verification agent, and a mutation agent — the power granted at each step stays strictly contained.
What Exactly Is a Handoff?
A handoff is the controlled mechanism by which active execution control, conversation history, and application state are transferred from one agent to another. Whereas a standard function call (tool call) merely retrieves data and immediately returns control to the same agent, a handoff ends the sending agent's active cycle and designates a new agent as the primary executor.
Technically, a handoff is modeled as a specialized tool call or an explicit routing signal. A triage agent, for example, has a function such as transfer_to_billing(reason, customer_id, context_summary). As soon as the language model selects this function, the application runtime intercepts the signal. The runtime closes off the current execution context, loads the target agent's system prompt and tool definitions, transforms the state, and starts the new specialist's reasoning loop.
The crucial difference from a static pipeline or a classic function call lies in autonomy: the receiving agent gets the freedom to run its own reasoning loop within its own domain, call its own tools, and in turn potentially initiate another handoff to a next specialist or back to the triage layer.
Architecture Patterns for Multi-Agent Collaboration
The topology of the mutual communication determines how robust and manageable the agent system is. In modern architectures, we distinguish three dominant patterns, each with its own strengths and operational challenges:
| Pattern | Topology | Advantages | Drawbacks & Risks |
|---|---|---|---|
| Supervisor / Router | Central orchestrator directs specialized sub-agents | Tight control, easy auditability, no direct coupling between workers | Single point of failure (SPOF) at the router; extra latency due to central triage |
| Decentralized Handoff (Swarm) | Peer-to-peer transfer between agents with no central boss | Flexible, low overhead, natural conversation flow for complex journeys | Risk of infinite ping-pong loops; harder to trace and debug |
| Hierarchical Graph | Layered structure with explicit state transitions and decision trees | Deterministic routing, formal state guarantees, robust error handling | Requires a formal graph definition and strict state management upfront |
When designing complex systems with formal state transitions, it's crucial to understand how transitions between states are recorded; read the guide on the shift from prompt engineering to graph engineering to see how deterministic graphs regulate agent behavior.
1. The Supervisor Pattern
In the supervisor model, one central LLM agent acts as air traffic controller. The supervisor analyzes the incoming request, determines which specialist should perform the task, delegates the work, and receives the final result. The sub-agents never communicate directly with each other; all data flows through the central orchestrator. This makes logging and compliance easy, but creates a bottleneck when the supervisor misinterprets subtle nuances from the user conversation.
2. The Peer-to-Peer Handoff Pattern (Swarm)
In a peer-to-peer model (often called a swarm architecture), agents can transfer control directly to each other without intervention from a central manager. Agent A determines that a question falls outside its domain and hands the session directly to Agent B. This lowers latency and avoids having to consult a central supervisor at every step. The challenge here lies in governance: without central control, transfers must be strictly bounded to prevent circular delegation loops.
3. The Hierarchical Network
For enterprise workflows, supervisors and peer-to-peer transfers are combined in a hierarchical structure. A main triage delegates to a domain cluster (for example, 'Customer Service'), within which specialized agents (such as 'Billing,' 'Returns,' and 'Account Management') carry out peer-to-peer handoffs. Only once the entire domain problem is resolved does control return to the overarching orchestration level.
Context and State Management During the Handoff
The success of a handoff stands or falls with how data migrates between agents. When a user has already spent five minutes providing order numbers and error messages to an intake agent, the receiving specialist must not, under any circumstances, ask for that information again. At the same time, we want to prevent the specialist's context window from getting polluted with irrelevant intermediate steps from the intake.
There are two primary strategies for state transfer:
Strategy A: Duplicating the Full Chat History
In this approach, the complete list of previous user and assistant messages is copied into the new agent's context window. The new agent simply gets its own system prompt plus the existing message sequence.
Advantage: No information loss; all context is preserved verbatim.
Disadvantage: Rapid increase in token usage, higher latency, and a risk of hallucinations because the new agent sees earlier tool calls that don't belong to its own toolset.
Strategy B: Structured State Payload (Context Slicing)
In this pattern, the sending agent extracts the relevant data and packages it into a validated JSON object. The new agent starts with a clean slate: a specific system prompt, the compact state payload, and only the most recent interactions.
Advantage: Minimal token usage, sharp model focus, and strict separation of responsibilities.
Disadvantage: Risk of data loss if the sending agent fails to include an essential detail in the payload.
Example: Implementing a Handoff Mechanism in Python
Below is a concrete and robust implementation of a peer-to-peer handoff architecture in Python. We use a custom exception class to interrupt the control flow from tool calls and hand it off to the runtime:
import json
from typing import Dict, Any, List, Optional
class HandoffException(Exception):
"""Signaal om de huidige agentloop te onderbreken en over te dragen."""
def __init__(self, target_agent: str, payload: Dict[str, Any]):
self.target_agent = target_agent
self.payload = payload
# Tool definitie voor de triage agent
def transfer_to_technical_support(issue_type: str, severity: str, context_notes: str):
"""Draag het gesprek over aan de tweedelijns technische ondersteuning."""
raise HandoffException(
target_agent="tech_support",
payload={
"issue_type": issue_type,
"severity": severity,
"context_notes": context_notes
}
)
# Definities van beschikbare agents
AGENT_REGISTRY = {
"triage": {
"system_prompt": "Je bent de triage-assistent. Analyseer het probleem en draag over.",
"tools": [transfer_to_technical_support]
},
"tech_support": {
"system_prompt": "Je bent de technische specialist. Los bugs en serverproblemen op.",
"tools": []
}
}
class AgentOrchestrator:
def __init__(self, max_handoffs: int = 3):
self.max_handoffs = max_handoffs
self.global_state: Dict[str, Any] = {}
def execute_session(self, initial_agent: str, user_input: str) -> str:
current_agent_name = initial_agent
handoff_count = 0
messages: List[Dict[str, str]] = [{"role": "user", "content": user_input}]
while handoff_count <= self.max_handoffs:
agent_config = AGENT_REGISTRY[current_agent_name]
try:
# Simuleer de LLM-stap en eventuele tool-executie
# In productie roept de runtime hier de provider API aan
if current_agent_name == "triage" and "server down" in user_input.lower():
# De triage agent besluit de handoff tool aan te roepen
transfer_to_technical_support(
issue_type="infrastructure_outage",
severity="critical",
context_notes="Klant meldt complete downtime van productieserver."
)
# Als er geen handoff plaatsvindt, retourneert de agent het antwoord
return f"[{current_agent_name}] Probleem succesvol verwerkt."
except HandoffException as handoff:
handoff_count += 1
current_agent_name = handoff.target_agent
# Werk de globale applicatiestatus bij met de payload
self.global_state.update(handoff.payload)
# Context Slicing: reset berichten met een compacte statusinjectie
messages = [
{
"role": "system",
"content": f"{agent_config['system_prompt']}\nContext: {json.dumps(self.global_state)}"
},
{
"role": "user",
"content": f"Vervolg actie vereist voor issue: {self.global_state.get('issue_type')}"
}
]
continue
raise RuntimeError("Maximale handoff-drempel overschreden: mogelijke oneindige lus.")
Common Failure Modes and Edge Cases
When moving from a single agent to multiple collaborating agents, the problems shift from prompt phrasing to network and application dynamics. There are four specific failure modes that occur structurally:
1. The Infinite Ping-Pong Cycle
When two agents' domain boundaries overlap, a situation can arise where Agent A hands the task off to Agent B, after which Agent B decides that a subtask should still be handled by Agent A after all. Without active detection, this leads to dozens of API calls within seconds. A robust orchestrator maintains a directed graph (DAG) of handoffs within the session and breaks the cycle as soon as a repeated transition occurs.
2. Context Erosion (The Telephone-Game Effect)
When a chain consists of three or more consecutive handoffs where a summary is passed along each time, context erosion occurs. Just like in the well-known game of telephone, each layer of abstraction loses specific details, such as serial numbers, exact error messages, or timestamps. The mitigation for this is separating volatile dialogue context from an immutable global data buffer (immutable session state) that's managed directly by the host application.
3. Dangling Asynchronous Tasks (Zombie Executions)
If an agent starts a long-running tool call (such as generating a financial report) and immediately initiates a handoff afterward, the tool output can arrive once the new agent is already active. If the new agent doesn't recognize the incoming callback format, the session crashes. Handoffs must therefore be atomic: a transfer may only be finalized once all of the current agent's active I/O processes have completed.
4. Ambiguous Intent in Multi-Domain Questions
When a user asks two questions in one message ("Where is my order, and how do I change my IBAN?"), a simple router often fails by selecting only one of the two questions. In that case, an advanced handoff pattern requires a splitting mechanism (Fork-Join), where two specialized agents are activated in parallel, after which an aggregator merges the answers.
When agent loops get stuck or show unexpected behavior, the step-by-step plan for debugging agentic loops helps systematically isolate recursive calls, missing break conditions, and faulty tool responses.
Token Economics and Latency: The Hidden Costs
Although multi-agent architectures improve precision, they introduce specific cost considerations that vary by architecture type. It's a misconception that multi-agent systems are inherently more expensive than monolithic agents; the actual cost depends on the chosen context strategy.
| Architecture | Prompt Tokens per Step | Number of Model Calls | Average Latency | Cost Profile |
|---|---|---|---|---|
| Monolith (Large Context Window) | High (all tools & rules at every step) | Low to medium | Average per step | High for long sessions due to cumulative input tokens |
| Supervisor / Router | Low for specialists, average for the router | High (router call + specialist call) | High (sequential waiting on routing) | Predictable; saves on specialist calls |
| Peer Handoff with Context Slicing | Very low (compact payload per agent) | Minimal (no intermediate supervisor) | Low (direct transition) | Most cost-efficient for complex, long workflows |
When calculating the total operational cost, you need to account for the handoff overhead: every transfer requires at least one generation step for the payload and one initial prompt processing step for the receiving agent. However, once a task involves more than five iterative tool steps, the savings from a compact context window comfortably offset this initial overhead.
Measurement Methods and Observability for Handoff Systems
Evaluating a distributed agent system requires specific metrics that go beyond traditional response times and token counters. To monitor the health of the architecture, four core dialogue statistics are used:
1. First-Pass Routing Accuracy: The percentage of initial handoffs where the receiving agent can successfully complete the task without a corrective transfer to a third agent being needed. A score below 85% usually points to unclear tool descriptions in the router.
2. Handoff Depth & Churn Rate: The average number of transfers per user session. A sudden rise in handoff depth often indicates unclear domain boundaries between agents, causing tasks to be pushed back and forth.
3. Payload Completeness Ratio: The extent to which the receiving agent can act immediately without having to ask the user again for missing entities. This can be measured automatically with an LLM-as-a-judge evaluation test.
4. Transition Latency: The pure processing time between the moment Agent A initiates the handoff and Agent B generates its first token. This metric exposes bottlenecks in database I/O or state serialization.
To validate whether a composed agent chain actually performs better than a single prompt, the overview on evaluating AI agents offers detailed benchmarks for trajectory analysis and success rates.
Practical Example: An E-Commerce Returns and Fraud Flow
Let's look at a realistic production environment: an e-commerce platform that processes return requests. This process involves three specialized agents:
Triage Agent: Welcomes the customer, identifies the order number, and determines the intent (return, defective product, or complaint). Has only read tools to look up orders.
Fraud & Policy Agent: Assesses whether the return falls within the 30-day window and checks the account's risk profile. Has access to internal payment history and fraud registers.
Fulfillment Agent: Generates the return label, books the time slot with the courier, and updates the inventory status. Has write access in the ERP system.
When a customer reports that a device arrived defective, the handoff journey looks like this:
1. The Triage Agent extracts the order number and calls transfer_to_policy(order_id="ORD-9812", reason="damaged_on_arrival") .
2. The Policy Agent validates the purchase date and concludes that a direct exchange is allowed. This agent then calls transfer_to_fulfillment(action="instant_replacement", return_type="prepaid_label") .
3. The Fulfillment Agent generates the label and sends the confirmation to the customer.
Each agent operates within its own strict security boundaries. It's simply impossible for the Triage Agent to accidentally generate a return label or view fraud registers, because that functionality is absent from its context and tool schema.
Conclusion and Implementation Guidelines
Multi-agent systems and handoff patterns transform monolithic, fragile prompts into modular, testable software components. By letting agents excel in one specific domain and regulating their mutual communication through validated payloads and hard transition limits, you get a robust architecture that can withstand complex production demands.
When building a new system, always start as simply as possible: begin with a single agent with a limited toolset. Only once instruction dilution sets in, per-step token costs become unsustainable, or strict security boundaries between tools are required is the move to a multi-agent structure with explicit handoffs justified.


