用一组并行 Claude 构建 C 编译器

举报
yd_298479158 发表于 2026/09/28 23:04:54 2026/09/28
【摘要】 最近,我一直在尝试一种新的语言模型监督方式,我们把它称为:Agent Teams,Agent 团队。在 Agent Teams 中,多个 Claude 实例会同时在同一个代码库上并行工作,而不需要人类持续在线干预。这种方式显著扩大了 LLM Agent 能够完成的任务规模。为了做压力测试,我让 16 个 Agent 从零开始编写一个基于 Rust 的 C 编译器,并要求它能够编译 Linux...

最近,我一直在尝试一种新的语言模型监督方式,我们把它称为:

Agent Teams,Agent 团队。

在 Agent Teams 中,多个 Claude 实例会同时在同一个代码库上并行工作,而不需要人类持续在线干预。

这种方式显著扩大了 LLM Agent 能够完成的任务规模。

为了做压力测试,我让 16 个 Agent 从零开始编写一个基于 Rust 的 C 编译器,并要求它能够编译 Linux Kernel。

经过近 2,000 次 Claude Code Session,以及约 20,000 美元 API 成本之后,这组 Agent 最终产出了一个约 10 万行代码的编译器。

它能够在以下架构上编译 Linux 6.9:

  • x86;
  • ARM;
  • RISC-V。

这个编译器本身已经是一个很有意思的产物,但本文更关注我从中学到的关于长时间运行、自主 Agent Team Harness 设计的经验:

  • 如何写测试,让 Agent 在没有人类监督的情况下保持正确方向;
  • 如何组织工作,让多个 Agent 真正能够并行推进;
  • 这种方法最终会在哪里撞到能力上限。

让 Claude 长时间持续运行

现有 Agent Scaffold,例如 Claude Code,通常默认用户在线,并与 Agent 共同工作。

如果让模型解决一个非常长、非常复杂的问题,它可能完成其中一部分,但最终通常会停下来等待用户继续输入,例如:

  • 回答一个问题;
  • 查看状态更新;
  • 澄清需求。

为了让 Agent 能够持续、自主推进,我构建了一个非常简单的 Harness,把 Claude 放进一个无限循环里。

如果你见过 Ralph Loop,这个结构应该很熟悉。

一个任务完成后,它会立刻开始下一个任务。

请把下面的脚本运行在 Container 里,而不是你的真实机器上。

#!/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 Prompt 中,我会告诉 Claude:

  • 需要解决什么问题;
  • 把问题拆成较小部分;
  • 持续追踪当前工作;
  • 判断下一步应该做什么;
  • 一直继续,直到整个项目足够完善。

最后这一点 Claude 实际上没有选择权。

因为循环会永远运行。

不过,有一次 Claude 意外执行了:

pkill -9 bash

结果把自己的父进程杀掉了,也顺便结束了无限循环。

算是一次小事故。

并行运行 Claude

并行运行多个实例,可以缓解单 Agent Harness 的两个弱点。

1. 单个 Claude Code Session 一次只能做一件事

随着项目规模扩大,如果存在多个 Bug,同时调试显然比串行处理效率高得多。

2. 多 Agent 可以产生专业化分工

除了让若干 Agent 直接解决核心问题之外,还可以让其他 Agent 专门负责:

  • 文档维护;
  • 代码质量;
  • 性能;
  • 特定子任务。

我的并行 Claude 实现非常简单。

系统会先创建一个新的裸 Git Repository。

然后:

  1. 为每个 Agent 启动一个 Docker Container;
  2. 把共享 Repository 挂载到:
/upstream
  1. 每个 Agent 把 Repository 克隆到自己的本地目录:
/workspace
  1. Agent 完成任务后,再从自己的 Container 把修改 Push 回共享 Upstream。

防止多个 Agent 同时做同一个任务

Harness 使用了一个非常简单的同步算法。

第一步:通过文件抢占任务锁

Claude 会在:

current_tasks/

目录中写一个文本文件,表示自己已经接下某项任务。

例如:

current_tasks/parse_if_statement.txt

另一个 Agent 可能同时锁定:

current_tasks/codegen_function_definition.txt

如果两个 Agent 同时尝试领取同一个任务,Git 的同步机制会迫使第二个 Agent 改选其他任务。

第二步:完成任务并合并

Claude 完成任务后,会:

  1. 从 Upstream 拉取最新改动;
  2. 合并其他 Agent 的修改;
  3. Push 自己的修改;
  4. 删除自己的任务锁。

Merge Conflict 很常见。

不过 Claude 足够聪明,通常能够自行处理。

第三步:重新启动一个全新 Session

无限 Agent Generation Loop 会在新的 Container 中创建一个新的 Claude Code Session。

然后继续重复整个循环。

这仍然只是一个非常早期的研究原型。

目前我还没有实现:

  • Agent 之间的其他直接通信方式;
  • 高层目标管理流程;
  • Orchestration Agent。

我基本把决策全部交给各个 Claude Agent 自己。

大多数情况下,Claude 会选择:

下一个最明显的问题。

当它被某个 Bug 卡住时,Claude 经常会自己维护一份持续更新的文档,记录:

  • 已经尝试过哪些失败方案;
  • 还有哪些任务没有完成。

从项目 Git History 中,可以看到这些 Agent 如何不断:

  • 抢占任务;
  • 完成任务;
  • 释放任务锁;
  • 推进代码库。

使用 Claude Agent Team 编程时学到的经验

Harness 只是让 Claude 循环执行。

但只有当 Claude 能够判断:

怎样才算取得进展

时,这个循环才真正有意义。

我的大部分精力,其实都花在了围绕 Claude 设计环境:

  • 测试;
  • 执行环境;
  • 反馈机制。

目标是让它能够在没有我参与的情况下自行定位当前状态。

下面这些方法,是我在编排多个 Claude 实例时最有帮助的经验。

编写极高质量的测试

Claude 会非常认真地自主解决你交给它的问题。

所以:

任务验证器必须几乎完美。

否则 Claude 会极其高效地解决错误的问题。

改进测试 Harness 的过程包括:

  • 寻找高质量编译器测试套件;
  • 为开源软件包编写验证器;
  • 编写 Build Script;
  • 观察 Claude 常犯哪些错误;
  • 根据这些失败模式增加新的测试。

例如,在项目后期,Claude 经常会出现一种问题:

每实现一个新功能,就破坏一些已有功能。

为了解决这一点,我建立了 CI Pipeline,并加强了测试约束。

这样,Claude 能够更可靠地测试自己的工作,并阻止新 Commit 破坏已有代码。

站在 Claude 的角度思考

我必须持续提醒自己:

这套测试 Harness 是写给 Claude 用的,不是写给我自己用的。

这意味着必须重新思考很多关于测试输出方式的默认假设。

例如,每个 Agent 都会被放进一个:

  • 全新的 Container;
  • 完全没有上下文。

对于大型项目,它可能花很多时间重新理解项目现状。

所以,在真正进入测试之前,我就给 Claude 提供了一些帮助它理解项目的机制。

例如,我要求它持续维护:

  • 大量 README;
  • Progress File;

并频繁更新当前状态。

同时,还必须针对语言模型本身的一些天然限制做设计。

其中包括:

上下文窗口污染

测试 Harness 不应该打印几千字节没有价值的输出。

最多只应该打印:

  • 少量几行摘要。

所有重要细节都写进日志文件中,让 Claude 在真正需要时再读取。

日志文件还应该方便自动处理。

例如:

如果发生错误,就应该在同一行中写:

ERROR

以及具体原因。

这样 Claude 就可以直接用:

grep

定位问题。

最好还提前计算汇总统计数据,避免 Claude 自己重新计算。

时间盲区

Claude 没有真正的时间感。

如果完全不加约束,它很可能花数小时一直运行测试,而不是继续推进任务。

因此,我的 Harness:

  • 只偶尔打印增量进度,避免污染 Context;
  • 默认提供:
--fast

选项。

这个选项只运行:

  • 1%;
  • 或 10%;

的随机样本。

这些抽样对于:

同一个 Agent 是确定性的

但在不同 VM 之间:

又是随机的。

这样一来:

  • 不同 Agent 总体上仍然能够覆盖全部测试;
  • 每个 Agent 又可以稳定识别自己修改造成的 Regression。

让并行化尽可能容易

当测试套件中有很多彼此独立的失败项时,并行化非常简单。

每个 Agent 只需要选择一个不同的失败测试进行修复。

当整个测试套件通过率达到:

99%

之后,我让不同 Agent 分别尝试让不同小型开源项目通过编译。

例如:

  • SQLite;
  • Redis;
  • libjpeg;
  • MQuickJS;
  • Lua。

这种任务天然可以并行。

但当 Agent 开始尝试编译 Linux Kernel 时,系统卡住了。

原因在于:

与拥有数百个独立测试的测试套件不同,编译 Linux Kernel 是一个巨大的单体任务。

每个 Agent 都会:

  1. 遇到同一个 Bug;
  2. 尝试修复同一个 Bug;
  3. 最后互相覆盖修改。

所以即使同时运行 16 个 Agent,也没有真正提高效率。

使用 GCC 作为在线已知正确 Oracle

为了解决这个问题,我使用:

GCC

作为一个已知正确的编译器 Oracle。

我写了一套新的测试 Harness。

它会随机地:

  • 使用 GCC 编译 Linux Kernel 中的大多数文件;
  • 使用 Claude 的 C 编译器编译剩余文件。

如果最终 Kernel 能够工作:

说明问题不在 Claude 编译器负责的那部分文件中。

如果 Kernel 失败:

系统就可以继续缩小范围,把其中一部分文件改回 GCC 编译。

这样,每个 Agent 就可以在不同文件上并行工作:

  • 定位不同 Bug;
  • 修复不同 Bug。

最终,Claude 的编译器逐渐可以接管越来越多文件,直到能够编译全部文件。

即便如此,还需要使用:

Delta Debugging

进一步寻找这种特殊情况:

  • 两个文件单独编译都没问题;
  • 但一起编译时会失败。

多 Agent 角色分工

并行系统的另一个优势,是可以做专业化。

LLM 生成的代码经常会重复实现已有功能。

因此,我让一个 Agent 专门:

合并重复代码。

另一个 Agent 负责:

提高编译器自身性能。

第三个 Agent 负责:

让生成的机器码更加高效。

我还让一个 Agent:

从 Rust 开发者视角批评项目设计,并对整体结构进行调整,从而提升代码质量。

另外还安排一个 Agent 专门:

维护文档。

对 Agent Team 的能力上限做压力测试

这个项目本质上是一个:

Capability Benchmark。

我真正感兴趣的是:

测试 LLM 在今天刚刚勉强能够实现什么。

这样可以帮助我们提前理解:

未来模型能够稳定实现什么。

我已经在整个 Claude 4 系列模型上,把这个 C 编译器项目当作长期 Benchmark 使用。

和我之前做过的项目一样,我一开始只写了一份高层要求。

目标是构建:

  • 从零实现;
  • 带优化能力;
  • 没有外部依赖;
  • GCC Compatible;
  • 能编译 Linux Kernel;
  • 支持多个 Backend;

的 C 编译器。

我指定了一些设计要求。

例如:

应该拥有:

SSA IR

这样可以支持多个 Optimization Pass。

但我并没有详细告诉 Claude:

具体该怎么实现。

不同 Opus 版本的能力变化

早期 Opus 4 系列模型,只能勉强写出一个能工作的编译器。

Opus 4.5 是第一个跨过某个能力阈值的模型。

它能够:

  • 构建真正可用的编译器;
  • 通过大型测试套件。

但它依然无法编译大型真实项目。

所以,使用 Opus 4.6 时,我再次把目标设为:

继续探索它的能力边界。

评测结果

两周内,项目总共运行了:

近 2,000 次 Claude Code Session。

Opus 4.6 消耗了:

20 亿 Input Token

并生成了:

1.4 亿 Output Token。

总成本:

略低于 20,000 美元。

和最昂贵的 Claude Max 订阅相比,这当然是一个极其昂贵的项目。

但如果让我自己完成同样的工作,这依然只是人工成本的一小部分。

更不用说:

如果需要组建一个完整团队来完成它,成本还会更高。

最终编译器能力

这是一个 Clean-room Implementation。

Claude 在整个开发过程中:

完全没有互联网访问。

编译器只依赖:

Rust Standard Library。

最终,这个约 10 万行代码的编译器能够在以下架构上构建可启动的 Linux 6.9:

  • x86;
  • ARM;
  • RISC-V。

它还能够编译:

  • QEMU;
  • FFmpeg;
  • SQLite;
  • PostgreSQL;
  • Redis。

在大多数编译器测试套件中,它的通过率达到:

99%

其中包括:

GCC Torture Test Suite。

它还通过了开发者最经典的最终测试:

可以编译并运行 Doom。

编译器仍然存在的局限

当然,这个编译器并不完美。

它依然有很多明显限制。

1. 缺少 16-bit x86 编译器

从 Real Mode 启动 Linux 时,需要 16-bit x86 Code Generator。

目前这个阶段仍然会调用 GCC。

不过:

  • x86_32;
  • x86_64;

都是它自己实现的。

2. 没有完整自研 Assembler 和 Linker

Claude 在项目最后阶段才开始自动实现:

  • Assembler;
  • Linker。

目前它们依然存在不少 Bug。

演示视频使用的是 GCC 的:

  • Assembler;
  • Linker。

3. 并不能编译所有项目

它能够成功构建许多真实项目。

但并不是所有项目。

因此,目前还不能直接当作真正编译器的 Drop-in Replacement。

4. 生成代码效率较低

即使开启所有 Optimization:

它生成的机器码效率依然比:

完全关闭 Optimization 的 GCC

还要差。

5. Rust 代码质量只是“还可以”

整个 Rust Codebase 的质量合理。

但和真正专家级 Rust 程序员相比:

仍然有明显差距。

逼近 Opus 的能力极限

最终这个编译器已经非常接近 Opus 当前的能力上限。

我非常努力地尝试修复上面的一些限制,但没有完全成功。

继续开发时,经常发生:

  • 添加新功能;
  • 修复新 Bug;
  • 却破坏已有功能。

其中一个特别困难的问题,就是:

16-bit x86 Code Generator。

Linux 从 16-bit Real Mode 启动时需要这部分能力。

Opus 无法真正实现一个符合要求的 16-bit x86 Code Generator。

它虽然能够通过:

66

和:

67

Opcode Prefix

生成正确的 16-bit x86 代码,

但最终输出大小超过:

60KB

而 Linux 对这一阶段代码大小的限制只有:

32KB

所以最终:

Claude 在这里“作弊”了。

它直接调用 GCC 完成这一阶段。

不过,这个限制只存在于:

x86。

对于:

  • ARM;
  • RISC-V;

Claude 的编译器可以完全自行完成整个编译流程。

为什么公开源码很重要

这个编译器的源码已经公开。

我建议:

  • 下载它;
  • 阅读代码;
  • 用你喜欢的 C 项目测试它。

我一直认为,理解语言模型真正能力的最佳方法就是:

把模型推到极限,然后研究它在哪里开始崩溃。

接下来,我还会继续让 Claude 对这个项目提交新修改,继续尝试解决这些剩余限制。

展望未来

每一代语言模型,都会打开一种新的协作方式。

早期模型主要用于:

IDE Tab Completion。

没过多久,模型已经可以:

根据 Docstring 自动补完整个 Function Body。

Claude Code 的推出,则让 Agent 真正进入主流开发流程,使开发者能够与 Claude Pair Programming。

但这些产品都默认一个基本交互模式:

  1. 用户定义任务;
  2. LLM 运行几秒或几分钟;
  3. 返回结果;
  4. 用户继续给出下一步指令。

Agent Teams 展示了一种完全不同的可能性:

让模型自主实现完整、复杂的项目。

这意味着,作为这些工具的使用者,我们可以开始设定更加野心勃勃的目标。

自主开发也带来真实风险

我们仍然处在非常早期阶段。

完全自主开发,也带来非常真实的风险。

当人类一直和 Claude 一起开发时:

  • 可以持续检查质量;
  • 可以实时发现错误。

但在自主系统中,很容易看到:

测试通过

然后就认为:

工作已经完成。

但现实中,往往并不是这样。

我过去从事渗透测试工作。

我的工作就是利用大型公司产品中的安全漏洞。

因此,一想到开发者可能直接部署:

他们自己从未亲自审查过的软件

我就感到真正担忧。

所以,这次实验一方面让我非常兴奋,另一方面也让我有些不安。

构建这个编译器,是我最近做过最有趣的项目之一。

但我完全没有预料到:

2026 年这么早的时候,这种事情就已经接近可行。

语言模型,以及我们围绕它们构建的 Scaffold,都在快速进步。

这意味着:

未来我们可以生成数量极其庞大的新代码。

我仍然认为:

积极应用最终会超过负面影响。

但我们确实正在进入一个新的世界。

而这个世界需要新的安全策略来应对。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。