这篇回答一个具体问题:如何让多个 AI Agent 在无人值守下长期并行协作而不跑偏。

最值得拿走的是三条 harness 设计原则:任务校验器要近乎完美,否则 Agent 会努力解决一个错误的问题;测试输出要为模型的上下文污染与时间盲区做优化;用文件锁认领任务、再用 GCC 这类「已知良好」参照把巨型任务切成可并行的子任务。最容易误用的地方,是把测试通过当成任务完成——作者自己也承认自主开发的最大风险正在于此。

站内内容多聚焦单 Agent 工作流与提示工程,这篇给出了多 Agent 并行的工程细节、失败模式与成本数据(约 2 万美元、2000 会话),是中文读者少见的完整一手复盘;国内团队落地时还需叠加容器隔离、代码审查与合规审计等约束。

建议你挑一个有自动化测试的小项目,用文件锁跑一次双 Agent 并行实验,亲身体会任务划分与测试质量对结果的影响。

—— FDEChina编辑部 · 架构师视角

我一直在试验一种新的语言模型监督方式,我们称之为「Agent 团队(agent teams)」。在 Agent 团队模式下,多个 Claude 实例在同一个代码库上并行工作,不需要人类实时干预。这种方式大幅扩展了 LLM Agent 所能做到的事情的范围。为了做压力测试,我给 16 个 Agent 布置了一个任务:从零开始写一个基于 Rust 的 C 编译器,要能编译 Linux 内核。在将近 2000 个 Claude Code 会话、2 万美元 API 成本之后,这支 Agent 团队产出了一个 10 万行的编译器,可以在 x86、ARM 和 RISC-V 上构建 Linux 6.9。

这个编译器本身就是一个有趣的产物,但我在这里更关注的,是我为长时间运行的自主 Agent 团队设计 harness(执行框架)的过程中学到的东西:如何写出能在没有人类监督的情况下让 Agent 保持正轨的测试,如何组织工作让多个 Agent 能并行推进,以及这种方式的边界在哪里。

让 Claude 长时间运行

现有的 Agent 脚手架(如 Claude Code)要求操作者在线并随时配合。如果你请它解决一个又长又复杂的问题,模型可能解决掉一部分,但最终会停下来等待后续输入——一个问题、一次状态更新,或者一个澄清请求。

为了引出持续的、自主的推进,我构建了一个把 Claude 放进简单循环里的 harness(如果你见过 Ralph-loop,这应该很眼熟)。它完成一个任务后立即领取下一个。(请在容器里运行,别在你的真机上跑)。

#!/bin/bash

while true; do
    COMMIT=$(git rev-parse --short=6 HEAD)
    LOGFILE="agent_logs/agent_${COMMIT}.log"

    claude --dangerously-skip-permissions 
           -p "$(cat AGENT_PROMPT.md)" 
           --model claude-opus-X-Y &> "$LOGFILE"
done

在 Agent 提示词里,我告诉 Claude 要解决什么问题,并要求它把问题拆成小块、记录自己正在做什么、决定下一步做什么,并有效地持续推进直到完美。(关于最后一点,Claude 没得选。循环永远运行——不过有一次,我确实看到 Claude 意外执行了 pkill -9 bash,把自己杀掉并终止了循环。哎呀!)

并行运行多个 Claude

并行运行多个实例可以弥补单 Agent harness 的两个弱点:

  • 一个 Claude Code 会话一次只能做一件事。尤其当项目范围扩大时,并行调试多个问题的效率要高得多。
  • 运行多个 Claude Agent 允许分工专业化。当一部分 Agent 负责解决当前的实际问题时,可以调用其他专职 Agent 去(比如)维护文档、盯住代码质量,或解决专门的子任务。

我的并行 Claude 实现非常朴素。新建一个裸 git 仓库,为每个 Agent 启动一个 Docker 容器,把仓库挂载到 /upstream。每个 Agent 把仓库克隆为 /workspace 下的本地副本,完成后从自己的容器推送到 upstream。

为了防止两个 Agent 同时去解决同一个问题,harness 使用一个简单的同步算法:

  • Claude 通过向 current_tasks/ 写入一个文本文件来对一个任务「上锁」(比如一个 Agent 锁定 current_tasks/parse_if_statement.txt,另一个锁定 current_tasks/codegen_function_definition.txt)。如果两个 Agent 试图认领同一个任务,git 的同步机制会迫使第二个 Agent 另选一个。
  • Claude 完成任务,然后从 upstream 拉取、合并其他 Agent 的更改、推送自己的更改、删除锁。合并冲突很频繁,但 Claude 足够聪明,能够处理。
  • 无限的 Agent 生成循环在一个新容器里启动新的 Claude Code 会话,循环往复。

这是一个非常早期的科研原型。我还没有实现任何其他的 Agent 间通信机制,也没有强制任何管理高层目标的流程。我没有使用编排(orchestration)Agent。

相反,我把「怎么做」交给每个 Claude Agent 自己决定。多数情况下,Claude 会挑「下一个最显而易见」的问题。卡在某个 bug 上时,Claude 常常会维护一份滚动更新的文档,记录已失败的方案和剩余任务。在项目的 git 仓库里,你可以翻阅提交历史,看着它对各个任务逐一上锁。

与 Claude Agent 团队协作的经验

脚手架让 Claude 在循环里运行,但只有当 Claude 能判断如何推进时,这个循环才有用。我的大部分精力花在围绕 Claude 设计环境——测试、环境、反馈——让它不需要我也能自我定位。以下是我在编排多个 Claude 实例时发现最有用的做法。

写出极高质量的测试

Claude 会自主地去解决我交给它的任何问题。所以任务校验器(verifier)必须近乎完美,否则 Claude 会去解决一个错误的问题。改进测试 harness 需要寻找高质量的编译器测试套件,为开源软件包编写校验器和构建脚本,观察 Claude 犯的错误,然后在识别出这些失败模式后设计新的测试。

举个例子,项目接近尾声时,Claude 开始频繁地在实现新功能的同时破坏已有功能。为了解决这个问题,我搭建了持续集成流水线,并实施了更严格的强制检查,让 Claude 能更好地测试自己的工作,这样新提交就无法破坏现有代码。

站在 Claude 的角度思考

我必须不断提醒自己:这个测试 harness 是为 Claude 写的,不是为我自己写的,这意味着我要重新审视许多关于「测试应该如何报告结果」的既有假设。

比如,每个 Agent 都被丢进一个没有任何上下文的全新容器,会花大量时间自我定位,在大项目上尤其如此。在触及测试之前,为了让 Claude 能帮上自己,我在指令里就要求它维护详尽的 README 和进度文件,并频繁更新当前状态。

我也时刻记住语言模型有一些固有限制,在本项目里需要围绕它们做设计:

  • 上下文窗口污染:测试 harness 不应打印成千上万字节的无用信息。它最多打印几行输出,把所有重要信息记入文件,让 Claude 在需要时能找到。日志文件应当便于自动处理:出错时应写入 ERROR 并把原因写在同一行,方便 grep 找到。预先计算好汇总统计也很有帮助,省得 Claude 自己重算。
  • 时间盲区:Claude 无法感知时间,放任不管的话,它会心甘情愿地花几个小时跑测试而不推进工作。harness 以较低频率打印增量进度(避免污染上下文),并内置一个默认的 –fast 选项,随机抽取 1% 或 10% 的样本运行。这个子样本对单个 Agent 来说是确定性的,但在不同虚拟机之间是随机的,这样 Claude 仍然能覆盖所有文件,而每个 Agent 都能精确识别回归。

让并行变得容易

当存在许多互不相同的失败测试时,并行化是轻而易举的:每个 Agent 挑一个不同的失败测试去修。测试套件通过率达到 99% 之后,每个 Agent 转而负责让一个不同的小型开源项目(如 SQLite、Redis、libjpeg、MQuickJS、Lua)编译通过。

但当 Agent 们开始编译 Linux 内核时,它们卡住了。与拥有数百个独立测试的测试套件不同,编译 Linux 内核是一整个巨型任务。每个 Agent 都会撞上同一个 bug、修掉它,然后互相覆盖对方的修改。跑 16 个 Agent 无济于事,因为每个都在解同一道题。

解决办法是把 GCC 当作一个在线的「已知良好」编译器 oracle 来对照。我写了一个新的测试 harness:用 GCC 随机编译内核的大部分文件,只用 Claude 的 C 编译器编译剩下的文件。如果内核能工作,那问题就不在 Claude 负责的那部分文件里;如果构建失败,就进一步用 GCC 重新编译其中一些文件来缩小范围。这让每个 Agent 都能并行推进,在不同文件里修不同的 bug,直到 Claude 的编译器最终能编译所有文件。(这一招奏效之后,仍需要应用 delta debugging(增量调试)技术来找出那些「单独都能过、合在一起就挂」的文件对。)

多种 Agent 角色

并行还让分工专业化成为可能。LLM 写的代码经常重复实现已有功能,所以我安排一个 Agent 专门合并它发现的重复代码。另一个负责提升编译器本身的性能,第三个负责让编译产出的代码更高效。我让另一个 Agent 以 Rust 开发者的视角点评项目设计,并对项目做结构性调整以提升整体代码质量;还有一个负责文档。

压测 Agent 团队的极限

这个项目被设计成一个能力基准。我有兴趣压测今天的 LLM「刚刚勉强能做到」的边界,以帮助我们为未来模型将稳定做到的事情做好准备。

我一直在把 C 编译器项目当作覆盖整个 Claude 4 系列的基准。与之前的项目一样,我先起草我想要的东西:一个从零开始、零依赖、GCC 兼容、能编译 Linux 内核、设计上支持多后端的优化编译器。我指定了设计的某些方面(比如要有 SSA IR 以支持多轮优化 pass),但没有对如何实现做任何细节规定。

之前的 Opus 4 模型勉强能产出一个能用的编译器。Opus 4.5 是第一个跨过门槛、能产出可通过大型测试套件的可用编译器的模型,但仍无法编译任何真实的大型项目。我对 Opus 4.6 的目标,是再一次试探极限。

评估

在两周内、近 2000 个 Claude Code 会话中,Opus 4.6 消耗了 20 亿输入 token,生成了 1.4 亿输出 token,总成本略低于 2 万美元。即使与最贵的 Claude Max 订阅方案相比,这也是一个极其昂贵的项目。但这笔钱只是我自己动手把它做出来所需成本的一小部分——更别提一整个团队了。

这是一个净室实现(clean-room implementation,Claude 在整个开发过程中没有接入互联网);它只依赖 Rust 标准库。这个 10 万行的编译器可以在 x86、ARM 和 RISC-V 上构建可启动的 Linux 6.9。它还能编译 QEMU、FFmpeg、SQLite、postgres、redis,并且在包括 GCC torture test suite 在内的大多数编译器测试套件上达到 99% 的通过率。它也通过了开发者的终极试金石:能编译并运行 Doom。

不过,这个编译器并非没有局限:

  • 它缺少从实模式(real mode)启动 Linux 所必需的 16 位 x86 编译器,这一步它调用 GCC 完成(x86_32 和 x86_64 编译器是它自己的)。
  • 它没有自己的汇编器和链接器;这是 Claude 最后开始自动化、目前仍有些 bug 的部分。演示视频是用 GCC 的汇编器和链接器制作的。
  • 它能成功构建很多项目,但不是全部。它还不是真实编译器的即插即用替代品。
  • 生成的代码效率不高。即使开启全部优化,它输出的代码也比关闭全部优化的 GCC 更低效。
  • Rust 代码质量尚可,但与专家级 Rust 程序员的水准相去甚远。

最终产出的编译器已经接近 Opus 能力的极限。我努力尝试(真的很努力!)修复上面几项局限,但没有完全成功。新功能和 bug 修复经常破坏已有功能。

一个特别有挑战性的例子是:Opus 无法实现从 16 位实模式启动所需的 16 位 x86 代码生成器。虽然编译器可以通过 66/67 操作码前缀输出正确的 16 位 x86 代码,但产出的编译结果超过 60KB,远超 Linux 强制执行的 32K 代码上限。于是 Claude 在这里直接「作弊」,这一阶段调用 GCC 完成(只有 x86 是这样。对 ARM 或 RISC-V,Claude 的编译器可以完全靠自己编译。)

编译器源码已经公开。下载它、通读代码、在你喜欢的 C 项目上试一试。我一直发现,理解语言模型能做什么的最好方式,就是把它们推到极限,然后研究它们从哪里开始崩溃。接下来几天我会继续让 Claude 推送新的更改,如果你想跟进 Claude 应对这些局限的持续尝试,可以关注。

展望未来

每一代语言模型都会打开新的使用方式。早期模型可用于 IDE 里的 tab 补全。不久之后,模型能根据 docstring 补全一个函数体。Claude Code 的发布让 Agent 走向主流,开发者可以与 Claude 结对编程。但以上每一种产品都建立在一个假设上:用户定义一个任务,LLM 运行几秒或几分钟返回答案,然后用户给出下一步指示。

Agent 团队展示了自主完成整个复杂项目的可能性。这让我们这些工具的使用者可以对自己的目标更有雄心。

我们仍处于早期,完全自主的开发伴随真实的风险。当人类在开发过程中陪坐在 Claude 旁边时,可以保证质量的一致性并实时抓错。对自主系统来说,很容易看到测试全部通过就认为工作完成,而事实很少如此。我以前做渗透测试,专门利用大公司产品中的漏洞,因此「程序员部署自己从未亲自验证过的软件」这种前景对我来说是一个真实的担忧。

所以,这个实验让我兴奋,也让我不安。造这个编译器是我近来最有趣的经历之一,但我没想到这在 2026 年初就几乎成为可能。语言模型和我们用来与之交互的脚手架的快速进步,为写出海量的新代码打开了大门。我预计正面应用会压过负面,但我们正在进入一个新世界,需要新的策略来安全航行。

致谢

特别感谢 Josef Bacik、Edwin Chen、Bernardo Meurer Costa、Jake Eaton、Dan Kelley、Felix Klock、Jannet Park、Steve Weis 以及 Anthropic 内外许多其他人士的帮助与贡献。

延伸阅读:想深入了解多 Agent 协作与编排,参见 Agent 主题页AI Coding 主题页;如何为 AI 系统设计测试与评估体系,可参考 FDE 能力模型;把这类方法落到具体项目里,见 FDE 项目生命周期指南

本文由 FDEChina 团队翻译自原文,转载已注明出处;如需引用请以原文为准。