以 C 编译器实验为例,理解并行 Agent 怎样通过独立工作区、任务锁和 Git 协作,以及语义冲突、故障拆分、测试反馈和角色分工。
多智能体研究主要交换资料与结论。共同开发代码时,交换的是会改变项目行为的补丁:一个 Agent 修改了接口,其他 Agent 的工作条件就可能随之变化。
因此,并行开发需要同时组织三件事:谁正在做哪项任务、代码变化怎样进入共同版本、组合后的项目怎样验证。 工作区、任务锁和测试分别参与其中,没有一种机制能单独覆盖全部问题。
Anthropic 的 C 编译器实验提供了一个具体案例:16 个 Agent 共同开发 Rust 实现的 C 编译器。这里借它理解协作机制:
- 状态与隔离: 各自编辑和运行,怎样与共享仓库保持联系。
- 认领与集成: 怎样减少重复劳动,怎样处理文本和行为冲突。
- 并行性与反馈: 怎样把共同瓶颈拆成独立工作,再用测试与专门角色推进项目。
一、多个 Agent 怎样在同一项目中工作h2
先区分共享的项目状态与各自操作的工作空间,再看任务归属怎样传播给其他参与者。
1. Shared Repository:通过代码与任务记录协作h3
共享仓库协作,是让多个 Agent 根据共同可见的项目状态选择工作,再通过提交交换修改。协调信息可以存在源码、任务记录、测试结果和进度文件中,不一定由一个中心 Agent 逐项分派。
这个编译器实验没有 Orchestrator Agent。各 Claude 会话自行选择下一项工作;人和 Harness 负责建立总体目标、运行环境与验证条件。
这与 Lead / Subagent 研究架构的区别,是任务安排与整合责任放在了不同位置。研究 Lead 收回材料后形成报告;共享项目则持续把修改纳入同一个代码版本。
可以把它的工作循环理解为:
读取项目状态 → 认领任务 → 修改与测试 → 同步共同版本 → 更新任务与进度
这里同步的不只是源码。其他 Agent 还需要知道哪些问题已经解决、哪些任务有人处理,以及哪些失败已经调查过。代码和协作记录一起构成下一轮工作的起点。
2. Workspace Isolation:独立操作与版本同步h3
工作区隔离解决独立操作,版本同步解决变化传播。
如果几个 Agent 直接编辑同一个目录,A 正在测试时,B 可能已经改了输入文件;测试结果就难以对应到一份明确代码。独立工作区让各 Agent 可以分别编辑、构建和运行,知道当前操作针对哪一份状态。
实验中,每个 Docker 容器都挂载共享裸仓库到 /upstream,再克隆到自己的 /workspace。各 Agent 操作本地副本,通过 Git 交换提交。
本地副本不会自动等于共同版本
A 的测试可能基于版本 V,B 此时已经推送了修改。A 本地通过,只能说明自己的这份状态通过。拉取 B 的提交以后,测试对象已经改变,需要重新检查组合状态。
由此可以分开两个判断:
- 我的修改在当前工作区是否成立?
- 我的修改与其他提交组合后,项目是否仍然成立?
这不是多跑一次同样的测试,而是在验证两份不同的代码状态。
进度记录补充源码没有表达的信息
代码可以说明现在实现了什么,却未必说明为何这样实现、已经排除了哪些假设。新会话需要借助 README、失败记录和进度文件恢复工作位置。
例如,“参数传递失败”还不足以接续调查;对应的目标架构、失败用例、相关提交与已尝试方案,才能减少重复定位。记录也应随项目更新,否则它会把旧判断传给下一轮。
3. Task Lock:认领任务与减少重复劳动h3
Task Lock 表达的是任务归属:当前这项工作已经有人处理。 它让其他 Agent 在选择任务前看到已有安排。
实验使用 current_tasks/ 下的文本文件记录认领。两个 Agent 争抢同一任务时,需要通过 Git 同步竞争认领状态,后者转向其他任务。工作完成后,修改与其他提交合并,再更新或移除认领标记。
理解这个机制,最重要的是区分本地意图与共享状态。A 只在自己的目录里写下“我要修复 X”,B 未必知道;认领信息进入大家采用的同步流程以后,才具有协调作用。
任务锁的粒度是任务,不是所有相关代码
“修复解析条件语句”和“调整表达式表示”可以是两个任务名,但可能同时修改一组类型。任务名不同,并不意味着涉及的文件或接口互不影响。
锁也不能自动识别两个失败用例是否来自同一根因。如果大家分别认领了不同测试,最后都去改同一个基础模块,重复工作仍可能发生。
因此,任务认领要配合进度与失败归因。它减少的是无意重复,代码能否组合还要由集成与验证决定。
二、代码冲突与共同故障怎样处理h2
独立工作不等于修改互不影响。代码需要整合,共同失败也需要拆成能够分别调查的问题。
4. Git Merge:整合补丁与检查语义冲突h3
Git Merge 整合不同提交,首先处理的是文件内容怎样组合。并行开发还需要检查组合之后的程序含义。
| 冲突 | 怎样发生 | 怎样发现与处理 |
|---|---|---|
| 文本冲突 | 两份补丁修改相同代码区域,Git 无法自动合并 | 对照两项任务的意图,手动调整补丁 |
| 语义冲突 | 文本能够合并,但接口、假设或行为不兼容 | 编译、集成测试和行为验证 |
例如,A 把一个函数的返回值改成“字节数”,B 在另一个文件中仍把它当作“元素数”。两份修改没有碰到同一行,Git 可能顺利合并,程序却已经改变含义。
这说明“没有冲突”有两种完全不同的意思:没有需要人工处理的文本冲突,不代表不存在行为冲突。
集成时需要核对的不只是自己的差异,还包括依赖条件是否变化。接口、公共类型和基础设施修改,尤其容易影响其他任务。专门角色与任务锁可以帮助分工,却不能省略共同版本的验证。
5. GCC Oracle:拆分可以独立排查的故障h3
并行性取决于能否拆出可分别调查的子问题。
几十个互不相关的失败测试,容易分派给不同 Agent;一次大型构建只暴露第一个失败点,则可能让所有 Agent 都停在同一个位置。此时增加 Agent,往往增加的是竞争修复。
GCC Oracle:用已知可用实现缩小失败范围
编译 Linux 内核时,实验确实出现了大家围绕同一个 bug 重复工作的情况。解决办法是改变验证方式:大部分文件交给 GCC 编译,只让剩余部分交给待测编译器,再检查混合构建结果。
如果失败,继续把可疑集合中的一部分改用 GCC,观察故障是否仍然出现。这样可以逐步缩小触发问题的范围。
这里的 Oracle 是提供参考行为的已知可用实现。它的作用不是让 Agent 阅读 GCC 源码,而是帮助控制变量:哪些文件由待测编译器负责,哪些变化与故障出现有关。
不同 Agent 因而可以调查不同文件集合。协作单位从“都让整个内核编译通过”,变成了“分别定位某个可复现故障”。
组合故障:单独通过不代表一起通过
实验还需要 delta debugging,寻找单独使用正常、组合时失败的文件对。独立子集的测试结果,不能完全代替组合行为。
我从这个例子提取的重点是:测试不仅能验收结果,还能改变任务的可拆分程度。能定位失败边界,才容易划分责任;始终只得到同一条“大任务失败”,就很难形成有效并行。
三、开发结果怎样验证与持续改进h2
测试提供修改是否成立的证据,专门角色则持续处理功能之外的质量目标。
6. Testing:局部验证、集成验证与回归检查h3
并行 Agent 要根据测试反馈选择下一项工作。验证器既影响“什么算完成”,也影响“接下来该查哪里”。
局部验证:确认本次修改确实解决目标问题
最小复现或专项测试,可以帮助把结果与当前补丁联系起来。没有这一步,只看到整个项目偶尔成功,很难说明本次修改产生了什么作用。
集成与回归:检查共同版本和已有能力
集成检查关注其他补丁加入后的组合;回归检查关注新增功能是否破坏过去正常的行为。实验后期出现功能反复退化,因此增加了更严格的 CI 验证。
这两类检查解释了为什么“我负责的测试通过”不等于“团队可以继续叠加修改”:后续 Agent 使用的是共同项目,而不是那一个孤立用例。
反馈表达:先给定位入口,再提供详细记录
终端可以返回失败项目、关键错误和日志位置,完整记录放到外部供按需读取。这样下一轮能够直接进入有关证据,而不必从海量输出中重新搜索。
快速抽样则缩短一次修改后的等待。实验让单个 Agent 内的样本保持稳定、不同虚拟机使用不同样本,兼顾前后比较与团队覆盖。抽样适合开发反馈,最终覆盖范围仍应按验收目标安排。
7. Specialized Roles:分工维护性能、结构与文档h3
任务分解按问题划分,角色分工则按持续职责划分。两者可以配合:功能 Agent 修复当前失败,性能或质量角色处理跨模块问题。
编译器里就存在两类不同性能目标:
- 编译器自身性能: 编译项目需要多长时间、消耗多少资源。
- 生成代码性能: 被编译出来的程序运行得怎样。
合并重复实现、审查 Rust 结构和维护文档,又是其他职责。分别关注这些目标,能减少团队只追逐眼前失败测试的倾向。
不过,跨模块工作也更容易改变其他人的条件。去重可能调整接口,结构修改可能影响正在开发的后端。因此,角色分工需要与任务认领、同步和验证一起使用。
这项实验在多种架构上构建了 Linux 6.9,但发布时仍有外部工具链依赖、生成代码效率与代码质量等限制。它展示了并行协作能够推进大型产物,也展示了测试覆盖、并行性和工程成熟度是不同的问题。实验报告与限制
几个关键问题,串起任务认领、代码集成与验证h2
独立工作区解决了什么,又没解决什么?
它让编辑和执行针对各自明确的本地状态。提交进入共享版本以后,修改仍会互相影响,因此不能替代集成验证。
为什么任务认领需要同步?
没有传播出去的认领只是本地记录。其他 Agent 需要在选择工作前取得共享状态,才能据此避开已有任务。
Task Lock 和 Git Merge 能否保证协作正确?
任务锁协调工作归属,Merge 整合文本版本;行为是否兼容仍要检查。两者都不能单独保证程序正确性。
没有文本冲突,为什么测试还会失败?
不同补丁可能对接口含义、数据格式或执行顺序作出不兼容假设。语义冲突可以发生在完全不同的文件里。
GCC Oracle 怎样帮助恢复并行性?
混合编译与逐步替换文件,让大型失败能够被归因到更小集合。不同 Agent 因而有了可以分别调查的故障范围。
为什么快速测试与完整验收要分开?
前者缩短反馈周期,帮助定位和比较修改;后者检查更完整的目标与组合。通过快速样本,说明的是这些样本没有暴露问题。
无中心协调 Agent,是否就等于 Handoff?
不是。这里通过任务记录与共享产物协调工作;Handoff指的是执行控制权从一个 Agent 转给另一个 Agent,机制不同。