Skip to main content
Lesson 12 of 18 · Mistral Agents: Building Autonomous AI

Introduction to Multi-Agent Handoffs

Lesson 12 of 18 Updated November 3, 2026 Developer
On this page
  1. Why orchestrate multiple agents?
  2. How handoffs work
  3. Typical architecture
  4. Execution modes
  5. Output events
  6. Key takeaways

Why orchestrate multiple agents?

So far, you’ve worked with individual agents: one agent, its instructions, its tools. This model hits limits fast when a task requires heterogeneous skills. Take a market research request: you need to search for data, analyze it numerically, then produce a readable report. You could try handing everything to a single agent, with instructions that balloon with every new requirement until they become a contradictory brick of text that the model applies less and less effectively. The Mistral API offers an alternative: chains of specialized agents that pass the baton.

This is the concept of a handoff: one agent transfers control of the conversation to another agent better equipped for the current subtask. The conversation itself doesn’t change—only the hand holding the reins does.

How handoffs work

The mechanism mirrors exactly what a human organization does when facing a composite request. A router agent receives the initial query, like a switchboard operator taking a call. It analyzes the request, identifies which specialist agent is best positioned to handle it, and then transfers the conversation to that specialist. The specialist handles its subtask and, if it encounters a need beyond its scope, can transfer to a third agent. The final response flows back to the user, who sees only a single interlocutor.

Four benefits follow, and they reinforce each other. First, specialization: each agent has a limited scope and precise instructions. The web search agent doesn’t handle calculations, and vice versa. This improves response quality because no instruction contradicts another. Second, maintainability: changing a specialist’s behavior doesn’t impact others. You can swap its model, instructions, or tools without touching the rest of the system. Third, scalability follows directly—adding a capability means creating a new specialist agent and registering it as a handoff target. The router then selects it when the request matches. Finally, traceability: every handoff generates an agent.handoff event in the outputs, letting you reconstruct after the fact which agent handled which part of the request without instrumenting anything yourself.

Typical architecture

User
    │
    ▼
Router Agent (orchestrator)
    ├── Web Search Agent (web_search)
    ├── Calculator Agent (code_interpreter)
    ├── Writer Agent (specific instructions)
    └── Document Agent (document_library)

The router dynamically decides which agent to transfer to based on the query. It isn’t limited to a single handoff: it can also orchestrate sequential flows, such as search then calculate then write, with each step enriching the context for the next.

Let’s follow a real request: “Find the current ECB interest rate and calculate the compound effect over 10 years for a €100K investment.” The Finance agent, acting as router, receives the request and sees it contains two distinct needs. It first transfers to the Web Search agent, which fetches the current ECB rate—a datum no model can know from memory. A second handoff passes control to the Calculator agent, which applies the compound interest formula to the rate just found. The user receives a single result, accompanied by the search sources and calculation details.

Execution modes

The Mistral API offers two modes for handoffs, and you choose at conversation startup. Server mode is the default.

response = client.beta.conversations.start(
    agent_id=router_agent.id,
    inputs="Complex query",
    handoff_execution="server"
)

Mistral then handles everything automatically: transfers, agent execution, and response synthesis. You receive only the final result, which is convenient and sufficient as long as you don’t need to interpose anything between steps.

response = client.beta.conversations.start(
    agent_id=router_agent.id,
    inputs="Complex query",
    handoff_execution="client"
)

In client mode, you receive handoff events and decide what to do at each step. Choose this mode when a human must approve a sensitive transfer, when you need to log every handoff for audit purposes, or when your business logic requires routing the model can’t infer. The lesson dedicated to these two modes will detail the trade-offs.

Output events

When a handoff occurs, three types of events appear in the outputs:

  • agent.handoff — Agent A transfers to Agent B (contains both agent IDs)
  • tool.execution — Agent B executes its tools
  • message.output — Agent B’s response
for entry in response.outputs:
    if entry.type == "agent.handoff":
        print(f"Transfer: {entry.previous_agent_id} → {entry.next_agent_id}")
    elif entry.type == "tool.execution":
        print(f"Tool executed: {entry.tool_name}")
    elif entry.type == "message.output":
        print(f"Response: {entry.content}")

Write this loop during your first trials, even before the system is complete. A multi-agent system that answers correctly but whose path you can’t trace becomes impossible to fix the day it answers wrong: you won’t know if the router misdirected, if the specialist performed poorly, or if the handoff got lost along the way. Three well-placed print statements save you from this blindness.

Key takeaways

  • Handoffs let an agent transfer control to another specialized agent
  • Typical architecture: router agent → specialist agents
  • Server mode = fully automatic; client mode = manual control of transfers
  • Each handoff generates a traceable event in the outputs
  • There’s no limit to the chaining depth between agents