返回 AICAP-180
B4 · Day 36reasoning/planning/multi-agent + 何时不用 agent

supervisor/worker 模式

B4 前半(Day 31-35)解决的是「单个 agent 的推理形态 + 怎么用统计判它」:

阶段: B4 · reasoning/planning/multi-agent + 何时不用 agent(Day 31-40) 标签: #multi-agent #orchestrator-workers #context-isolation #agent-loop

今日导引(由浅入深)

B4 前半(Day 31-35)解决的是「单个 agent 的推理形态 + 怎么用统计判它」:

  • Day31 CoT/ReAct/plan-execute 谱系(推理不是越多越好)
  • Day32 agent vs workflow 二分(能固定就别上 agent)
  • Day33 pass@k / pass^k(非确定输出的两种口径)
  • Day34 self-consistency(多采样投票降方差)
  • Day35 bootstrap CI(小样本 Δ 的显著性)

从今天起转入多 agent 编排:当一个 agent 的 context 装不下、或子任务需要专职分工时,怎么拆。今天落地最经典的一种 supervisor/worker(orchestrator-workers) 模式;明天(Day37)立刻用同一任务集去实测「多 agent 是否真的更好」。最小可判定产出:在本仓 loop.ts + toolRegistry mock 上跑出 1 条确定性可测的端到端编排 transcript

1. 机理精读

定义。supervisor/worker(Anthropic 称 orchestrator-workers)是一个分层结构:

  • 顶层 supervisor(orchestrator) 不直接干活,只做两件事——拆解(把用户目标切成子任务)和路由(把每个子任务派给一个专职 worker)。
  • 每个 worker 是一个独立的子 agent,有自己的 system prompt、自己的工具子集、以及最关键的——隔离的 context
  • worker 把结果回传,supervisor 再汇总成最终答案。

参考 Anthropic《Building Effective Agents》(2024-12)的 orchestrator-workers 章节。

为什么这样设计——核心收益是 context 隔离。单 agent 把所有工具描述、所有中间观察、所有历史都塞进一个窗口,token 互相稀释注意力(这正是 Day41 context engineering 要展开的命题)。把「查 AML 类型学」和「查实时链上数据」拆给两个 worker,各自的窗口里只有与本职相关的高信号 token,噪声被物理隔离掉。分工还带来 prompt 专门化——research worker 的 system 可以只讲数据源和引用纪律,不必同时塞 AML 合规规则。

关键权衡——隔离不是免费的。三条代价:

  1. 协调开销:supervisor 自己要消耗 step 和 token 做拆解与汇总。
  2. token 翻倍:同一份背景信息可能要分别喂给多个 worker,端到端 token 常是单 agent 的 2× 以上(Day37 实测这个倍数)。
  3. 跨 agent 错误传播:supervisor 拆错了子任务、或某个 worker 给出错误中间结论,错误会沿调用链放大,且更难定位。

所以这套模式的判定门槛是「子任务真正可分工 / 需隔离」,不是「显得高级」。

与相邻概念的边界

  • 与 Day32 的 workflow 区别:workflow 是预定义代码路径(路由规则写死在代码里,确定、便宜、可测);orchestrator-workers 里 supervisor 是 LLM 自主决定派给谁、派什么子查询,属于 agent 范畴。
  • 并行 agent(sectioning/voting)的区别:orchestrator-workers 是动态拆解(子任务数量与内容运行时才定),并行 agent 是预先固定的并行分片。今天聚焦前者。

汇总契约要显式。supervisor 汇总 worker 结果时,必须约定一个结构化回传格式(而非自由文本拼接),否则汇总环节会成为错误传播的放大器:

  • worker 返回应带「结论 + 证据 + 不确定标记」,让 supervisor 能判断是否采信;
  • 本仓 finalAnswer 工具(orchestratorAgent.ts:74-89)强制 sources 数组(kind: 'note'|'tool' + title/path),就是把「汇总必须可溯源」写进 schema 的做法;
  • 缺了这层契约,supervisor 只能盲信 worker 文本,跨 agent 错误无从拦截。

2. 推导 / 手算 / 代码走读

本仓有两份真实代码支撑今天的编排:底层无框架的 src/agent/loop.ts,以及上层用 ai SDK 实现的真实 orchestrator-workers src/agent/orchestrator/orchestratorAgent.ts。逐条走读:

  • runAgentLoop(opts)loop.ts:34):框架自由的 observe→act 循环opts.modelLoopModel 类型)和 opts.toolsLoopTool[])都是注入的——所以整条 loop 用 fake model 就能离线单测,不需要任何 API key(文件头注释明示这是「agent loop, implemented not noted」的作品)。
  • 循环体(loop.ts:45-58):每个 step 调 opts.model({ task, transcript })。若返回 out.tool,则 toolCalls++、查 tools.get(name)、跑 tool.run(args)、把观察 push 进 transcript 后 continue;若返回 out.text,则收尾返回 { output, steps, toolCalls, transcript, hitCap:false }
  • 硬 step caploop.ts:41,59):maxSteps ?? 8,循环跑满未收敛则返回 hitCap:trueoutput:''。这是防 agent 无限打转的最低安全栅,supervisor 也复用同一思想。
  • 上层真实编排 runOrchestrator(opts)orchestratorAgent.ts:22):supervisor 通过 generateText 暴露四个工具——invokeKnowledgeAgent / invokeResearchAgent / invokePortfolioAgent(三个专职 worker 的 dispatch)+ finalAnswer。这正是 orchestrator-workers 的形状:supervisor 不直接查数据,而是把 subQuery 路由给 worker
  • worker 隔离体现在 dispatch 里(如 orchestratorAgent.ts:26-38):每次 dispatch 先 budget.resetSubAgent(),再调 runKnowledgeAgent({ model: opts.modelSubAgent, query: subQuery, ... })——worker 拿到的只有它的 subQuery不是 supervisor 的完整历史,这就是 context 隔离的代码落点。
  • 协调开销的代码证据:stopWhen: ({ steps }) => steps.length >= 8orchestratorAgent.ts:101)给 supervisor 也设了步数上限;Budgetorchestrator/budget.ts)的 assertCanStep / assertCostOk / assertNotTimedOutbudget.ts:31-50)把「token 翻倍」这件事变成可强制的预算栅。

src/agent/orchestrator/ 的最小 supervisor→2 worker 骨架,可在 loop.ts 的注入式 model 上用一个 fake supervisor model(先 emit 两次 tool 调两个 worker、再 emit text 汇总)跑出确定性 transcript,无需真实模型。

最小确定性轨迹(手写 fake supervisor model 的状态)

stepsupervisor 输出loop 行为transcript 增量
1{tool:{name:'workerA',args}}跑 workerA,push 观察call workerA(...) + tool obs
2{tool:{name:'workerB',args}}跑 workerB,push 观察call workerB(...) + tool obs
3{text:'汇总...'}收尾返回model 最终文本

该序列完全确定,runAgentLoop 返回 toolCalls=2steps=3hitCap=false——可写死断言做单测。

worker 内部的隔离子 loop:每个 worker 的 LoopTool.run 内部可再起一个 runAgentLoop(自己的 fake model + 自己的工具子集),这层嵌套就是「隔离 context」在代码上的物理边界——内层 transcript 不回流到 supervisor 的 transcript,只回传最终 output 字符串。这与 orchestratorAgent.ts 里 worker 只回 { text: r.text }:37)的契约一致。

3. 今日实战

  1. src/agent/orchestrator/ 下用 runAgentLoop 搭最小 supervisor→2 worker 编排:supervisor 的 LoopModel 第一步 emit {tool:{name:'workerA',...}}、第二步 emit {tool:{name:'workerB',...}}、第三步 emit {text: 汇总};两个 worker 注册成 LoopToolrun 内部各自跑一个隔离的子 loop(或直接返回 fixture 结果)。
  2. 工具发现/调用走 src/agent/mcp/toolRegistry.ts 的 in-process mock:register(spec, handler) 注册 worker 暴露的工具,list() 给 supervisor 看动作空间(按 name 稳定排序),call(name,args) 带 schema 校验执行。
  3. 对 Day31 标注的 8 任务子集跑一条端到端轨迹,把 transcript(含 supervisor 的 call workerA(...) / call workerB(...) 行)落盘。
  4. 真实 model 轨迹用 orchestratorAgent.tsrunOrchestrator(需 modelOrchestrator + modelSubAgent),这一步待 key
  5. 给编排骨架加离线单测:断言 toolCalls=2、worker 各被调用一次、最终 output 含两个 worker 的回传摘要——确定性序列让断言可写死,无需 mock 网络。

4. 今日实测 / 产出

  • loop.tstoolRegistry mock 已在 repo 且测试绿
  • 编排骨架可离线用 fixture model 跑出 1 条端到端 transcript(确定性可测)。
  • 真实 model 轨迹「待跑(需 key)」。
  • 产出:可运行编排 transcript 1 条。

5. 常见误区 / 陷阱

  • 把 supervisor/worker 当默认架构:多数任务单 agent 就够,强行分层只是徒增 token 和失败点(Day37 会用数据反驳)。
  • worker 之间共享 context:一旦让 worker 看到 supervisor 全量历史,就失去隔离收益、回到单 agent 的注意力稀释问题。
  • 忘了给 supervisor 设 step/cost cap:supervisor 自主拆解,没有 stopWhen / Budget 栅就可能无限派活。
  • 用 AutoGen/SK 当主线框架:二者均处维护模式,本仓走自建 loop 优先(用户 2026-06-11 决策),自建才能讲清每个组件存在的理由。
  • 汇总只拼文本不带溯源:worker 结果直接字符串拼接进最终答案,丢掉 sources,导致引用断链、错误无法回溯到具体 worker。

6. 学习资源(每条带 YYYY-MM)

  • Anthropic《Building Effective Agents》(2024-12)——orchestrator-workers 模式与「能简单就别复杂」原则的主引用。
  • 本仓 src/agent/loop.ts(框架自由 observe→act loop,注入式可离线测)。
  • 本仓 src/agent/orchestrator/orchestratorAgent.ts(真实 ai SDK 版 supervisor→3 worker + finalAnswer)。
  • 本仓 src/agent/orchestrator/budget.ts(step / toolCall / cost / timeout 预算栅)。
  • Anthropic Agent SDK 文档 (2025)——orchestrator-workers 在 SDK 中的延续。

SOTA检查 (2026-06 更新)

orchestrator-workers 仍是主线多 agent 模式(2024-12《Building Effective Agents》+ 2025 Agent SDK 沿用),现行有效。

  • 避免:把 AutoGen / Semantic Kernel 当多 agent 主线——两者均处维护模式。
  • 自建优先:本仓自建 loop 优先(用户 2026-06-11 决策),理由是「自建过同等物,才能讲清托管平台每个组件为何存在」。
  • 下次复查点:Anthropic engineering blog 是否在 2026 出多 agent 编排更新版;MCP 2026-07-28 最终规范定稿后 worker 工具暴露契约是否调整。

本日交叉引用

  • 上游依赖:Day31(agent 推理谱系)、Day32(agent vs workflow 边界)。
  • 下游被用:Day37(用本日编排做单 vs 多 agent 对照)、Day40(编排的成本进 gate)。
  • 代码资产:src/agent/loop.tssrc/agent/orchestrator/orchestratorAgent.tssrc/agent/orchestrator/budget.tssrc/agent/mcp/toolRegistry.ts

衔接

  • 昨天:Day 35 — bootstrap 置信区间(小样本 Δ 的 95% CI,CI 跨 0 即不显著)。
  • 今天:supervisor 拆任务并路由给隔离 context 的 worker——收益是分工与降噪,成本是协调开销 + token 翻倍 + 错误传播。
  • 明天:Day 37 — 单 agent vs 多 agent(用同任务集实测 accuracy Δ + token 倍数,验证多 agent 不总更好)。