叫来一队 Agent,不等于做过多角度评审
用风险驱动选择、不可变执行计划、隔离上下文、完成屏障和证据化报告控制多 Agent 协作。
本页目录 · 24 节
多 Agent 的价值不来自 Agent 数量,而来自独立信息增益。如果多个 Worker 读取同一份上下文、沿同一条推理路径、最后用不同角色名复述同一个结论,系统只是把一次偏差复制成多份。
Marshall 的 Worker 机制因此不是一个「虚拟团队名单」,而是一组可验证合同:Risk-based Selection 决定是否需要 Worker,Immutable Plan 决定每个实例能看什么和做什么,Barrier 决定什么时候可以综合,Worker Report 则把结论绑定到证据与不确定性。
flowchart LR
R[Risk Profile] --> S[Worker Selection]
S --> P[Immutable Worker Plan]
P --> W1[Worker A]
P --> W2[Worker B]
P --> W3[Worker C]
W1 --> B[Join Barrier]
W2 --> B
W3 --> B
B --> M[Parent Synthesis]
Parent Agent 始终拥有目标解释、风险选择、计划签发、冲突综合和最终交付责任。Worker 只拥有一个窄问题、一份只读上下文和一个结构化输出位置。
第一步不是 Spawn,而是证明需要并行视角
WorkerSelectionV1 先生成 Risk Profile:
axes
domain_count / repo_count
path_clarity
deep_triggers
evidence
Risk Axis 包括 API、Data、Permission、Runtime、Migration、Backfill、IAM、Production Mutation、Cross-repo、Cross-domain、Source Authority、Security、Domain、Layer、Correctness、Scope 与 External Reference。它们不是标签装饰;每个 Axis 都要有 Locator、内容 Hash 与观察时间作为证据。
Selection 根据风险选择不同 Mode:
| Mode | 合同含义 | Worker 数量 | 适合的任务形状 |
|---|---|---|---|
light |
路径清楚、单仓单域、没有声明的风险轴与 Deep Trigger | 无 | Parent 可直接完成和验证 |
standard |
有少量需要独立检查的风险面 | 少量 | 主分析配窄评审,或少数互不依赖视角 |
deep |
有多个风险轴,或命中 Migration、Backfill、IAM、生产写、跨仓、跨域、来源权威不明等 Trigger | 按容量上限控制;Review 要求多个独立视角 | 高风险、宽搜索空间或多证据域 |
deep 是风险等级,不是「必须凑够预设人数」。通用合同只规定 Fan-out 容量,具体下限由 Stage Policy 决定;Local Review、PR Review 的 Deep 合同要求多个独立视角,用于覆盖不同评审面。
如果风险覆盖需要超过当前容量,Selection 不能悄悄截断实例。它必须进入 blocked_for_split:split_required = true,不生成可 Dispatch 的实例,先把 Design Unit 或 Slice 拆小。这一规则防止上下文、等待和综合成本在单层 Fan-out 中失控。
Role 必须匹配 Risk Axis
每个 Selected Instance 都要声明 matched_risk_axes,而角色只能认领自己支持的 Axis。例如权限评审不能因为名字听起来严格,就替代 Data Runtime 证据;领域 Worker 也不能对 IAM 结论投票。
Validator 检查三层关系:
- Worker 匹配的 Axis 必须来自当前 Risk Profile;
- 角色能力必须覆盖它认领的每一个 Axis;
- 除特定的必选 Critic 外,不能选择一个没有任何 Risk Match 的 Worker。
这把「为什么叫它」从 Prompt 中的解释,变成了机器可拒绝的 Selection 合同。
Worker Plan 是不可变的执行快照
Selection 只决定需要哪些视角,WorkerPlanV1 才决定怎样执行。Plan 绑定:
audit / workflow / stage / purpose
attempt / run / generation / resume_epoch
design_unit / slice
selection_id + selection_sha256
mode / max_parallel / max_dispatches / max_repair_rounds
instances / barriers
plan_sha256
plan_sha256 覆盖完整且有序的 Dispatch Payload。运行开始后,如果要更换 Prompt、Model、Context、权限、输出路径或 Worker 数量,就必须产生新 Plan,而不能在原 Plan 下口头补充。否则最终 Report 无法证明自己执行的到底是哪份指令。
每个 Worker Instance 还要绑定自己的细粒度合同:
instance_id / worker_id / node_id
role / phase / matched_risk_axes
context_refs / output_binding
agent_contract
depends_on_instance_ids / join_barrier_id
其中 Agent Contract 固化配置文件与 Prompt 的 Hash、请求与实际 Model、Reasoning Effort、Service Tier、Sandbox、Network Policy、Output Schema 及其 Hash。角色名称只描述语义责任,真正的能力边界来自这些字段。
Context Isolation 是获得独立证据的前提
Worker 不读取完整对话,也不继承 Parent 的全部推理。每个实例只获得一个生成后的 Dispatch Context,其引用包含:
- Artifact Role、路径与 SHA-256;
access: read_only;- Context Manifest ID、路径与 Hash;
- Team Contract 的路径与 Hash;
- 精确 Source Set 的 Hash。
这样可以回答「这个结论基于哪些字节」,而不是只知道「Worker 大概看过仓库」。Context Hash 变化后,旧 Report 不能继续复用。
隔离还要防止 Anchoring。Marshall 对 explore 和 pre_draft 阶段设置了明确约束:它们的 Context 不能包含 design_draft 或 final_design。先让 Worker 看完主方案,再请它「独立探索」,通常只能得到围绕主方案的小修小补。真正需要独立证据时,应隔离主结论,只给问题、源码与来源边界。
但隔离也不能过度。把所有上下文都拿走,会让 Worker 重新发现已知事实,制造重复成本。合理的 Context Pack 应共享目标、术语、当前源码版本和安全边界,同时隔离 Parent 的中间判断与无关材料。
Capability 限制 Worker 能修改什么
Parent 持有 Stage Lease,并按 Plan 给 Worker 签发短期 Capability。Capability 绑定 Run、Plan、Worker/Instance、允许角色、Context Path、TTL 与当前 Lease Fence。
Worker 对 State 的写入范围只有两类:
start:登记自己的 Run 与 Node 执行状态;publish:发布 Worker Result、Selected Worker、Node 状态或 Late Result。
如果一次 Worker Mutation 改动 Approval、Delivery、Mutation Intent 或其他未授权 State 字段,Runtime 会拒绝整次 CAS。Worker 的 Markdown Prompt 写着「只读」只是意图,Capability、State Mutation Allowlist、Read-only Sandbox 与 Network Policy 才是技术边界。
这也明确了责任:Worker 可以报告「建议 Push」,却不能把建议转换成 Push 权限;可以发现生产数据风险,却不能因此获得数据查询或写入能力。
Parallelism 要受预算和依赖控制
Plan 同时限制 max_parallel_workers、max_total_dispatches 与 max_repair_rounds。三者分别控制瞬时并发、整个计划的调用总量和失败后的修复轮数。
每个 Instance 可以声明对其他 Instance 的依赖,Plan 必须无环。真正独立的 Worker 可以并行;需要前一个结果的 Worker 必须显式排在后面。把有依赖的任务强行并行,不会提高吞吐,只会生成过时假设和后续返工。
Join Barrier 采用明确的成员列表与 kind: all。Parent 只能在 Barrier 的所有必需成员都有当前、有效、可验证的 Report 后进入综合。Barrier 不能靠「已经等了很久」自动放行,也不能把 Selection 没有选中的可选角色偷偷加入等待集合。
Review Stage 还直接禁用 Repair Round:评审 Worker 的职责是发现和证明问题,不是在自己的隔离上下文中反复修改主方案。修复由 Parent 重新规划,避免 Reviewer 同时成为自己问题的消解者。
Worker Report 不是自由格式总结
WorkerReportV1 把结果拆成机器状态与语义内容:
execution_status: completed | failed | timed_out | cancelled | stale
verdict: pass | findings | blocked | deferred
severity
findings[]
evidence_locators[]
blocking
recommended_route
missing_evidence[]
report_body
每个 Finding 都有 ID、摘要、严重度、是否阻塞和 Evidence Locator,还可以绑定 Uncertainty、Claim、Decision 与 Node。Report 的 Control 部分继续绑定 Selection/Plan、Attempt、Generation、Resume Epoch、Context Hash、Role Prompt Hash、Report Schema Hash 与 Worker Payload Hash。
因此「安全 Worker 说有问题」还不是可用结论。Parent 要能定位它读取的证据、确认 Report 属于当前 Plan,并判断 Finding 是否真正命中当前范围。
不确定性必须选择 Route
Worker 不应该用自信语气填补缺失信息。Report 把 Uncertainty 结构化为:类型、是否 Material、是否可发现、已经检查的证据、影响的 Node/Claim/Decision、最早失效节点,以及下一步 Route。
允许的 Route 包括:
continue:未知不影响当前决定;bounded_explore:再做一次有边界的只读发现;question_gate:需要用户做 Material Choice;clarify_reentry或design_reentry:使相关下游结果失效并回到更早阶段;block:缺少必要证据,不能安全继续。
这一设计避免两种极端:Worker 遇到未知就全部阻塞,或把未知包装成推断继续推进。
Freshness 与 Late Result
并行系统最危险的不是 Worker 失败,而是 Worker 成功得太晚。
假设多个 Worker 基于 Generation n 同时运行,Parent 根据部分报告修订了输入并进入 Generation n + 1。其他 Worker 随后返回,即使它通过 Schema、结论也正确,仍然不是新 Generation 的当前证据。
Publication 必须重新核对:
plan / selection
attempt / run / generation / resume_epoch
lease fence / capability
context / prompt / schema hashes
不匹配的结果进入 Stale 或 late_results,保留审计价值,但不能满足当前 Barrier。把晚到结果直接「合并一下」会重新引入已经失效的输入。
Parent 综合不是多数投票
多个 Worker 返回冲突结论时,正确做法不是按 pass 与 findings 数量投票。LLM 的错误往往相关:相同模型、相同上下文和相似 Prompt 可能让多数意见共享同一个盲点。
Parent 综合应按以下顺序:
- 去重相同 Evidence Locator 与实质相同的 Finding;
- 比较来源权威、版本和观察时间;
- 区分事实冲突、解释冲突和产品取舍;
- 对可发现的事实做一次有边界的 Readback;
- 对不可由代码或文档决定的取舍进入 Question Gate;
- 把采用、拒绝或延期的 Finding 绑定到 Decision。
Worker 提供的是专业证据,不是责任票。最终 Scope、Trade-off 和外部动作仍由 Parent 与用户授权决定。
多 Agent 的成本模型
并行可以降低 Wall-clock Time,却通常增加总 Token、工具调用、上下文复制和综合成本。可以用一个简单的不等式判断是否值得增加 Worker:
预期收益
= 独立发现概率 × 问题影响 × 提前发现价值
预期成本
= Dispatch + Context 打包 + 等待 + Report 校验
+ 重复探索 + Parent 综合 + Stale/Late 恢复
只有预期收益明显大于成本,Fan-out 才合理。独立搜索多个数据源、跨领域安全评审、并行读取互不依赖的仓库通常收益较高;围绕同一个函数反复做相似 Review,收益往往很低。
Anthropic 在自己的 Research 系统中报告,多 Agent 使用的 Token 达到普通 Chat 的一个数量级以上,并指出多数 Coding Task 的可并行部分少于 Research。这个量级来自其特定系统与评测,不是 Marshall 的性能基准;它说明的是方向:多 Agent 的能力提升主要通过投入更多独立计算获得,不能假设并行天然更省。
常见失败模式
Role Theater
角色名不同,但 Context、Prompt 和 Evidence Source 相同。解决点是 Risk Match、Context Isolation 与 Evidence Binding,而不是继续增加角色。
Duplicate Exploration
任务边界只写「调查这个问题」,多个 Worker 搜索完全相同的路径。Plan 应说明每个实例的子问题、来源范围、停止条件和输出合同。
Anchored Critic
Explore Worker 先看到 Design Draft,只在现有方案周围找小问题。需要独立发现时,Pre-draft Context 不应包含主方案。
Correlated Majority
多个 Worker 因共享模型与资料得出同一个错误结论。综合要比较证据质量,不能以票数替代 Readback。
Barrier Under-specification
Parent 在必需 Worker 未发布当前 Report 前继续。Barrier 必须绑定精确 Instance,而不是「已有部分返回」。
Barrier Over-specification
低风险任务等待所有可选角色,或已取消 Worker 仍阻塞阶段。Barrier 成员必须来自实际 Selection,并有明确的取消、超时和重新规划路径。
Late Result Accepted as Fresh
旧 Generation 的报告被纳入新设计。Publication 与 Barrier 必须重新校验完整执行身份。
Unbounded Hierarchy
Worker 再递归创建 Worker,协调成本指数增长。Marshall 用实例上限、Dispatch Budget、Repair Round 与 blocked_for_split 控制深度和宽度。
Worker Escapes Its Role
评审 Worker 直接修改代码或调用外部 Provider。只读 Sandbox、Capability 与 State Allowlist 要共同限制它,不能只依赖 Prompt。
Synthesis Becomes the Bottleneck
Worker 产出大量重复长文,Parent 的上下文被报告淹没。Report 应结构化 Finding 与 Locator,大正文保存在 Artifact 中,Parent 只加载会改变决定的部分。
适用边界与 Trade-off
Worker 编排适合子问题能独立探索、证据来源不同、结果可通过清晰接口汇合,而且遗漏代价足以覆盖额外成本的任务。例如跨仓库调用链、数据与权限同时变化、宽度优先的资料研究,或需要相互独立的设计 Critic 与 Deterministic Verification。
它不适合强共享上下文、步骤高度串行、多人会写同一片代码,或 Parent 一次读取就能验证的窄任务。此时拆分会增加上下文复制、同步和冲突,却没有增加新的证据。
多 Agent 的设计目标不是最大并发,而是最小充分独立视角:只派出能改变当前决定的 Worker,并让每份结论都可以追溯、过期、拒绝和重新计算。
参考资料
- OpenAI Agents SDK: Agent orchestration:Manager、Handoff、LLM 编排与代码编排的适用形状。
- Anthropic: How we built our multi-agent research system:Orchestrator-Worker、并行研究、协调失败模式与其系统中的 Token 成本观察。
- Anthropic: Effective context engineering for AI agents:有限 Context、Subagent、Compaction 与按需加载的取舍。
相关文章
从 Workflow Harness 到轻量 Prompt:Codex 5.6 之后我删掉了什么
当模型的原生流程已经够强,Harness 会从效率放大器变成上下文负担。这次重写保留了安全边界,同时大幅精简 Prompt 和运行时。
目标路由:「帮我改一下」和「帮我发个 PR」不该走同一条路
路由不是给请求贴标签,而是先确定这次授权了哪些副作用、什么证据才算完成。