這篇文章詳細紀錄了 Anthropic 如何使用並行代理團隊來構建一個功能完備的 C 編譯器。以下是該部落格文章的全文完整繁體中文翻譯:
使用並行 Claude 代理團隊構建 C 編譯器
發佈日期:2026 年 2 月 5 日 作者:Nicholas Carlini(Anthropic 安全團隊研究員)
我們指派了 Opus 4.6 模型,利用「代理團隊(agent teams)」構建了一個 C 編譯器,然後(基本上)就放手不管了。以下是這次實驗告訴我們關於自主軟體開發未來的啟示。
對代理團隊進行極限壓力測試
我一直在實驗一種監管語言模型的新方法,我們稱之為「代理團隊」。在代理團隊中,多個 Claude 實例在一個共享的代碼庫上並行工作,無需人類主動干預。這種方法極大擴展了 LLM 代理能達到的目標範圍。
為了進行壓力測試,我指派了 16 個代理,要求它們從零開始用 Rust 撰寫一個能編譯 Linux 核心(Kernel)的 C 編譯器。經過將近 2,000 次 Claude Code 會話和約 2 萬美元的 API 成本,這個代理團隊產出了一個擁有 10 萬行代碼的編譯器,能夠在 x86、ARM 和 RISC-V 上構建 Linux 6.9。
編譯器本身是一個有趣的成品,但我這裡的重點在於我從中學到的經驗:如何為長期運行的自主代理團隊設計「腳手架(harnesses)」、如何編寫測試以確保代理在無人監管的情況下不偏離軌道、如何結構化工作以便多個代理能並行推進,以及這種方法的極限在哪裡。
實現長期運行的 Claude
現有的代理架構(如 Claude Code)通常需要一個操作者在線協作。如果你要求解決一個長期且複雜的問題,模型可能會解決一部分,但最終會停止並等待輸入——例如提問、狀態更新或澄清請求。
為了實現持續的自主進展,我構建了一個將 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
並行運行多個實例可以解決單個代理架構的兩個弱點:
- 效率: 一個 Claude Code 會話一次只能做一件事。隨著項目規模擴大,並行調試多個問題效率更高。
- 專門化: 當一些代理負責解決核心問題時,其他專門的代理可以負責維護文檔、監控代碼質量或解決特定的子任務。
我的並行實現非常簡單:創建一個空的 git 倉庫,為每個代理啟動一個掛載了該倉庫的 Docker 容器。每個代理克隆一份本地副本,完成工作後再推送到遠端。
為了防止兩個代理同時解決同一個問題,腳手架使用了簡單的同步算法:
- 鎖定機制: Claude 通過在
current_tasks/目錄寫入文本文件來「鎖定」任務(例如:一個代理鎖定parse_if_statement.txt,另一個鎖定codegen_function_definition.txt)。如果兩個代理試圖搶佔同一任務,git 的同步機制會強制第二個代理選擇其他任務。 - 合併衝突: Claude 工作完成後,會拉取(pull)遠端代碼、合併其他代理的更改、推送(push)自己的更改並刪除鎖定。雖然合併衝突頻繁發生,但 Claude 足夠聰明,能自行解決。
- 循環重複: 無限代理生成循環會在新的容器中啟動新的 Claude Code 會話,循環往復。
這是一個非常早期的研究原型。我尚未實現代理間的其他溝通方式,也沒有強制執行高層目標的管理流程。我沒有使用編排代理(orchestration agent)。
相反,我讓每個 Claude 代理自行決定如何行動。大多數情況下,它們會挑選「下一個最明顯」的問題。陷入僵局時,Claude 通常會維護一份記錄失敗嘗試和剩餘任務的文檔。在項目的 git 歷史中,你可以看到它不斷鎖定各種任務的過程。
與 Claude 代理團隊協作的教訓
腳手架讓 Claude 循環運行,但只有在 Claude 知道如何取得進展時才有用。我的大部分精力花在設計 Claude 周圍的環境——測試、環境、反饋——讓它在沒有我的情況下也能自我定位。以下是我發現最有用的方法:
1. 編寫極高質量的測試
Claude 會自主解決我給它的問題。因此,任務驗證器必須近乎完美,否則 Claude 會解決錯誤的問題。改進測試腳手架需要尋找高質量的編譯器測試套件、編寫驗證器和開源軟件包的構建腳本,並觀察 Claude 犯的錯誤,從而設計新測試來應對這些失敗模式。
例如,在項目後期,Claude 每次實現新功能時都會頻繁破壞現有功能。為了解決這個問題,我建立了一個持續集成(CI)流水線,實施更嚴格的強制措施,確保新的提交不會破壞舊代碼。
2. 站在 Claude 的角度思考
我必須不斷提醒自己,這個測試腳手架是為 Claude 寫的,而不是為我自己。這意味著需要重新思考關於測試反饋的假設。
例如,每個代理進入的是一個全新的容器,沒有背景知識,會花大量時間定位自己。為了幫助 Claude,我在指令中要求它維護詳盡的 README 和進度文件,並頻繁更新當前狀態。
我還考慮到語言模型的內在局限性:
- 上下文污染: 測試腳手架不應打印數千個無用的字節。最多只需打印幾行,並將詳細信息記錄到文件中。
- 日誌易讀性: 錯誤日誌應易於自動處理。如果有錯誤,Claude 應該寫下
ERROR並在同一行註明原因,以便grep查找。 - 時間盲性: Claude 無法判斷時間,如果不管它,它可能會花數小時運行測試。腳手架會不頻繁地打印增量進度,並包含一個
--fast選項,僅運行 1% 或 10% 的隨機樣本。
3. 讓並行化變得容易
當有許多獨立的測試失敗時,並行化很簡單:每個代理選一個失敗的測試。但在編譯 Linux 核心時,代理們卡住了。編譯核心是一個巨大的單一任務,每個代理都會遇到同一個 Bug,修復它,然後覆蓋彼此的更改。
解決方案是引入 GCC 作為「已知正確的編譯器預言機(oracle)」。我寫了一個新的測試腳手架,隨機地將核心的大部分文件交給 GCC 編譯,只留下少數文件交給 Claude 的編譯器。如果內核崩潰,說明問題出在 Claude 編譯的文件中。這讓每個代理能並行地修復不同文件中的不同 Bug。
4. 多代理角色分工
並行化也實現了專門化。我指派一個代理負責合併重複代碼,另一個負責優化編譯器性能,第三個負責讓生成的代碼更高效。我還要求一個代理以 Rust 開發者的角度批評設計並改進代碼質量,另一個則專注於文檔。
評估成果
- 規模: 10 萬行代碼,完全依賴 Rust 標準庫。
- 成本: 兩週內消耗 20 億輸入 Token,1.4 億輸出 Token,API 成本近 2 萬美元。這比最貴的訂閱計劃貴得多,但遠低於雇用人類團隊的成本。
- 能力: 成功構建了可引導的 Linux 6.9、QEMU、FFmpeg、SQLite、PostgreSQL、Redis。在 GCC 酷刑測試中達到 99% 通過率。它還通過了終極測試:編譯並運行《毀滅戰士》(Doom)。
侷限性:
- 缺乏 16 位代碼生成: 它無法處理 Linux 進入保護模式所需的 16 位實模式代碼,這部分目前調用 GCC(但在 ARM 和 RISC-V 上可以完全獨立編譯)。
- 匯編器與鏈接器: 這些是最後自動化的部分,仍有 Bug。演示視頻使用了 GCC 的匯編器和鏈接器。
- 效率: 生成的代碼效率不如 GCC。即使開啟所有優化,性能也低於 GCC 在關閉優化時的表現。
- 代碼質量: Rust 代碼質量「合理」,但不及專家水平。
展望未來
代理團隊展示了自主實施整個複雜項目的可能性。這讓我們作為工具的使用者能擁有更宏大的目標。
我們仍處於早期階段,完全自主開發存在真實風險。當人類與 Claude 協作時,可以即時發現錯誤。對於自主系統,很容易看到測試通過就以為大功告成,但事實往往並非如此。作為一名前滲透測試員,想到程序員部署從未經過人工驗證的軟體,我感到擔憂。
雖然這個實驗令我興奮,但也讓我感到不安。我沒想到在 2026 年初這就已經成為可能。我們正在進入一個新世界,這將需要新的策略來安全導航。
原文出處
留言
張貼留言