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 合规规则。
关键权衡——隔离不是免费的。三条代价:
- 协调开销:supervisor 自己要消耗 step 和 token 做拆解与汇总。
- token 翻倍:同一份背景信息可能要分别喂给多个 worker,端到端 token 常是单 agent 的 2× 以上(Day37 实测这个倍数)。
- 跨 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.model(LoopModel类型)和opts.tools(LoopTool[])都是注入的——所以整条 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 cap(
loop.ts:41,59):maxSteps ?? 8,循环跑满未收敛则返回hitCap:true、output:''。这是防 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 >= 8(orchestratorAgent.ts:101)给 supervisor 也设了步数上限;Budget(orchestrator/budget.ts)的assertCanStep/assertCostOk/assertNotTimedOut(budget.ts:31-50)把「token 翻倍」这件事变成可强制的预算栅。
落
src/agent/orchestrator/的最小 supervisor→2 worker 骨架,可在loop.ts的注入式 model 上用一个 fake supervisor model(先 emit 两次tool调两个 worker、再 emittext汇总)跑出确定性 transcript,无需真实模型。
最小确定性轨迹(手写 fake supervisor model 的状态):
| step | supervisor 输出 | 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=2、steps=3、hitCap=false——可写死断言做单测。
worker 内部的隔离子 loop:每个 worker 的 LoopTool.run 内部可再起一个 runAgentLoop(自己的 fake model + 自己的工具子集),这层嵌套就是「隔离 context」在代码上的物理边界——内层 transcript 不回流到 supervisor 的 transcript,只回传最终 output 字符串。这与 orchestratorAgent.ts 里 worker 只回 { text: r.text }(:37)的契约一致。
3. 今日实战
- 在
src/agent/orchestrator/下用runAgentLoop搭最小 supervisor→2 worker 编排:supervisor 的LoopModel第一步 emit{tool:{name:'workerA',...}}、第二步 emit{tool:{name:'workerB',...}}、第三步 emit{text: 汇总};两个 worker 注册成LoopTool,run内部各自跑一个隔离的子 loop(或直接返回 fixture 结果)。 - 工具发现/调用走
src/agent/mcp/toolRegistry.ts的 in-process mock:register(spec, handler)注册 worker 暴露的工具,list()给 supervisor 看动作空间(按 name 稳定排序),call(name,args)带 schema 校验执行。 - 对 Day31 标注的 8 任务子集跑一条端到端轨迹,把 transcript(含 supervisor 的
call workerA(...)/call workerB(...)行)落盘。 - 真实 model 轨迹用
orchestratorAgent.ts的runOrchestrator(需modelOrchestrator+modelSubAgent),这一步待 key。 - 给编排骨架加离线单测:断言
toolCalls=2、worker 各被调用一次、最终output含两个 worker 的回传摘要——确定性序列让断言可写死,无需 mock 网络。
4. 今日实测 / 产出
loop.ts与toolRegistrymock 已在 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(真实aiSDK 版 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.ts、src/agent/orchestrator/orchestratorAgent.ts、src/agent/orchestrator/budget.ts、src/agent/mcp/toolRegistry.ts。
衔接
- 昨天:Day 35 — bootstrap 置信区间(小样本 Δ 的 95% CI,CI 跨 0 即不显著)。
- 今天:supervisor 拆任务并路由给隔离 context 的 worker——收益是分工与降噪,成本是协调开销 + token 翻倍 + 错误传播。
- 明天:Day 37 — 单 agent vs 多 agent(用同任务集实测 accuracy Δ + token 倍数,验证多 agent 不总更好)。