Multi-Agent Handoff 合同工程:别让 Agent 交接变成甩锅现场
Multi-Agent Handoff ååå·¥ç¨ï¼å«è®© Agent 交æ¥åæç©é ç°åº
AINativeè½¯ä»¶å·¥ç¨ 2026-08-14 0 é 读11åéå¾å¤å¢éç¬¬ä¸æ¬¡æå Agent æ¹æ Multi-Agentï¼ä»£ç çèµ·æ¥ä¼çªç¶âé«çº§âå¾å¤ï¼Planner è´è´£æä»»å¡ï¼Researcher è´è´£æ¥èµæï¼Coder è´è´£æ¹ä»£ç ï¼Reviewer è´è´£æéï¼æååäº¤ç» Publisher è¾åºç»æãDemo é¶æ®µè¿å¥ä¸è¥¿å¾é¡ºï¼çè³ä¼ç»äººä¸ç§éè§ï¼åªè¦æèè´£æç»ï¼ç³»ç»å°±èªç¶æ´å¯é ã
çä¸ç产åï¼æå®¹æåçå°æ¹æ°æ°ä¸æ¯æä¸ä¸ª Agent ç promptï¼èæ¯ Agent å Agent ä¹é´ç交æ¥ã䏿¸¸è¯´âæå·²ç»å®æäºâï¼ä¸æ¸¸æ¥å°çæ¯ä¸å¨è天记å½ï¼Reviewer 说â缺å°è¯æ®âï¼Coder 说âè¯æ®å¨åé¢ä¸ä¸æéâï¼Publisher åç°å°é¢ãæè¦ãæ ç¾é½æ²¡æï¼å´åä¸ç¥éåºè¯¥éåç»è°ãæåæ¥å¿éåªå©ä¸å¥å¾æ è¾çè¯ï¼handoff failedã
è¿ç¯æç« 讨论ä¸ä¸ªå¾çªä½å¾å ³é®çé®é¢ï¼Multi-Agent ç³»ç»éç handoffï¼ä¸è½åªæ¯æä¸ä¸è½®æ¶æ¯å¡ç»ä¸ä¸ä¸ª Agentï¼èåºè¯¥åå端æå¡ä¹é´ç API 䏿 ·ï¼æä¸ä»½æç¡®ç Handoff Contractã
æä¼æå®ææäºå±ï¼ä¸ä¸æé¢ç®ãç¶ææºãè¯æ®å ãæéè¾¹çãéªæ¶åæ§ãæç« éçä»£ç æ¯ä¸ä¸ªå¯è¿è¡ç TypeScript æå°å®ç°ï¼éç¹ä¸æ¯æ¡æ¶ç«æï¼èæ¯æâ交æ¥âè¿ä»¶äºä»çå¦ prompt åæå¯æ£æ¥ãå¯åæ¾ã坿æ¶çå·¥ç¨åè®®ã
ä¸ã为ä»ä¹ Multi-Agent æå åå¨äº¤æ¥å¤
å Agent ç失败é常æ¯è¾ç´æ¥ãç¨æ·ç»ä¸ä¸ªä»»å¡ï¼Agent è¾åºéäºï¼ä½ è½å´ç» promptãå·¥å ·è°ç¨ãæ£ç´¢ç»æå模åè½åææ¥ãMulti-Agent ç失败æ´éº»ç¦ï¼å 为éè¯¯ä¼æ²¿ç交æ¥é¾è·¯ä¼ æã䏿¸¸æ¼äºä¸ä¸ªçº¦æï¼ä¸æ¸¸å¯è½ä¼åºäºéè¯¯ç¶æç»§ç»å å·¥ï¼ä¸é´ Agent 误解äºä»»å¡è¾¹çï¼æåè¾åºçèµ·æ¥å®æ´ï¼ä½å ¶å®å·²ç»å离åå§ç®æ ã
è¿æå¾å¤ Agent SDK åç¼æææ¡£é½ä¼å¼ºè°å 个è½åï¼è§åãå·¥å ·è°ç¨ãä¸å®¶åä½ãç¶æä¿æãå¯è§æµæ§ãè¯ä¼°ä¸äººå·¥å®¡æ ¸ãè¿äºè½åé½éè¦ï¼ä½å®ä»¬ä¸é´ç¼ºäºä¸å±å¾å®¹æè¢«ä½ä¼°çä¸è¥¿ï¼åä½åæ¹å°åºäº¤æ¥äºä»ä¹ã
å¨çå®é¡¹ç®éï¼ææ´æ¿ææ Multi-Agent 失败åæäºç±»ã
第ä¸ç±»æ¯ä¸ä¸æä¸¢å¤±ãPlanner æä»»å¡ææä¸ä¸ªåä»»å¡ï¼ä½åªæå½åå任塿 é¢ä¼ ç» Researcherï¼æ²¡æä¼ åå§ç¨æ·ç®æ ãçº¦ææ¡ä»¶åç¦æ¢äºé¡¹ãResearcher 宿äºå±é¨æä¼ï¼æ´ä½å´éäºã
第äºç±»æ¯ç¶ææ±¡æãæä¸ª Agent å¨ä¸é´ä¿®æ¹äºä»»å¡å®ä¹ï¼æ¯å¦æâçæè稿âåæâåå¸æç« âï¼ä¸æ¸¸æ¿å°çç¶æå·²ç»å å«å±é©å¨ä½ï¼å´æ²¡æä»»ä½å°æ¹è®°å½è¿ä¸ªå¨ä½æ¯è°ææçã
第ä¸ç±»æ¯æéæ¼ç§»ã䏿¸¸åªè¢«å 许读æä»¶ï¼ä¸æ¸¸å´ç»§æ¿äºå叿éï¼æè Coder å¯ä»¥æ§è¡å½ä»¤ï¼Reviewer ä¹è«åå ¶å¦æ¿å°äºæ§è¡å½ä»¤çè½åã
第åç±»æ¯è¯æ®æé¾ãResearcher å¼ç¨äºæ¥æºï¼Coder æ Writer 卿¹åæ¶å æäºæ¥æºæ å°ãæç» Reviewer åç°æç« éæç»è®ºï¼ä½æ¾ä¸å°åªæ¡è¯æ®æ¯æã
第äºç±»æ¯éªæ¶ç¼ºå¤±ã䏿¸¸æ¥å°ä»»å¡åé»è®¤ç»§ç»æ§è¡ï¼å³ä½¿è¾å ¥ä¸å®æ´ä¹ç¡¬ç头ç®è¡¥ãç³»ç»è¡¨é¢ä¸âèªå¨åç¨åº¦å¾é«âï¼å®é æ¯å¨æé误ææåä¸å»ã
è¿äºé®é¢ä¸æ¯é âè¯·ä½ è®¤ç交æ¥âè½è§£å³çãAgent 䏿¯å ¬å¸åäºï¼ä¸ä¼å¤©ç¶çè§£ç»ç»æµç¨ï¼å®åªä¼æ ¹æ®å½åè¾å ¥åä¸ä¸æ¥ãä½ è¦è®©å®å¯é 交æ¥ï¼å°±å¿ é¡»æäº¤æ¥åè®®åè¿æ°æ®ç»æãç¶ææºåè¿è¡æ¶æ£æ¥éã
äºãHandoff Contract çæå°å®ä¹
ä¸ä¸ªç产å¯ç¨ç Handoff Contract è³å°è¦å å«å «ç±»å段ã
- taskï¼è¿æ¬¡äº¤æ¥è¦å®æä»ä¹ï¼ä¸æ¯æ´ä¸ªé¡¹ç®æ¿æ¯ï¼èæ¯å¯æ§è¡ä»»å¡ã
- ownerï¼ä¸æ¸¸æ¯è°ï¼ä¸æ¸¸æ¯è°ï¼è°å¯¹äº¤æ¥è¾å ¥è´è´£ã
- input bundleï¼ä¸æ¸¸å¿ 须读åçè¾å ¥å ï¼å æ¬åå§ç®æ ãå½ååä»»å¡ã约æãå·²å®æäº§ç©ã
- state cursorï¼ä»»å¡ç¶ææ¸¸æ ï¼è¯´æè¿æ¯ plannedãresearchedãdraftedãreviewed è¿æ¯ ready_to_publishã
- permission scopeï¼ä¸æ¸¸å 许åä»ä¹ï¼ä¸å 许åä»ä¹ã
- evidenceï¼æ¯æå½åç»è®ºçè¯æ®å ï¼å¯ä»¥æ¯ URLãæä»¶è·¯å¾ãæ¥å¿çæ®µãæµè¯ç»æãæªå¾ã
- acceptance criteriaï¼ä¸æ¸¸æ¥æ¶è¿æ¬¡äº¤æ¥åå¿ é¡»æ£æ¥ä»ä¹ã
- receiptï¼ä¸æ¸¸æ¥æ¶ãææ¶æè¦æ±è¡¥ä»¶çåæ§ã
注æï¼è¿ä¸æ¯æè天记å½ç»æåä¸ä¸é£ä¹ç®åãèå¤©è®°å½æ¯è¿ç¨ï¼ååæ¯è¾¹çãè天记å½å¯ä»¥å¾é¿ãå¾ä¹±ãå å«åºè¯ï¼ååå¿ é¡»çãæç¡®ãå¯éªè¯ã
LangGraph ç memory ææ¡£æçæè®°å¿å®ä¹ä¸º thread-scopedï¼æé¿æè®°å¿å®ä¹ä¸ºè·¨ thread ç namespace storeãMem0 è¿ç±»è®°å¿å±ä¹å¼ºè° AddãExtractãRecallãå®ä»¬è§£å³çæ¯âç³»ç»å¦ä½è®°å¾ä¸è¥¿âï¼ä¸æ¯â两个 Agent äº¤æ¥æ¶è°å¯¹è¾å ¥è´¨éè´è´£âãæä»¥ä¸è¦æ memory å½ handoff contractãMemory å¯ä»¥æ¯è¯æ®æ¥æºï¼contract ææ¯äº¤æ¥åè®®ã
ä¸ãä¸ä¸ªå¯è¿è¡ç TypeScript å忍¡å
ä¸é¢æ¯ä¸ä¸ªæå°å®ç°ã宿²¡æä¾èµå¤ææ¡æ¶ï¼åªè¡¨è¾¾ä¸ä»¶äºï¼äº¤æ¥è¾å ¥å¿ é¡»è¿ schemaï¼ç¶ææµè½¬å¿ é¡»åæ³ï¼æ¥æ¶æ¹å¯ä»¥ææ¶ã
type AgentRole = 'planner' | 'researcher' | 'writer' | 'reviewer' | 'publisher';
type HandoffState =
| 'planned'
| 'researched'
| 'drafted'
| 'reviewed'
| 'ready_to_publish';
type Permission =
| 'read_sources'
| 'write_artifact'
| 'run_tests'
| 'publish_external';
interface EvidenceItem {
id: string;
kind: 'url' | 'file' | 'log' | 'test' | 'screenshot';
ref: string;
claim: string;
capturedAt: string;
}
interface HandoffContract {
id: string;
task: string;
from: AgentRole;
to: AgentRole;
state: HandoffState;
originalGoal: string;
constraints: string[];
artifacts: string[];
permissions: Permission[];
evidence: EvidenceItem[];
acceptanceCriteria: string[];
contextBudget: {
maxTokens: number;
summaryRequired: boolean;
mustInclude: string[];
};
}
interface HandoffReceipt {
handoffId: string;
receiver: AgentRole;
status: 'accepted' | 'rejected' | 'needs_more_input';
missing: string[];
acceptedAt: string;
}
è¿ä»½ç»æéæå®¹æè¢«å¿½ç¥çæ¯ contextBudgetãå¾å¤ Multi-Agent ç³»ç»ä¼æâä¸ä¸æçªå£è¶³å¤å¤§â误解æâå¯ä»¥ä¸åä¸ä¸ææ²»çâãä¸ä¸æè¶å¤§ï¼è¶éè¦é¢ç®ãå ä¸ºä¸æ¸¸ Agent ä¸åªæ¯è¯»ä¸ä¸æï¼å®è¿ä¼è¢«ä¸ä¸æéçæ§ä»»å¡ãåºå¼ç»è®ºãæªç¡®è®¤å设干æ°ã
æçç»éªæ¯ï¼handoff è¾å ¥è¦åä¸å±ã第ä¸å±æ¯ 10 è¡ä»¥å çä»»å¡ååï¼ä¸æ¸¸å¿ é¡»ä¼å 读ã第äºå±æ¯ç»æåè¯æ®å ï¼ä¸æ¸¸æéå±å¼ã第ä¸å±ææ¯å®æ´è¿ç¨æ¥å¿ï¼åªç¨äºæéååæ¾ï¼ä¸åºè¯¥ç´æ¥å¡è¿ä¸» promptã
åãç¶ææºï¼ç¦æ¢âçèµ·æ¥å®æäºâ
Handoff Contract å¿ é¡»ç»å®ç¶ææºï¼å¦åå®åªæ¯ä¸ä»½æ¼äº® JSONãç¶ææºçä»·å¼å¨äºï¼å®è½ç¦æ¢ä¸äºå±é©æ·å¾ãæ¯å¦æ²¡æ research evidence çè稿ä¸è½è¿å ¥ reviewedï¼æ²¡æ review receipt çæç« ä¸è½è¿å ¥ ready_to_publishï¼æ²¡æ publish æéç Agent ä¸è½è§¦åå¤é¨åå¸ã
const allowedTransitions: Record<HandoffState, HandoffState[]> = {
planned: ['researched'],
researched: ['drafted'],
drafted: ['reviewed'],
reviewed: ['ready_to_publish'],
ready_to_publish: [],
};
function canMove(from: HandoffState, to: HandoffState): boolean {
return allowedTransitions[from]?.includes(to) ?? false;
}
function assertTransition(prev: HandoffContract, next: HandoffContract) {
if (!canMove(prev.state, next.state)) {
throw new Error(`illegal handoff transition: ${prev.state} -> ${next.state}`);
}
if (next.permissions.includes('publish_external') && next.to !== 'publisher') {
throw new Error('publish_external can only be granted to publisher');
}
if (next.state === 'reviewed' && next.evidence.length === 0) {
throw new Error('reviewed handoff requires evidence');
}
}
è¿æ®µä»£ç 徿´ç´ ï¼ä½å®è½æ¡ä½ä¸ç±»é«é¢äºæ ï¼Agent èªå·±å®£å¸âæå·²ç» review è¿äºâãå¨ç产系ç»éï¼ç¶æä¸æ¯èªç¶è¯è¨å£°æï¼èæ¯è¿è¡æ¶è®¤å¯çç»æã
å¦æä½ ç¨å·¥ä½æµå¼æï¼ç¶ææºå¯ä»¥æ¾å¨ TemporalãStep FunctionsãLangGraph æèªç orchestration å±éãå¦æä½ åªç¨æ®ééåï¼ä¹å¯ä»¥æç¶ææºæ¾å¨æ¶è´¹è å ¥å£ãå ³é®ä¸æ¯éåªä¸ªå·¥å ·ï¼èæ¯ä¸è¦æç¶ææµè½¬äº¤ç»æ¨¡åèªç±åæ¥ã
äºãæ¥æ¶æ¹å¿ é¡»ææææ¶
å¾å¤ Agent ç¼æå¤±è´¥ï¼æ¯å ä¸ºä¸æ¸¸æ²¡æææ¶æºå¶ãåªè¦ä¸æ¸¸è¾åºäºï¼ä¸æ¸¸å°±ç»§ç»ãè¿æ ·çä¼¼èªå¨åï¼å®é 䏿¯å¨å¶é âæ²é»å¤±è´¥âã
æ¥æ¶æ¹åºè¯¥å¨æ§è¡åå å acceptance checkã
function receiveHandoff(contract: HandoffContract): HandoffReceipt {
const missing: string[] = [];
if (!contract.originalGoal.trim()) missing.push('originalGoal');
if (contract.constraints.length === 0) missing.push('constraints');
if (contract.acceptanceCriteria.length === 0) missing.push('acceptanceCriteria');
for (const required of contract.contextBudget.mustInclude) {
const inArtifacts = contract.artifacts.some(a => a.includes(required));
const inEvidence = contract.evidence.some(e => e.claim.includes(required));
if (!inArtifacts && !inEvidence) missing.push(`mustInclude:${required}`);
}
if (contract.state === 'researched' && contract.evidence.length < 2) {
missing.push('at_least_two_evidence_items');
}
return {
handoffId: contract.id,
receiver: contract.to,
status: missing.length ? 'needs_more_input' : 'accepted',
missing,
acceptedAt: new Date().toISOString(),
};
}
ææ¶æºå¶ä¼è®©ç³»ç»çææ¾å¾âä¸å¤ä¸æ»âï¼ä½é¿æä¼æ¾èåå°èæ°æ®ä¼ æãçäº§ç³»ç»ææç䏿¯å¤±è´¥ï¼èæ¯ä¸ç¥éä»ä¹æ¶åå·²ç»å¤±è´¥ãä¸ä¸ªæç¡®ç needs_more_inputï¼æ¯ä¸ä¸ªç似宿´ä½å®é é误ç䏿¸¸ç»æä¾¿å®å¾å¤ã
å ãè¯æ®å ï¼ä¸è¦è®©ç»è®ºè£¸å¥
Multi-Agent ç³»ç»éï¼è¯æ®å æ¯æ®é RAG å¼ç¨æ´éè¦ãRAG å¼ç¨é常æå¡äºåçè´¨éï¼handoff evidence è¿æ¿æ 责任追踪ã
ä¸ä¸ªå¥½ç evidence item ä¸åºè¯¥åªæ¯ URLãå®è³å°è¦è¯´æè¿æ¡è¯æ®æ¯æåªä¸ä¸ª claimãä»ä¹æ¶åæè·ãæ¥èªåªä¸ªäº§ç©ãå¦å Reviewer çå°ä¸å 龿¥ï¼ä»ç¶ä¸ç¥éè¯¥æ£æ¥ä»ä¹ã
const evidence: EvidenceItem = {
id: 'ev-langgraph-memory-001',
kind: 'url',
ref: 'https://docs.langchain.com/oss/python/concepts/memory',
claim: 'çæè®°å¿æ¯ thread-scopedï¼é¿æè®°å¿å¯è·¨ thread namespace å¬å',
capturedAt: '2026-08-14T08:05:00+08:00',
};
å¨æç« åä½ã代ç çæãæ°æ®åæè¿ç±»é¾è·¯éï¼æå»ºè®®æ evidence åæä¸ç±»ã
第ä¸ç±»æ¯ source evidenceï¼è¯æäºå®æ¥æºã第äºç±»æ¯ execution evidenceï¼è¯ææä¸ªå½ä»¤ãæµè¯æèæ¬ç¡®å®è·è¿ã第ä¸ç±»æ¯ decision evidenceï¼è®°å½ä¸ºä»ä¹éæ© A è䏿¯ Bã
å¾å¤å¢éåªå第ä¸ç±»ï¼æä»¥ Review é¶æ®µåªè½æ£æ¥âææ²¡ææ¥æºâãä½çäº§äºæ 常常æ¥èªç¬¬ä¸ç±»ï¼å½æ¶ä¸ºä»ä¹è·³è¿å®å ¨æ£æ¥ï¼ä¸ºä»ä¹æ publish æé交ç»è¿ä¸ª Agentï¼ä¸ºä»ä¹æ²¡æç人工审æ¹ï¼å¦ææ²¡æ decision evidenceï¼äºååªè½ç¿»è天记å½ï¼æéææ¬ä¼é常é«ã
ä¸ãæéè¾¹çï¼handoff ä¸è½ç»§æ¿ä¸å
Multi-Agent handoff éæå±é©çé»è®¤å¼ï¼æ¯â䏿¸¸ç»§æ¿ä¸æ¸¸å ¨é¨è½åâãè¿å¨å é¨ demo éæ¹ä¾¿ï¼å¨ç产éå¾å±é©ã
Publisher éè¦ publish_externalï¼Writer ä¸éè¦ï¼Researcher éè¦ read_sourcesï¼ä¸ä¸å®éè¦ write_artifactï¼Reviewer éè¦è¯»è¯æ®å产ç©ï¼ä¸åºè¯¥æ¥æå叿éãæéåºè¯¥è·ä»»å¡é¶æ®µç»å®ï¼è䏿¯è·æ´ä¸ªä¼è¯ç»å®ã
å¯ä»¥ç¨ä¸ä¸ªç®åçæéç©éµå第ä¸å±é²æ¤ã
const rolePermissions: Record<AgentRole, Permission[]> = {
planner: ['write_artifact'],
researcher: ['read_sources', 'write_artifact'],
writer: ['write_artifact'],
reviewer: ['read_sources', 'run_tests'],
publisher: ['read_sources', 'write_artifact', 'publish_external'],
};
function assertPermissionScope(contract: HandoffContract) {
const allowed = new Set(rolePermissions[contract.to]);
const illegal = contract.permissions.filter(p => !allowed.has(p));
if (illegal.length) {
throw new Error(`${contract.to} received illegal permissions: ${illegal.join(',')}`);
}
}
æ´ç¨³çåæ³æ¯è¿è¡æ¶ä¹é离æéãæ¯å¦ä¸å Agent 使ç¨ä¸åå·¥å ·ç½ååï¼ä¸åå¤é¨ API keyï¼ä¸åæä»¶ç³»ç» mountãHandoff Contract åªè½å£°ææéï¼çæ£çæéæ¶æå¿ é¡»ç± runtime æ§è¡ã
è¿ç¹å°¤å ¶éååå¸ãæ¯ä»ãå é¤ãåæ¶æ¯ãæ¹é ç½®è¿ç±»å¤é¨å¨ä½ãåªè¦å¨ä½ä¼ç¦»å¼æ¬æºæå½±åçå®ç¨æ·ï¼å°±ä¸è½å 为â䏿¸¸è¯´å¯ä»¥âèç´æ¥æ§è¡ã
å «ãä¸ä¸æé¢ç®ï¼äº¤æ¥ä¸æ¯å¡æ»¡çªå£
ä¸ä¸æå·¥ç¨æè¿å¾çï¼ä½å¨ handoff åºæ¯éï¼ææçéç䏿¯âå¦ä½å¡æ´å¤âï¼èæ¯âå¦ä½å°å¡ä¸ä¸ä¸¢å ³é®çº¦æâã
ä¸ä¸ªå®ç¨è§åæ¯ï¼handoff prompt çå 20% æ¾ååï¼å 80% ææ¾èµæãååéå¿ é¡»å å«åå§ç®æ ãç¦æ¢äºé¡¹ãå½åç¶æãéªæ¶æ åãèµæå¯ä»¥è¢«æªæï¼ååä¸è½è¢«æªæã
ä½ å¯ä»¥å¨çæä¸æ¸¸ prompt åå䏿¬¡é¢ç®æ£æ¥ã
function buildHandoffPrompt(contract: HandoffContract, rawContext: string) {
const contractBlock = JSON.stringify({
task: contract.task,
originalGoal: contract.originalGoal,
constraints: contract.constraints,
state: contract.state,
permissions: contract.permissions,
acceptanceCriteria: contract.acceptanceCriteria,
}, null, 2);
const maxContextChars = Math.floor(contract.contextBudget.maxTokens * 3);
const trimmedContext = rawContext.slice(0, maxContextChars);
return [
'ä½ æ£å¨æ¥æ¶ä¸ä¸ªä¸æ¸¸ Agent ç交æ¥ãå
æ£æ¥ååï¼åå³å®æ¯å¦ç»§ç»ã',
'妿ååç¼ºåæ®µæè¯æ®ä¸è¶³ï¼è¾åº needs_more_inputï¼ä¸è¦èªè¡èè¡¥ã',
'HANDOFF_CONTRACT:',
contractBlock,
'SUPPORTING_CONTEXT:',
trimmedContext,
].join('
');
}
è¿æ®µä»£ç æ æå¾ä¿å®ã宿²¡æè®©æ¨¡åèªå·±å¤æåªäºä¸ä¸æéè¦ï¼èæ¯å æåååæ®µåºå®å¨æåé¢ãå®é 项ç®å¯ä»¥åå æè¦å¨ãrerankerãsemantic cacheï¼ä½è¿äºé½æ¯ä¼åå±ï¼ä¸åºè¯¥æ¿ä»£ååå±ã
ä¹ã5 个ç产é·é±ä¸ä¿®å¤åæ³
第ä¸ä¸ªé·é±æ¯æ handoff åæèªç¶è¯è¨ãæ¯å¦âæå·²ç»å®æè°ç ï¼è¯·ä½ ç»§ç»åä½âãè¿å¥è¯æ²¡æç¶æã没æè¯æ®ã没æéªæ¶æ åãä¿®å¤åæ³æ¯ï¼èªç¶è¯è¨å¯ä»¥ä¿çç»äººçï¼ä½æºå¨æ§è¡å¿ é¡»è¯»ç»æåååã
第äºä¸ªé·é±æ¯è®©ä¸æ¸¸èªå¨è¡¥ç¼ºã䏿¸¸åç°ç¼ºçº¦æï¼å´èªå·±çä¸ä¸ªçº¦æç»§ç»ãä¿®å¤åæ³æ¯ï¼ç¼ºå ³é®åæ®µå¿ é¡» needs_more_inputï¼åªæéå ³é®å段å¯ä»¥ä½¿ç¨é»è®¤å¼ï¼èä¸é»è®¤å¼è¦åè¿ receiptã
第ä¸ä¸ªé·é±æ¯è¯æ®åªè¿æ£æï¼ä¸è¿ååãWriter åæç« æ¶å¼ç¨äºæ¥æºï¼ä½ Reviewer çè¾å ¥éåªææç¨¿ï¼æ²¡æ source mapãä¿®å¤åæ³æ¯ï¼evidence åºè¯¥ç¬ç«åå¨ï¼æ£æå¼ç¨åªæ¯ evidence çæ¶è´¹ç»æã
第å个é·é±æ¯æéè·ä¼è¯èµ°ãä¸ä¸ªä¼è¯éæ¾ç»ææè¿åå¸ï¼åç»ææ Agent é½è½åãä¿®å¤åæ³æ¯ï¼æéè· handoff state å receiver role ç»å®ï¼æ¯æ¬¡äº¤æ¥éæ°è®¡ç®ã
第äºä¸ªé·é±æ¯æ²¡æææ¶ææ ãå¢éåªç»è®¡ä»»å¡å®æçï¼ä¸ç»è®¡ handoff reject rateãä¿®å¤åæ³æ¯ï¼æ acceptedãneeds_more_inputãrejected é½åæææ ãhandoff reject rate çæåé«ä¸ä¸å®æ¯åäºï¼å¯è½è¯´æç³»ç»ç»äºå¼å§æ´é²èè¾å ¥ã
åãHandoff Contract å MemoryãTraceãWorkflow çå ³ç³»
è¿å个ä¸è¥¿ç»å¸¸è¢«æ··å¨ä¸èµ·ã
Memory è´è´£è®°ä½ä¿¡æ¯ãå®å¯ä»¥åè¯ç³»ç»ç¨æ·å好ãåå²éæ©ã䏿¬¡ä»»å¡ç»æãä½ memory ä¸è´è´£è¯æè¿æ¬¡äº¤æ¥å®æ´ã
Trace è´è´£è®°å½åçè¿ä»ä¹ãå®éåæéã审计ãåæ¾ãä½ trace å¾å¾å¤ªé¿ï¼ä¸è½ç´æ¥ä½ä¸ºä¸æ¸¸æ§è¡è¾å ¥ã
Workflow è´è´£æ§å¶ä»»å¡æä¹æµè½¬ãå®è½ä¿è¯ A å颿¯ Bï¼B å颿¯ Cãä½å¦æ A ç» B çè¾å ¥è´¨éå¾å·®ï¼workflow ä¹åªæ¯å¨ç¨³å®å°ä¼ éåå¾ã
Handoff Contract è´è´£å®ä¹ä¸æ¬¡äº¤æ¥æ¯å¦åæ ¼ãå®ç«å¨ MemoryãTraceãWorkflow ä¸é´ï¼æâè®°å¾ä»ä¹ââåçäºä»ä¹ââä¸ä¸æ¥å»åªâè¿æ¥èµ·æ¥ã
妿åªè½å åä¸ä»¶äºï¼æå»ºè®®ä»åååæ®µåææ¶æºå¶å¼å§ï¼è䏿¯å æå¤æå¹³å°ãå 为å¾å¤ Multi-Agent 项ç®ä¸æ¯æ»äºç¼ºå¹³å°ï¼èæ¯æ»äºæ¯ä¸æ¥é½å¨é»è®¤è¾å ¥æ²¡é®é¢ã
åä¸ãä¸ä¸ªè½å° checklist
æåç»ä¸ä¸ªå·¥ç¨è½å°æ¸ åãä½ å¯ä»¥ç´æ¥æ¿å»æ¹èªå·±ç Agent ç¼æã
- æ¯ä¸ª Agent è¾åºå¿ é¡»å å«ç»æå handoffï¼ä¸åªè¾åºèªç¶è¯è¨ã
- æ¯æ¬¡ handoff é½è¦æ fromãtoãstateãtaskãoriginalGoalã
- åå§ç¨æ·ç®æ åç¦æ¢äºé¡¹å¿ é¡»è¿å ¥åååé¨ï¼ä¸è½åªçå¨è天åå²éã
- evidence è¦ç¬ç«æå ï¼è³å°å å« refãclaimãcapturedAtã
- 䏿¸¸æ§è¡åå¿ é¡»å acceptance checkã
- ç¼ºå ³é®å段æ¶å¿ é¡»ææ¶ï¼ä¸è½èªå¨èè¡¥ã
- publishãdeleteãpaymentãmessageãconfig change çå¤é¨å¨ä½å¿ é¡»åç¬ææã
- ç¶ææµè½¬ç± runtime æ£æ¥ï¼ä¸ç±æ¨¡å声æã
- handoff receipt è¦æä¹ åï¼ä¾¿äºå®¡è®¡åéæ¾ã
- ææ éå å ¥ handoff accept rateãreject reasonãmissing field topNã
ç»è¯
Multi-Agent ç³»ç»çæ£é¾çå°æ¹ï¼ä¸æ¯æå 个 Agent 串起æ¥ã串起æ¥å¾å®¹æï¼é¾çæ¯è®©æ¯ä¸æ¬¡äº¤æ¥é½æè¾¹çãæè¯æ®ãæéªæ¶ãæè´£ä»»ã
å¦æä½ ç°å¨ç Agent ç³»ç»è¿åçå¨â䏿¸¸è¾åºä¸æ®µè¯ï¼ä¸æ¸¸ç»§ç»æ¥çåâï¼é£å®æ´åä¸ä¸ªè天æ¥é¾ï¼è䏿¯ä¸ä¸ªå·¥ç¨ç³»ç»ãè天æ¥é¾è½å demoï¼ä¸è½æç产ã
Handoff Contract çä»·å¼ï¼å°±æ¯æ Agent åä½ä¸ææ¨¡ç³ç䏿®µåææç¡®åè®®ãå®ä¸ä¼è®©æ¨¡åçªç¶åèªæï¼ä½ä¼è®©ç³»ç»å¨è¾å ¥ä¸å®æ´ãæéä¸å¯¹ãè¯æ®ä¸è¶³ãç¶æéæ³æ¶åæ¶å䏿¥ãå¾å¤æ¶åï¼å¯é ç³»ç»åä¸å¯é ç³»ç»çå·®è·ï¼ä¸å¨äºåè æ°¸è¿ä¸ç¯éï¼èå¨äºåè ç¥éä»ä¹æ¶ååºè¯¥æç»ç»§ç»ã
Aitishiku.com