多 agent 并行开发:一套编排纪律
你负责定计划、裁定、验收;子 agent 负责写代码。
这不是「把任务丢出去」,而是一套有纪律的编排。下面是完整方法。
什么时候用,什么时候别用
用:需要多路并行推进、或要在有限时间里把一条长计划跑完。
别用:单个小改动、需要与人密集来回澄清的设计阶段、以及你自己两分钟能做完的事。
派发有固定开销——写任务信、收编、验证。小任务不划算,编排成本会超过它省下的时间。
一、领地划分:约束在共享运行时状态,不在文件路径
最容易犯的错,是按「文件不重叠」推理就并行派发。
这是错的。真正决定能不能并行的,不是文件是否重叠,而是有没有共享的独占资源:
- 开发服务器端口——只给需要端到端验证的那一路,其余任务信里写死「不许起也不许杀」
- 数据库文件与迁移——同一时刻只允许一路动数据层
- 依赖安装与 lockfile——由编排方预先建好包骨架并装好依赖,执行方一律禁止装包
- 版本控制的索引锁——撞上了等几秒重试,绝不许删。删掉别人正在用的锁会毁坏仓库状态
- 索引本身——见下一节
另外,多个实现共用的测试夹具、根配置、公共常量,统一由编排方改,执行方各用自己的夹具。只说「只改自己的目录」不够,共享文件必须点名。
提交范围要用 pathspec 收窄
某个执行方把自己的文件加进索引、还没提交就被打断;你随后加入自己的文件并提交——提交动作提交的是整个索引,于是别人的半成品被裹进一条完全对不上的提交消息里。
正确做法是用 pathspec 形式指定提交范围,而不是「先全部加入索引再提交」。
注意 pathspec 只认已跟踪的文件。新建文件必须先加入索引,此时索引里可能已经有别人的东西,所以加入之后要立刻用同样的路径提交,把范围重新收窄。
这一条要写进每一封任务信。
二、每一轮的固定动作
- 收残留——先看工作区状态。有改动就跑测试,绿则按路径提交,绝不整仓提交
- 验状态——类型检查加测试;关键节点起服务端到端走一遍
- 推送——攒够就推,不要囤
- 派下一批——按计划顺序,一次只派一条链的一小批。被中止时损失小
- 裁定——执行方报上来的设计缺口,能自己定的当场定并落文档
- 更新汇报——维护一个给人看的单一入口文档
**不要在有 agent 在飞的时候跑全量验证。**它们的文件是半成品,类型检查必然红。你会把半成品误判成回归,白白浪费一轮。要么跑范围收窄的,要么等它们落地再跑全量。
三、任务信怎么写
四样东西缺一不可:
领地——写死只改哪个目录,并且逐个点名列出不许碰的目录。说「别碰其他人的」不够,执行方不知道其他人是谁。
为什么这么做——给判断依据,不只给指令。执行方拿到理由才知道边界在哪,才能在遇到没写到的情况时做出合理推断。
验收方式——跑什么命令、什么算通过。
纪律块——固定模板,每封信都带。
两条容易漏的
**范围收窄的测试必须同时要求类型检查。**测试框架不做类型检查。只让执行方跑收窄后的测试,等于在整个并行期间把类型这一层砍掉了——会出现测试全绿而类型检查报一堆错的情况。
**要求「做完一小步就提交」。**后台任务会被中止。攒着不提交的执行方一旦被杀,就是颗粒无收。
四、执行方必须停下上报、不许自行决定的
- 产品语义
- 范围调整
- 引入新依赖
- 不可逆动作
- 两个执行方冲突且双方都有据
- 设计文档本身有错
- 实测推翻了既有结论
在任务信里明写:不要自己拍板,写进报告让编排方裁。
好的执行方会照做,而且它们对自己那一摊的诊断常常比你准。
**另外:不许为了绕过阻塞而 mock 掉生产代码。**如果某个探针导入生产模块失败,正确做法是停下上报,而不是在探针里 mock 一个假实现——那样测出来的就不是真实系统。
最有价值的上报是「你的判断是错的」
这一条要在派单里显式写出来:
如果实测发现我说的根因或模型不成立,如实报告并给数据,不要硬套我的模型。
不写这句,执行方会默认你的模型正确,然后想办法让数据符合它。你最后拿到的是一份「成功验证了错误模型」的漂亮结论。
执行方停下来说「你错了」,比它硬凑一个好看的数字有价值得多。
五、验收纪律:绿色不构成证据
这是整套里最值钱的部分。
因为你不再亲手跑每一步,只能读报告,所以**「看起来对」和「真的对」输出相同**这件事的风险被放大了。
**一、性能数字必须带「东西真的在变」的证据。**光报速度不采信,要有独立的、随负载变化的佐证。而且证据不成立时,让脚本直接抛错,不要照常写出结果。
**二、仪器本身要能自证。**测量要有能力区分「真实的零」和「选择器漏报的零」。优化会改变系统结构,仪器不跟着更新就会开始安静地说谎。
**三、端到端不可省。**单元测试在干净环境里天然是绿的,测不出只在特定运行环境才暴露的问题。
**四、假通过比报错危险得多。**报错至少会被看见;恒真的断言会一直绿着,直到有人偶然发现它什么都没验。所以凡是断言「某东西不存在」,先确认在当前环境里它本来就该存在——否则你验的是环境,不是代码。
**五、修完必须反向验证。**把产品代码故意改坏,确认测试真的会红,再改回来。不能验证它还抓得到 bug 的测试,等于没有。
会随机变红的守卫,等于没有守卫
以墙钟时间为阈值的断言,在并行套件里必然抖动。哪怕余量给得很足,全量跑仍然会偶发失败。
危害不在于「偶尔要重跑」,而在于它会训练所有人忽略这盏红灯。等哪天它因为真回归而变红,没人会当回事。如果它还挡在部署门禁上,那就是在随机拦截部署。
修法不是调大阈值——那只是把抖动推迟到机器更忙的时候。正确做法是测工作量而不是测时间:遍历次数、比较次数、输出条数、请求总量。这些是确定性的,同样能抓算法回归,且不受机器负载影响。
测量前先确认你测的是自己的代码
一个指标如果被第三方服务的延迟主导,它就根本测不到你的实现,优化前后的差值只是波动。
下结论前先单独测一次基础设施本身的耗时,否则你优化的是别人的服务器。
加机器门禁,不要靠「记得」
比如让构建去比对「磁盘上存在的测试文件」和「测试框架实际收集到的集合」,不一致就点名失败。
但没见过它正确失败一次的门禁不算数——加完要做一次反向验证。
六、收编时的态度
**不要只信报告。**关键结论自己复跑一遍。
**关于共享代码的事实断言必须自己查。**执行方对自身处境的描述可信,对别人代码的断言不一定——它看不到全局。
发现报告有误就当场更正,并在文档里留痕,不要静默改掉。
七、派发被中止时
后台通道会成批中止,有时连开发服务器一起带走。这是常态,不是故障。
- 不要恐慌重派——先收残留,跑测试,绿则按路径提交
- 重试一次——这个模式通常会自己恢复,别过早转人工
- 连续多轮失败才转人工——把任务写成自包含的信投进执行方信箱,同时给出可以在自己终端直接跑的命令
- 服务被杀就立刻起回来——可能有人正在看
只要每一轮都收残留,就不会丢工作。
八、裁定要落文档,不要只在对话里说
执行方报上来的设计缺口,你裁定之后要写进设计文档,并说明依据。
理由很直接:下一个 agent 读不到你们的对话,只能读文档。
而且裁定时,写「为什么不那么做」比写「做了什么」有用——后者读代码就知道,前者不写下来,六个月后没人记得。
收束
这套编排可以压缩成三句:
领地划在运行时状态上,不划在文件上。
执行方最有价值的输出是「你错了」,不是「做完了」。
绿色不构成证据。