Envelope
Writing

AI agent handoffs: how to design clean transitions between agents

July 2026 · 6 min read

A handoff is the contract between agents — what one produces and what the next expects. Most multi-agent systems fail here. Here's how to design handoffs that don't break.

Quick answer

An AI agent handoff is the point where one agent finishes its work and passes the result to the next. It's a contract: the upstream agent commits to producing a specific output; the downstream agent expects to receive it in a specific form. When that contract is undefined or assumed rather than designed, handoffs fail — and the failure is usually silent until something downstream goes wrong.

Why handoffs fail

Most multi-agent systems break at the seams, not at the centre. The individual agents work fine in isolation. The problem is the gap between them.

Format mismatches. Agent A produces a prose summary. Agent B expects a structured JSON object with specific fields. Neither agent is wrong — they just weren't designed to connect.

Missing context. Agent A completes its task and passes the output, but the context that shaped that output — the original brief, the constraints, the decisions made along the way — doesn't travel with it. Agent B starts from incomplete information.

Ambiguous completion signals. Agent A isn't sure whether it's done. It produces output anyway. Agent B doesn't know whether what it received is final or partial.

No error contract. Agent A hits a problem and returns something — but "something" isn't a well-formed result. Agent B has no handling for that case, so it proceeds as if everything is fine.

Each of these is a design failure, not a model failure. They can all be prevented by specifying the handoff before either agent is built.

Two types of handoff

Not all agent transitions work the same way. It helps to distinguish between two types:

Pipeline handoffs. Agent A produces an output that becomes Agent B's input. One finishes before the other starts. The dependency is sequential and the output format is the primary design concern. A research agent passing a brief to a drafting agent is a pipeline handoff.

Reporting-line handoffs. An orchestrator agent delegates a task to a sub-agent, waits for a result, and then decides what to do next based on what came back. The sub-agent doesn't decide where its output goes — it returns to the agent that called it. The primary design concern here is the return format and the handling of partial or failed results.

Most production workflows have both. A pipeline runs left to right; orchestrators sit above it and delegate down. Design both types explicitly.

Designing the output contract

Every agent that passes work to another agent needs a defined output contract. This is the spec the upstream agent writes to. It should answer:

  • What format? JSON, markdown, plain text, a structured object — be explicit. "A summary" is not a format.
  • What fields? If it's structured, name every field. Mark which are required and which are optional.
  • What's the completion signal? How does the downstream agent know the output is final and not partial? A status field, a specific key, a schema that validates correctly?
  • What happens on failure? What should the upstream agent return if it can't complete its task? An error object with a reason field is better than an empty result or a prose explanation of what went wrong.

Write this as a schema, not a description. A description leaves room for interpretation; a schema doesn't.

Designing the input contract

The downstream agent has its own contract — what it needs to receive in order to do its job. This is the input contract, and it's just as important as the output contract.

  • What's required? The downstream agent should be able to validate its input before starting. If a required field is missing, it should fail loudly with a clear error rather than proceeding with incomplete information.
  • What's optional? Some fields improve output quality if present but aren't blocking. Distinguish these from required fields.
  • What context needs to travel? Often the upstream output alone isn't enough. The original brief, the user's goal, constraints set upstream — decide what travels with every handoff and encode it explicitly.

The gap between the upstream output contract and the downstream input contract is where most handoff failures hide. Design them together and validate that they match.

What context should travel with a handoff

Individual agents have limited context windows. A handoff isn't just an output — it's a decision about what the downstream agent needs to know.

A useful rule: pass the minimum context that lets the receiving agent do its job without needing to ask questions or make assumptions about decisions already made upstream.

That typically means:

  • The result of the upstream step (the primary output)
  • The original goal or brief (so the downstream agent knows what success looks like)
  • Any constraints or decisions made by a human gate earlier in the workflow
  • An error or status field indicating whether the upstream step completed cleanly

What to drop: intermediate reasoning, tool call logs, raw data that's already been processed. These add token cost without adding useful information for the downstream step.

Error handling at the handoff

Handoffs need explicit failure modes. When an upstream agent can't complete its task cleanly, the downstream agent needs to know — and needs a structured way to handle it.

Define at least three states for every handoff:

Complete. The upstream agent finished its task. The output is valid and the downstream agent can proceed.

Partial. The upstream agent made progress but couldn't complete. The output may still be useful, but the downstream agent should know it's working with incomplete input.

Failed. The upstream agent couldn't produce usable output. The downstream agent should not proceed — it should escalate, retry, or route to a human gate.

An error object with a status field and a reason string handles all three cleanly. An agent that returns prose when it fails is far harder for downstream agents to handle reliably.

Worked example: research → draft → review

Here's a three-agent pipeline with explicit handoff specs at each transition.

Agent 1: Research

  • Input: { topic: string, constraints: string[], depth: "brief" | "detailed" }
  • Output: { status: "complete" | "partial" | "failed", findings: Finding[], sources: string[], reason?: string }
  • A Finding is { claim: string, evidence: string, confidence: "high" | "medium" | "low" }

Handoff 1 → 2: Agent 2 receives the full output object. If status === "failed", it escalates. If status === "partial", it proceeds but flags the draft as low-confidence.

Agent 2: Draft

  • Input: { research: ResearchOutput, brief: string, format: "email" | "report" | "summary" }
  • Output: { status: "complete" | "failed", draft: string, word_count: number, flags: string[], reason?: string }
  • flags carries anything the drafting agent wants the reviewer to check — uncertain claims, gaps in the research, tone decisions that may need review.

Handoff 2 → 3: Agent 3 receives the draft and the original brief. The flags array tells it where to focus review effort. If status === "failed", it routes to a human rather than reviewing an empty draft.

Agent 3: Review

  • Input: { draft: DraftOutput, brief: string, review_criteria: string[] }
  • Output: { status: "approved" | "revision_required" | "escalate", feedback: string, revised_draft?: string }

Each handoff is fully specified before any agent is built. A developer implementing any one of these agents knows exactly what they'll receive and exactly what they need to produce.

Design your AI agents in Envelope

Envelope turns a plain-language description of what you want an AI agent system to do into a complete design — roles, tools, model assignments, and human review gates. Free to start, no code required.

Start designing →

Frequently asked questions

How is an agent handoff different from a function call?

A function call is a technical implementation — one piece of code calling another. An agent handoff is a design decision — defining what one agent is responsible for producing and what the next needs to receive. Handoffs exist at the workflow design level; how they're implemented (function calls, message queues, API calls) is an engineering decision. The design contract needs to be clear before the implementation choice matters.

Do I need to define handoffs if I'm using an orchestration framework?

Yes. Frameworks handle the mechanics of passing data between agents — routing, queuing, retrying. They don't define what the data should look like or what the downstream agent should do with it. That's a design decision no framework makes for you. Skipping the handoff spec because the framework handles "the connection" is the most common reason multi-agent systems behave unpredictably in production.

What's the right level of structure for a handoff output — JSON or natural language?

JSON (or a typed schema) for machine-to-machine handoffs between agents. Natural language for anything that passes through a human gate or gets surfaced to a user. When an agent's output is consumed by another agent, structure is essential — an LLM interpreting free text introduces variability at every step. When the output is for a human to read and approve, natural language is appropriate. Many workflows have both: a structured payload for the next agent plus a human-readable summary for the gate.

How do I handle a handoff when the upstream agent is non-deterministic?

Define the output schema strictly and validate before passing. The upstream agent can produce variable content — that's fine — but it should always produce a valid structure. Use a validation step (a lightweight schema check, not another full agent pass) between the upstream output and the downstream input. If validation fails, route to error handling rather than passing an invalid payload downstream.

Should context from earlier in the workflow travel through every handoff?

Not all of it — be selective. The original goal or brief usually should travel all the way through, since every agent needs to know what success looks like. Intermediate reasoning, raw tool outputs, and data that's already been processed usually shouldn't — they add token cost and noise without helping the downstream agent do its job. Design a "workflow context" object that travels through every handoff, and keep it minimal: goal, constraints, any human-gate decisions, status.

What's the most common handoff mistake in practice?

Assuming the downstream agent can figure out what it received. Teams design the agents and forget to specify the connection. The first agent produces whatever seems natural; the second receives it and tries to interpret it. This works in testing when both agents were built by the same person who knows what was intended. It breaks in production — different runs, different outputs, edge cases the builder didn't consider. The fix is always the same: write the output and input contracts before writing the agents, not after.

Does your handoff structure hold up?

Paste your agent spec into the validator to check structure, role clarity, and tool access before you build.