Hotdry.
ai-systems

Claude Opus 4.6 多智能体团队构建 C 编译器的架构设计与通信机制剖析

深入分析 Anthropic 如何利用 16 个并行 Claude 实例,通过锁文件同步与任务分解策略,在两周内完成一个能够编译 Linux 内核的 Rust 实现 C 编译器。

大语言模型在代码生成领域的能力边界正在被不断重新定义。Anthropic 研究员 Nicholas Carlini 最近发表的技术博客详细披露了使用 Claude Opus 4.6 通过多智能体团队协作构建一个完整 C 编译器的完整工程实践 [1]。这个名为 "Claudes' C Compiler"(CCC)的项目最终生成了约 100,000 行 Rust 代码,能够成功编译 Linux 6.9 内核(支持 x86、ARM 和 RISC-V 架构),在 GCC torture 测试套件上达到 99% 的通过率,并通过了编译并运行 Doom 这一终极检验标准。整个过程消耗约 20,000 美元的 API 成本,历时两周,完成了近 2,000 次 Claude Code 会话。这一实验不仅验证了前沿模型在复杂系统工程中的可行性,更揭示了多智能体协作的关键架构设计与通信机制。

架构设计:去中心化的并行执行框架

该项目最引人注目的设计决策之一是彻底摒弃中央编排架构,转而采用完全去中心化的并行执行模式。每个 Claude 智能体实例运行在独立的 Docker 容器中,共享同一个 Git 仓库作为代码协调的单一数据源。这种架构选择背后有着深刻的工程考量:中央调度器虽然听起来更加优雅,但在实践中往往成为单点故障的根源,并且需要额外的智能体专门负责编排工作,浪费了宝贵的计算资源。

核心的无限循环执行器由一个简单的 bash 脚本实现,它持续不断地启动新的 Claude Code 会话。当一个会话完成其任务后,脚本立即启动下一个会话,形成一个永不停歇的工作流水线。这种设计确保了即使某个会话因为各种原因失败,整个系统仍然能够持续推进。从代码层面来看,这个循环读取一个名为 AGENT_PROMPT.md 的提示文件,将当前项目的完整上下文传递给模型。提示中包含了项目的总体目标、进度追踪机制以及如何自主判断下一步工作方向的指导原则。

在并行执行层面,系统为每个智能体创建一个独立的 Docker 容器,并将共享仓库挂载到容器的 /upstream 目录。每个智能体首先从 /upstream 克隆代码到本地工作目录 /workspace,完成任务后将自己的变更推送到上游,并释放占用的资源。这种隔离设计既保证了并行执行的安全性,又通过 Git 的内置功能解决了版本控制与冲突合并的问题。

任务分解策略:从宏大目标到原子任务

如何在没有人工干预的情况下让智能体自主地将一个宏大的工程目标分解为可执行的小任务,是整个项目成功的关键因素之一。项目采用了 "锁文件" 机制作为任务认领系统的基础。智能体通过在 current_tasks/ 目录下创建特定的文本文件来声明对某个任务的独占权。例如,当某个智能体决定实现数组下标功能时,它会创建 current_tasks/parse_if_statement.txt(实际文件名与任务内容并不严格对应,仅作为锁的标识)来阻止其他智能体同时处理同一任务。

这种设计利用了 Git 的文件级锁定特性来防止并发冲突。当第二个智能体尝试认领已被占用的任务时,Git 的同步机制会强制它选择其他未锁定的任务,从而自然地实现了任务的自动负载均衡。智能体被要求将问题分解为 "小碎片",跟踪自己正在处理的内容,判断下一步应该做什么,并持续推进直到任务完美完成。从实际运行结果来看,智能体在遇到困难时表现出色:它们会维护一个不断更新的失败尝试文档,记录哪些方案已经测试过、哪些仍然需要探索。

测试套件的设计同样遵循了渐进式细化的原则。初期使用相对宽松的验收标准,随着编译器逐渐成熟,测试要求也越来越严格。特别值得一提的是针对 Linux 内核编译的专门优化:当所有智能体反复撞上同一个内核编译 bug 并相互覆盖修复时,研究员引入了 GCC 作为 "在线参考编译器预言机" 的创新方案。新测试框架随机选择内核的大部分文件使用 GCC 编译,仅对剩余文件使用 CCC。如果内核正常工作,则问题不在 CCC 编译的文件子集中;如果失败,则通过重试精确定位具体是哪些文件导致的问题,从而实现了高效的并行调试。

跨智能体通信机制:最小化协调的工程智慧

最令人惊讶的发现可能是:如此复杂的项目居然没有实现任何显式的智能体间通信协议。系统完全依赖三个核心机制来协调工作 —— 共享 Git 仓库作为通信总线、锁文件作为任务分配器、以及智能体自主维护的进度文档。没有任何中央协调者告诉某个智能体应该做什么,每个智能体根据当前仓库的状态自主判断最明显的下一个问题是什么。

这种 "最小化协调" 的设计选择反映了对大语言模型本质能力的深刻理解。强制实施复杂的通信协议往往会导致消息丢失和状态不一致,而依赖 Git 的内置冲突解决机制则利用了一个经过数十年工程验证的工具。当确实发生合并冲突时,Claude 的能力使其能够智能地识别冲突根源并尝试自动解决。实践表明,冲突确实频繁发生,但模型通常能够正确处理。

项目还设置了专门的智能体角色来优化整体产出质量。一个智能体负责合并重复代码,另一个专注于编译器本身的性能优化,第三个负责输出更高效的机器码,还有一个被指派从 Rust 开发者的角度批判性地审视项目设计并提出结构改进建议。这些角色的设置表明,在去中心化的大框架下,适度的专业化可以显著提升整体效率。

工程实践的关键教训与局限性分析

近两千次会话的实践积累了大量宝贵的工程经验。最核心的发现是:测试套件的质量直接决定了智能体团队产出的质量。如果任务验证器存在缺陷,智能体可能会 "解决错误的问题",朝着与预期相反的方向努力。项目投入了大量精力寻找高质量的编译器测试套件,为开源软件包编写验证器和构建脚本,并持续观察智能体容易犯的错误类型,针对性地设计新的测试用例来捕捉这些失败模式。

为每个智能体创建全新的容器环境这一决策带来了意想不到的副作用:由于缺乏上下文积累,每个新会话都需要相当长的时间来 "定位" 自己,特别是在大型项目中。为了缓解这一问题,项目要求智能体维护详尽的 README 和进度文件,并频繁更新当前状态。这种做法使得后续会话能够快速恢复上下文,避免重复工作。

另一个关键的工程权衡是上下文窗口污染问题。测试框架被设计为只打印必要的几行输出,所有重要信息都记录到文件中供智能体按需查找。这种 "少即是多" 的设计哲学确保了有限的上下文窗口被高效利用。项目还特别注意到大语言模型无法感知时间这一特性,因此测试框架实现了默认的 --fast 选项,仅运行 1% 或 10% 的随机样本。这个样本在每个智能体上是确定性的,但在不同虚拟机之间是随机的,既保证了覆盖率又控制了每个会话的计算成本。

尽管成果令人印象深刻,项目仍然暴露出现有方法的明显局限性。生成的代码效率不高,即使开启所有优化选项,输出质量仍然不如 GCC 关闭优化的版本。16 位 x86 实模式支持无法正确实现,最终只能通过调用 GCC 来绕过这一限制。汇编器和链接器部分是项目末期才开始自动化的,目前仍存在 bug。新的功能实现和 bug 修复往往会意外破坏已有的功能,表明在长期维护性方面仍需改进。

这一实验清晰地表明,当前的大语言模型在存在明确定义规范和完备测试套件的场景下,能够完成令人瞩目的复杂系统工程。然而,模糊的需求定义、缺乏测试基准的任务以及需要深度推理的创新性挑战,仍然是这类方法难以企及的领域。多智能体协作的未来发展方向可能集中在如何更智能地设计测试套件、如何在保持去中心化优势的同时减少重复劳动,以及如何将形式化验证方法更深入地集成到智能体工作流程中。

参考资料

[1] https://www.anthropic.com/engineering/building-c-compiler

查看归档