Coordinator-Worker 与 Context 继承:结构化协作的工程实现

Coordinator-Worker 与 Context 继承:结构化协作的工程实现 Coordinator-Worker 与 Context 继承结构化协作的工程实现《Claude Code 架构解密》精读笔记 · 第10篇 · 第6章后半6.6-6.12上一篇我们拆解了 Fork-and-Delegate 的轻量并行分叉机制。当任务复杂度升级——“先调研、再实现、后验证”——Fork 的隐式编排就力不从心了。这时需要一个指挥者来显式调度工作流这就是 Coordinator-Worker 模式的用武之地。本篇将从结构化编排、异步生命周期、上下文缓存共享三个维度解析 Claude Code 如何把多 Agent 协作从散兵游勇升级为正规军。一、导语从游击队到正规军Fork-and-Delegate 像游击战——每个子 Agent 继承完整上下文、独立执行、无需协调。但对代码库做安全审计→修复高危漏洞→验证修复这样的多阶段任务需要严格的阶段控制和结果聚合。核心矛盾Fork 的继承式共享带来了缓存效率和上下文连贯性但代价是缺乏编排结构Coordinator 的隔离式编排带来了结构化控制和安全性但代价是缓存失效和额外成本。Claude Code 的解法不是二选一而是两种模式互斥并存——根据任务特征选型同一时刻只有一种模式激活。二、架构图解七模式协作全景第6章的七个设计模式并非孤岛它们形成了一张协作网络┌─────────────────────┐ │ Agent Type Registry │ ← 加载 Agent 定义 └──────────┬──────────┘ │ ┌──────────▼──────────┐ │ Tool Sandboxing │ ← 过滤工具集 └─────┬────────┬──────┘ │ │ ┌───────────────▼┐ ┌────▼──────────────┐ │ Fork-and-Delegate│ │ Coordinator-Worker │ ← 两种互斥编排 └───────┬────────┘ └─────┬──────────────┘ │ │ ┌───────▼──────────────────▼──────┐ │ Async Agent Lifecycle │ ← 统一生命周期 └───────┬──────────────────┬──────┘ │ │ ┌────────────▼──────┐ ┌───────▼──────────┐ │ Context Cache │ │ Scoped Memory │ ← 成本优化 长期记忆 │ Sharing (Fork专属) │ │ (所有Agent共享) │ └───────────────────┘ └──────────────────┘协作路径解读Agent Type Registry → 提供定义Tool Sandboxing → 过滤权限Fork / Coordinator → 互斥编排Async Lifecycle → 统一生命周期管理Context Cache → Fork 专属成本优化Scoped Memory → 全局跨会话记忆三、核心点拆解3.1 Coordinator-Worker编排者不执行角色分离的极端设计Coordinator 只有 4 个工具——Agent启动 Worker、TaskStop停止 Worker、SendMessage继续 Worker 对话、SyntheticOutput结构化输出。不能读文件、不能写文件、不能执行 Shell。相对应地Worker 拥有丰富的执行工具但被禁止创建子 Agent防嵌套递归和向用户提问后台无交互界面。四阶段工作流软约束Research调研→ Synthesis综合→ Implementation实现→ Verification验证软约束的精妙之处LLM 可根据实际情况灵活调整——简单任务跳过 Research纯分析任务跳过 Implementation。XML 通知协议Worker 完成时用结构化 XML 报告结果task-notificationtask-id{agentId}/task-idstatuscompleted|failed|killed/statussummary{human-readable status summary}/summaryresult{agents final text response}/resultusagetotal_tokensN/total_tokenstool_usesN/tool_usesduration_msN/duration_ms/usage/task-notification为什么用 XML 不用 JSONLLM 对 XML 标签的解析更鲁棒——JSON 一个多余逗号就崩XML 标签的嵌套结构对 LLM 更自然。而且task-notification可以嵌入普通文本中不需要额外的通信通道。3.2 自包含 Prompt 与 Scratchpad 间接通信Coordinator-Worker 与 Fork 最关键的区别上下文隔离。维度Fork-and-DelegateCoordinator-Worker上下文共享子 Agent 继承父 Agent 完整对话历史Worker 看不到 Coordinator 的任何对话Prompt 要求只需简短的 Fork 指令必须自包含所有必要上下文缓存效率高Prompt Cache 共享低每个 Worker 独立请求Coordinator 的 system prompt 有一条明确规则Prompts must be self-contained. Workers cannot see your conversation.启动 Worker 时必须将所有必要信息嵌入 prompt——文件路径、行号、具体需求、背景上下文。这种隔离带来两个好处安全隔离Worker 看不到 Coordinator 与用户的对话降低信息泄露风险独立性Worker 可以被独立测试和调试Scratchpad 间接通信Worker 之间无法直接通信Coordinator 可指定一个共享目录作为草稿纸——Worker 写入中间结果其他 Worker 读取。一种简单但有效的间接通信模式。3.3 Async Agent Lifecycle五阶段状态机长时间运行的 Agent 不应阻塞主线程但异步执行引入了新的复杂性——进度反馈、错误处理、资源清理、前后台切换。五阶段生命周期Created → Running → Completed → Failed → Killed核心实现runAsyncAgentLifecycle()五阶段阶段动作关键点Phase 1初始化——创建进度追踪器tracker 记录 toolUseCount / token 用量 / recentActivitiesPhase 2消息流处理——实时追踪进度for await (const message of makeStream())逐消息更新Phase 3完成处理finalizeAgentToolcompleteAsyncAgentPhase 4安全审查classifyHandoffIfNeeded分类审查Phase 5通知 Coordinator/父 AgentenqueueAgentNotificationXML 格式通知进度追踪器的 token 统计细节输入 token 取最新值API 每次返回的是累计值包含缓存命中部分输出 token逐轮累加每轮输出是增量这个细节反映了对 LLM API 计费模型的深入理解。3.4 前台/后台切换与自动后台化Agent 支持前台后台动态切换。核心机制是backgroundSignal——一个 Promise当 Agent 被切换到后台时 resolve。Agent 执行逻辑可以await这个信号来调整行为前台即时显示进度后台只在完成时通知。自动后台化定时器默认 120 秒解决了一个 UX 问题用户启动 Agent 后可能忘记手动切后台长时间运行的前台 Agent 会阻塞主界面。120 秒后自动后台化是合理的默认行为。3.5 十步资源清理链最精密的工程异步 Agent 生命周期中最精密的部分。运行中的 Agent 可能持有 MCP 连接、Hook 注册、文件缓存、Shell 进程等多种资源。finally块确保这些资源被可靠释放1. mcpCleanup() // 关闭 MCP 连接 2. clearSessionHooks() // 清除 Hook 注册 3. cleanupAgentTracking() // 清除 Cache 检测 4. readFileState.clear() // 释放文件缓存 5. initialMessages.length 0 // 释放消息引用 6. unregisterPerfettoAgent() // 注销 Tracing 7. (保留位) 8. delete todos[agentId] // 删除 Todo 条目 9. killShellTasksForAgent() // 杀死后台 Shell 10. killMonitorMcpTasksForAgent() // 杀死 Monitor 任务清理顺序的设计哲学先关闭外部连接MCP正在执行的工具调用可能依赖它们再清除注册信息Hook、Tracing依赖于 MCP 状态然后释放内存缓存文件缓存、消息引用最后清理进程资源Shell、Monitor最独立的资源第 5 步的微妙之处为什么用initialMessages.length 0而不是initialMessages []因为.length 0会原地清空数组所有持有该数组引用的代码都能观察到清空效果。重新赋值只改变引用旧数组仍被其他引用持有无法被 GC 回收。在 Fork 场景中上下文消息可能非常大这个差异对内存管理至关重要。3.6 通知防重复乐观锁模式functionenqueueAgentNotification({taskId,status,finalMessage}){letshouldEnqueuefalseupdateTaskState(taskId,setAppState,task{if(task.notified)returntask// 已通知过shouldEnqueuetruereturn{...task,notified:true}})if(!shouldEnqueue)return// 构建 XML 通知...}在状态更新回调中设置notified标志利用状态更新的原子性保证检查标记不可分割。典型的乐观锁模式——不使用显式锁而是通过原子操作保证一致性。3.7 Retain/Evict 懒清理UI 层面的内存管理用户查看 Agent 面板 →retain: true阻止驱逐用户离开面板 → 开始 30 秒倒计时PANEL_GRACE_MS倒计时结束且任务已完成 → 驱逐面板数据释放内存懒清理策略在响应速度用户切回来时数据仍在和内存效率长时间不看的数据被释放之间取得了平衡。3.8 Context Cache Sharing四维一致性保证成本优化的架构洞察假设父 Agent 有 50,000 tokens 对话历史Fork 出 3 个子 Agent——方案成本朴素方案3 × 50,000 150,000 input tokensPrompt Cache 方案50,000 缓存写入一次 3 × 50,000 缓存读取便宜 90%要利用 Prompt Cache必须确保多个请求的前缀字节级一致——哪怕一个字节的差异都会导致缓存失效。四维一致性保证维度机制代码关键字维度 1统一占位符所有 Fork 子 Agent 的 tool_result 使用同一文本FORK_PLACEHOLDER_RESULT维度 2精确工具列表useExactTools: true跳过工具解析直接使用父级工具列表useExactTools维度 3模型继承model: inherit避免模型切换导致缓存失效model: inherit维度 4文件状态缓存克隆Fork 子 Agent 继承父 Agent 的文件读取缓存cloneFileStateCache架构启示LLM 系统的成本优化不仅仅是算法问题更是系统架构问题——成本优化是跨切面关注点cross-cutting concern需要在消息构建、工具解析、模型选择、缓存管理多个层面协同设计。3.9 Fork vs Coordinator系统性对比维度Fork-and-DelegateCoordinator-Worker上下文共享继承父 Agent 完整上下文Worker 无父上下文需自包含 prompt工具权限继承父级所有工具Coordinator 只有编排工具Worker 有执行工具缓存效率高Prompt Cache 共享低每个 Worker 独立请求任务编排隐式父 Agent 自行决定显式四阶段工作流互动能力无子 Agent 静默执行Worker 间可通过 Scratchpad 间接通信递归深度硬限制禁止递归 Fork硬限制Worker 不可嵌套 Agent适用场景并行独立任务需要共享上下文复杂工作流需要阶段控制成本模型低缓存共享高独立请求选择指南并行独立子任务 需要理解完整上下文 →Fork多阶段编排 子任务间有依赖 →Coordinator成本敏感 →ForkPrompt Cache 共享可省 90% 输入成本安全敏感 →CoordinatorWorker 看不到 Coordinator 与用户的对话四、横向对比三大框架的多 Agent 编排哲学维度Claude CodeLangGraphOpenAI Agents SDKAutoGen编排模型隐式Fork/ Prompt 引导Coordinator显式有向图函数调用交接对话协议灵活性LLM 动态决定任务分解图结构编译时确定声明式轻量Agent 协商可预测性较低LLM 决策不确定较高图结构确定中等较低并行度真正并行Fork/Worker支持并行分支串行交接支持并行对话上下文传递Fork 共享 / Worker 自包含图边传递状态交接时传递完整上下文对话消息传递复杂度较高7 个模式中等图定义较低中等适用场景通用 AI 编程助手预定义工作流单一信任域多 Agent 研究/讨论Claude Code 的选择逻辑vs LangGraph任务类型不可预知需要 LLM 自主判断如何分解vs Agents SDK需要进程级隔离的生产级复杂场景不是单一信任域内的轻量交接vs AutoGenAgent 间对话引入额外 LLM 调用成本 不确定性传播不如 Coordinator 集中编排五、实战启示三个可复用设计模式模式一角色分离 最小权限编排者不执行执行者不编排这个原则可以推广到任何多角色系统——Coordinator 只有调度工具、Worker 只有执行工具、记忆 Agent 只能编辑一个文件。每个角色的权限边界越窄系统的安全推理越简单。模式二十步确定性清理链资源清理不是try-finally里的三行代码而是精心排序的多步链条外部连接先关MCP注册信息次之Hook、Tracing内存缓存随后文件、消息进程资源最后Shell、MonitorinitialMessages.length 0的细节值得记住原地清空 vs 重新赋值在共享引用场景中有本质区别。模式三四维缓存一致性在 LLM 系统中做成本优化不是在某个组件里做缓存而是在多个维度上协调一致消息层面统一占位符工具层面精确工具列表模型层面继承父级模型缓存层面文件状态克隆任何一个维度的疏忽都会导致缓存前缀断裂90% 的成本节省瞬间归零。成本优化是跨切面架构关注点不是局部优化。六、下期预告第 10 篇完成了第 6 章Agent 编排的精读。七个模式从轻量分叉到结构化编排再到生命周期管理构建了一套完整的多 Agent 协作体系。下一篇进入第 7 章——上下文管理这是 Agent 系统的灵魂所在有限的上下文窗口如何装下无限的需求第 11 篇Context 的生死抉择——补丁压缩、截断算法与 Session Memory7.1 上下文窗口的核心矛盾7.2 补丁压缩处理机制7.3 Session Memory——实时更新要素系统7.4 消息截断算法——在正确的地方按一下本文是《Claude Code 架构解密》精读笔记系列第 10 篇覆盖第 6 章后半6.6-6.12。系列共 20 篇持续更新中。