Context & Hand-offs Between Agents
Hand-off contracts, passing references instead of payloads, isolation versus sharing, and validating at the boundary.
When one agent passes work to another, important details can get lost, like a game of telephone. Pass a clear package: the original goal, facts, decisions, what was tried and the answer format. Send links to big files instead of copying them.
- Hand-off
- The package of information passed between agents.
- Artifact
- A file or result saved to be used later.
- Schema
- The exact format an answer must follow.
Without this, details get lost like a game of telephone.
In a single-agent system, the context is just the conversation. In a multi-agent system, you build the context on purpose at every boundary. You decide what each agent sees and what leaves it. Done well, this is the whole advantage of the approach: each agent works in a clean, relevant window. Done badly, it is a game of telephone. Information is reworded, trimmed and bent at every hand-off, until the last agent is solving a different problem from the one the user asked.
The hand-off contract
Treat every transfer from one agent to another like an API with a schema, not like a chat message. A good hand-off carries:
- The goal: the user's original request word for word, never a paraphrase of a paraphrase.
- The task: what this agent must do, and its definition of done.
- The relevant facts: only what this agent needs, either checked or clearly marked as unchecked.
- Limits and decisions: choices already made that must not be argued again, such as budget, tone and scope.
- What was tried: dead ends and failed attempts, so the next agent does not repeat them.
- Files by reference: IDs or paths to documents and data, not their full contents.
- The expected return shape: a schema that the receiving agent's answer must fit.
{
"trace_id": "run_8f3a",
"goal_verbatim": "Draft a renewal-risk summary for Acme Corp before Thursday's QBR",
"task": "Pull Acme's last 90 days of support tickets and classify churn-risk signals",
"done_when": "Every ticket is classified and top 3 risks are cited with ticket IDs",
"facts": [
{ "text": "Acme is on the Enterprise plan, renews 2026-11-30", "verified": true },
{ "text": "Champion left the company in September", "verified": false, "source": "CRM note" }
],
"decisions": ["Audience is the account exec, not the customer", "Keep under 200 words"],
"tried": ["Searching tickets by company name missed subsidiaries; use account_id=4471"],
"artifacts": [{ "kind": "ticket_export", "ref": "store://runs/8f3a/tickets.jsonl" }],
"return_schema": "RiskSummary"
}Pass references, not payloads
Do not copy large outputs, such as a scraped page, a data table or a generated document, through the lead's context on their way to the next agent. Write them to storage, such as files, object storage or a database. Then pass a reference and a short summary. This keeps every context window small. It avoids the losses that happen when a model retypes a long text. And it gives you a record of exactly what each agent produced.
Keeping apart, or sharing
There is a real tension here. Keeping contexts apart keeps them clean and cheap. Sharing stops agents from making decisions that clash because they do not know what the others decided. A practical answer is to keep the working context separate and to share the decision log. The working context is the long, noisy part: searching, reading and tool results. The decision log is the short, important part: what was decided and why. Each agent sees the goal, the decision log and its own task. The noise stays local.
Shrinking without losing the plot
- Summarize at the boundaries, not all the time. One deliberate summary at a hand-off is easier to audit than a constant blur.
- Keep the goal and the limits out of the summarizer's reach. Pin them word for word in every context.
- Make summaries structured, with decisions, open questions and files. Avoid free-form stories.
- Keep the full detail somewhere it can be fetched, so a later agent can dig in when the summary is not enough.
Check at the boundary
The hand-off is the cheapest place to catch errors. Check the outgoing package against its schema before you send it. Check the returning result before the lead uses it. A worker that returns broken JSON or an empty field should cause an immediate retry or a flagged gap. It should not slip quietly into the combining step, where it turns into a confident-sounding invention.
- ✓The context at each boundary is made by you. Design it on purpose.
- ✓Hand-offs are contracts: goal, task, facts, decisions, dead ends, file references and a return schema.
- ✓Pass references to large files, and keep working contexts small.
- ✓Keep the noisy working context apart, share the short decision log, and check at every boundary.
Redesign a leaky hand-off
- Find or build a two-agent flow where agent A's free text is pasted into agent B's prompt.
- Run it five times. Note what information is lost or bent between A and B.
- Replace the pasted text with a structured hand-off like the one above, with files passed by reference.
- Run the same five cases again. Count how many distortions disappear.
Q1Why pass the user's goal word for word at every hand-off?show answer
Paraphrases drift. After a few hops the receiving agent may be solving a slightly different problem. The exact goal text ties every agent to the real request.
Q2What is the benefit of passing a reference to a file instead of its contents?show answer
Smaller contexts, no losses from retyping long text, and a record of exactly what was produced.
Q3How do you combine keep contexts apart with agents must not make clashing decisions?show answer
Keep the long, noisy working context apart, but share a short decision log so every agent knows what has already been decided.