用一队并行的 Claude 写一个 C 编译器
本文作者 Nicholas Carlini,Anthropic 安全团队(Safeguards)研究员。
我在试一种监督语言模型的新方式,我们叫它「agent 团队(agent teams)」:多个 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)需要操作者在线陪着。给它一个又长又复杂的问题,它会解掉一部分,然后停下来等你输入——一个问题、一次状态汇报、或一句澄清。
为了诱导出持续、自主的推进,我搭了个 harness,把 Claude 塞进一个简单的循环里(见过 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
(请在容器里跑,别在你真实的机器上跑。)在 prompt 里,我告诉 Claude 要解的问题,让它拆成小块、记录在做什么、想清楚下一步做什么,然后一直干到完美为止。最后这点 Claude 没得选——循环永远转。(不过有一次我看到 Claude 不小心 pkill -9 bash,把自己杀了、循环也就停了。哎呀。)
让 Claude 并行跑
并行多实例能补单 agent harness 的两个短板:
- 一个 Claude Code 会话一次只能做一件事。项目一大,并行调试多个问题效率高得多。
- 并行允许专业化分工:几个 agent 解主问题,另一些专门 agent 去(比如)维护文档、盯代码质量、解专门的子任务。
我的并行实现很朴素:建一个裸 git 仓库,每个 agent 起一个 Docker 容器、把仓库挂到 /upstream,agent 克隆一份到 /workspace,干完从自己容器 push 回 upstream。
为防止两个 agent 同时解同一个问题,harness 用一个简单的同步算法:
- Claude 通过往
current_tasks/写一个文本文件来给任务上锁(比如一个锁parse_if_statement.txt,另一个锁codegen_function_definition.txt)。两个 agent 抢同一任务时,git 的同步会逼第二个去选别的。 - Claude 干完任务,从 upstream pull、合并别的 agent 的改动、push、再删锁。合并冲突很常见,但 Claude 够聪明,能搞定。
- 那个「无限 agent 生成循环」在新容器里再起一个 Claude Code 会话,循环往复。
这是个很早期的研究原型。我没实现 agent 间的其他通信方式,也没强制任何高层目标管理流程,没有编排 agent(orchestration agent)。我把怎么做完全交给每个 Claude 自己——多数情况它会挑「下一个最显然」的问题,卡在某个 bug 时常常维护一份「失败方案 + 待办」的运行文档。
用 Claude agent 团队编程的经验
脚手架把 Claude 塞进循环,但循环只有在 Claude 能看清「怎样才算有进展」时才有用。我大部分精力花在设计 Claude 周围的环境——测试、环境、反馈——好让它不靠我也能给自己定位。
写极高质量的测试
Claude 会自主地去解我给的任何问题,所以任务验证器必须近乎完美,否则 Claude 会去解错的问题。这要求我找到高质量的编译器测试套件、为开源软件写验证器和构建脚本、盯着 Claude 犯的错、再针对发现的失败模式设计新测试。
例如临近尾声,Claude 开始频繁地「每实现一个新功能就弄坏一个旧功能」。我于是搭了 CI 流水线、加了更严的强制,让 Claude 能更好地测自己的活、新提交不能破坏现有代码。
站在 Claude 的角度想
我得不断提醒自己:这套测试 harness 是为 Claude 写的,不是为我自己写的。每个 agent 都被丢进一个毫无上下文的新容器,要花不少时间给自己定位(大项目尤甚)。所以我在指令里要求它勤维护 README 和进度文件。我还得为语言模型的固有局限专门做设计:
| 局限 | 设计对策 |
|---|---|
| 污染 context window | 测试 harness 不该打印几千个没用的字节。最多打几行,重要信息记到文件里让 Claude 需要时去找。日志要好自动处理:出错就写 ERROR 并把原因放同一行,方便 grep。预先算好汇总统计,省得 Claude 重算 |
| 时间盲(time blindness) | Claude 感知不到时间,放任不管会乐呵呵地花几小时跑测试而非取得进展。harness 只偶尔打印增量进度,并默认带 --fast 选项跑 1% 或 10% 的随机抽样(按 agent 确定、跨 VM 随机,这样既覆盖所有文件、每个 agent 又能精准识别回归) |
让并行变容易
当有很多各自独立的失败测试时,并行很简单:每个 agent 挑一个不同的失败测试去修。测试通过率到 99% 后,每个 agent 转去让一个不同的小型开源项目(SQLite、Redis、libjpeg、QuickJS、Lua 等)能被编译。
但当 agent 开始编译 Linux 内核时卡住了:内核不像「几百个独立测试」,它是一个巨大的整体任务。每个 agent 都撞上同一个 bug、修同一个 bug、然后互相覆盖彼此的改动。16 个 agent 没用,因为它们卡在解同一个任务上。
⭐ 解法是拿 GCC 当一个「已知良好的在线编译器神谕(oracle)」来对照。我写了个新 harness:随机用 GCC 编译内核的大部分文件,只留一小部分用 Claude 的编译器编。内核能跑 → 问题不在 Claude 这部分;坏了 → 再细分、把其中一些文件改回 GCC 编。这样每个 agent 就能并行地在不同文件里修不同 bug,直到 Claude 的编译器能编全部文件。
多种 agent 角色
并行也带来专业化。LLM 写的代码常常重复实现已有功能,于是我派一个 agent 专门合并它发现的重复代码;另一个负责提升编译器自身性能;第三个负责让产出的机器码更高效;还有一个以 Rust 开发者的视角批判项目设计、做结构性改进;再一个写文档。
压测 agent 团队的极限
这个项目是当能力基准来设计的。我感兴趣的是压测「今天的 LLM 刚刚好能勉强做到」的边界,好为「模型将来能稳定做到」做准备。我把这个 C 编译器项目当成贯穿整个 Claude 4 系列的基准。
之前的 Opus 4 系列勉强能产出一个能用的编译器。Opus 4.5 是第一个跨过门槛、能产出可通过大型测试套件的编译器的——但仍编译不了任何真实大项目。我对 Opus 4.6 的目标,是再一次测极限。
结果
两周内、近 2000 次 Claude Code 会话,Opus 4.6 吃掉 20 亿输入 token、生成 1.4 亿输出 token,总成本不到 2 万美元。这是一次洁净室实现(开发全程 Claude 没有联网),只依赖 Rust 标准库。这个 10 万行编译器:
- 能在 x86、ARM、RISC-V 上构建可启动的 Linux 6.9;
- 能编译 QEMU、FFmpeg、SQLite、postgres、redis;
- 在大多数编译器测试套件(含 GCC torture 套件)上99% 通过率;
- 通过了开发者的终极石蕊测试——能编译并运行 Doom。
但它也有不少局限:缺能让 Linux 从实模式启动的 16 位 x86 编译器(这步它直接调 GCC 作弊,仅 x86 如此,ARM/RISC-V 它能完全自编);没有自己的汇编器和链接器;能构建很多项目但非全部;生成代码效率不高(开全部优化也不如 GCC 关全部优化);Rust 代码质量合理但远不及专家水准。
这个编译器已经几乎触到 Opus 能力的上限。我(很努力地)试过修上面几个局限,但没完全成功——新功能和修复频繁地弄坏现有功能。最难的一例:Opus 始终实现不了启动 16 位实模式所需的 16 位 x86 代码生成器(输出超过 60kb,远超 Linux 强制的 32k 限制),最后只能调 GCC 顶上。
展望
每一代语言模型都开启了与之协作的新方式:早期模型用于 IDE 里的 tab 补全;后来能从 docstring 补全函数体;Claude Code 让 agent 进入主流、让开发者能和 Claude 结对编程。但这些产品都假设:用户定义一个任务 → LLM 跑几秒或几分钟返回答案 → 用户再追问。
agent 团队展示了「自主实现整个复杂项目」的可能,这让我们作为工具的使用者,可以把目标定得更野心勃勃。
我们仍处于很早期,而完全自主的开发带有真实的风险。当人坐在 Claude 旁边时,能实时保证质量、当场抓错;自主系统则很容易「看到测试通过就以为大功告成」,而事实往往并非如此。我做过渗透测试,「程序员部署自己从没亲自验证过的软件」这个念头让我真正担忧。
所以这个实验既让我兴奋,也让我不安。造这个编译器是我最近做过最好玩的事之一,但我没料到这在 2026 年初就已经差不多可行。语言模型和我们与之交互的脚手架都在飞速进步,门正在打开——能写的新代码量将极其庞大。我相信正面应用会盖过负面,但我们正在进入一个需要新策略才能安全航行的新世界。