用任务依赖图降低多智能体合并成本
文章指出,按功能清单分派并行编码任务,容易让各分支对共享接口作出冲突假设。它主张用任务图明确依赖、接口契约和完成证据,再决定哪些工作并行、哪些顺序推进。
AI 深度解读
多个 AI Coding Agent 同时开工,各自测试全绿,合并时却发现接口、权限和业务规则对不上。原文认为,问题往往出在任务拆分阶段:团队列了待办事项,却没有明确任务之间的依赖。
作者提出用任务图组织并行开发:先稳定共享契约,再分发实现任务,最后用可核验的证据交接。它值得读的地方,是把「多开几个 Agent」变成了一套可以检查的协作方法。不过,文中没有团队实测或效率对照,效果仍需结合项目验证。
文件分开了,为什么还是合不到一起
以「增加发票导出」为例,前端做按钮、后端做 API、另一个 Agent 写测试,看起来可以同时开始。但按钮需要知道响应格式,审计事件依赖权限规则,测试也需要确定成功和失败分别是什么。
如果这些决定尚未落定,几个 Agent 就可能各自补出一套答案。代码未必冲突,行为却可能冲突。
作者建议先建立导出契约,再让 API 和 UI 基于契约并行实现,随后验证 API、审计事件和 UI。这里的契约,就是大家共同遵守的接口与行为约定,包括字段、权限、错误和事件载荷。
能否并行,要看行为是否独立,不能只看文件是否分开。
Git worktrees 能隔离工作目录和分支,却不会发现前端仍读取旧字段、后端已经改了字段名。按 frontend、backend、tests 分工,也只是安排角色,没有自动消除依赖。
作者给出的判断很实用:如果一个任务先合并,会迫使另一个任务增加兼容处理、返工,或者重新解释同一条规则,就应该画一条依赖边。
因此,一个 Agent 能独立实现并验证完整行为时,可以交给它一个端到端的纵向切片;涉及共享接口的决定,则适合先做成串行的基础任务。改动跨多少文件,并不是拆分依据。
任务契约要让 Agent 知道何时停手
任务图中的节点不能只有一句标题。它还需要说明输入、负责范围、禁止改动的行为、验收条件,以及完成后提交什么证据。
下面是原文为发票导出 API 提供的任务契约,用来限制实现范围并明确验收方式:
id: invoice-export-api
depends_on:
- export-contract
owns:
paths:
- apps/api/src/invoices/export/**
behavior:
- GET /v1/invoices/:id/export returns a signed download URL
inputs:
contract_ref: docs/contracts/invoice-export.yaml
must_not_change:
- payment-token storage
- existing invoice response fields
acceptance:
- unauthorized callers receive 404
- export never includes payment tokens
- audit event contains invoice ID and actor ID
evidence:
- command: pnpm test invoices:export
- artifact: test-results/invoice-export.xml
handoff:
- changed paths
- commit SHA
- assumptions or newly found dependencies
要重点看 must_not_change:它把「不能顺手整理什么」写进任务。owns 只是声明预计改动范围,不是文件锁;真正的完成标准来自 acceptance,证明方式则由 evidence 指定。
这里的 404、支付令牌脱敏、审计事件包含发票 ID 和操作者 ID,都是示例中的具体约定,不应直接当作所有系统的通用规则。
共享契约也应该成为独立节点。公共 API 字段、数据库迁移、共享领域类型、权限与租户边界、事件名称、feature flag 行为,以及面向用户的错误或重试承诺,都可能影响多个任务。
作者认为,一份带版本的 JSON Schema、附示例的类型接口,或者简短决策记录就可以承担这个角色。关键是验收能拒绝不兼容的示例,而不是文档写得长。
还需要声明 provides 和 consumes,分别表示任务产生什么、依赖什么。原文的例子是:任务 A 增加 Invoice.status = "exporting",任务 B 却只接受 ["draft", "paid"]。即使两者改的是不同文件,也必须增加 A → B 的依赖,或者先更新共享契约。
原文用 ExportResponse v1 连接 API 和 UI 的生产、消费关系。调度前先做拓扑排序,也就是按依赖安排顺序,只启动前置任务已经完成的节点。
并行资格和完成资格,要分开检查
画出了任务图,不代表每个节点都值得单独派一个 Agent。作者提出五个检查问题:
- 是否有明确负责人,并且负责的行为有边界?
- 是否能在不修改未完成共享契约的情况下完成?
- 是否能脱离其他任务尚未合并的代码,运行有意义的检查?
- 评审者是否不用读完其他并行任务,也能理解当前 diff?
- 任务被取消或延期后,功能是否仍处于安全状态?
其中四到五项回答「是」,才算较强的并行候选;只有一到两项,通常说明它依然依赖其他工作,应合并到前置任务,或者排在后面。原文没有明确三项通过时如何处理,需要团队自行判断。
测试也不天然独立。接口没定,测试 Agent 只能等待,或者自己发明预期行为。作者建议把测试夹具和预期行为关联到契约节点;数据库迁移则单独建节点,明确向前执行与回滚行为。
完成后,Agent 应交付一张证据回执,让评审者知道究竟检查了哪个版本:
{
"task": "export-api",
"commit": "8d21c4a",
"base": "f3c980b",
"changed_paths": ["apps/api/src/invoices/export/route.ts"],
"checks": [{"command": "pnpm test invoices:export", "status": "passed"}],
"contract_version": "invoice-export/v1",
"assumptions": [],
"new_dependencies": []
}
关键字段是 new_dependencies。一旦发现新依赖,作者要求暂停该节点、修改任务图,避免 Agent 把范围扩张藏在实现里。commit 和 base 则标明成果版本及其起点,便于后续复核。
任务图决定能否并行开工,合并队列决定成果能否进入主干。
两者承担不同职责。完成门禁检查任务证据,合并队列还要把确定的提交放到最新共享基线上重新验证;某个分支曾经测试通过,不能替代集成检查。
我的判断
这套方法说得最对的地方,是把共享决定从实现任务里拿了出来。否则,最先动手的 Agent 很容易顺便决定接口,其余 Agent 只能追着变化调整。对前端和 Node 协作而言,字段、权限、状态和错误约定,确实比目录划分更能决定并行边界。
但原文是一套流程建议,没有展示实际团队规模、任务耗时、冲突率或采用前后的对照。「少量边界清楚的任务通常更快」是作者的经验判断,不能当成已经验证的效率结论。
它也有维护成本。provides、consumes 和依赖边需要有人准确填写,漏掉业务规则,图仍然可能给出错误的并行许可。原文没有提供自动发现依赖的实现,也没有讲清契约中途变更时如何通知所有下游。
与普通任务清单相比,它更适合共享规则较多的功能;与单 Agent 顺序开发相比,它增加了前期协调工作。对于局部样式或独立小修复,完整套用 YAML 契约和回执可能不划算。比较合理的取舍,是按耦合程度增加约束,把精力花在容易产生返工的共享决定上。
能拿来做什么
- 做前端与 Node 联动功能时,先确定请求、响应、权限和错误示例,再分别派发实现任务。可以从原文的发票导出场景开始检查现有任务是否具备并行条件。
- 给日常 AI 编程任务补上
must_not_change和验收条件,明确禁止改动的周边行为,并提供能验证结果的命令,减少 Agent 顺手扩展范围。 - 并行启动前,检查每个任务提供和消费的接口、类型与事件。发现共享状态值或权限规则尚未确定,就先处理基础节点。
- 收工时要求返回提交、基线、实际执行的检查和新依赖,再交给集成流程复核。把「完成了」变成可以定位和验证的结果。