Your multi_agent pipeline works fine in testing. Then you deploy it and watch it fail: Agent A finishes its task and "passes" to Agent B. But B has no idea what A did, what files it touched, or what errors it encountered.
This is the handoff failure: the moment context evaporates between sequential agents.
The Classic Handoff Disaster
{"from": "researcher", "to": "coder", "task": "build api"}
The receiving agent sees a task. But it has no evidence that research happened, no artifacts to work with, no awareness of constraints or edge cases discovered. It starts fresh. Wasted work. Broken outputs. Angry users.
Pattern 1: Artifact Chaining
Don't just pass instructions—pass evidence.
interface Handoff { from: string;
to: string;
nextTask: string;
artifacts: Array<{path: string, type: string, summary: string}>; // evidence
observations: Array<{finding: string, confidence: number}>; // discoveries
constraints: string[]; // limitations discovered
checksum: string; // verify continuity
}
Each agent appends artifacts. The receiver can verify: "Did research actually produce outputs? What did edge cases look like?"
Pattern 2: Contract Testing During Handoff
Before releasing control, validate what you received:
const contract = {
requiredArtifacts: ['research_summary.md', 'data_sources.json'],
expectedOutputs: ['src/**/*.ts'],
qualityThreshold: { sentiment: 0.7, completeness: 1.0 }
};
const verifyHandoff = (handoff: Handoff) => {
const missing = contract.requiredArtifacts.filter(a => !handoff.artifacts.some(x => x.path.includes(a)));
if (missing.length) throw new Error(`Missing artifacts: ${missing}`);
// Verify outputs match quality threshold
return handoff.checksum === computeChecksum(handoff.artifacts);
};
Pattern 3: Shared Memory Repository
The handoff should update a shared knowledge base:
class SharedMemory {
async write(namespace: string, key: string, value: any) {
// Durable storage, versioned
const entry = { key, value, timestamp: Date.now(), author: this.agentId };
await this.store.append(`${namespace}/${key}`, entry);
}
async read(namespace: string, key: string): Promise<any> {
const history = await this.store.getAll(`${namespace}/${key}`);
return history.reduce((acc, entry) => entry.value, {});
}
async query(namespace: string, filter: (entry: any) => boolean) {
const history = await this.store.getAll(namespace);
return history.filter(filter).sort((a, b) => b.timestamp - a.timestamp);
}
}
Now Agent B can query: "What did the researcher find?"
Top comments (0)