Anthropic 研究員以 16 個 Claude 智能體協作編寫可編譯 Linux 6.9 的 C 編譯器
Building a C compiler with a team of parallel Claudes
Anthropic 研究員 Nicholas Carlini 讓 16 個 Claude 智能體協作,打造以 Rust 編寫、可編譯 Linux 6.9 的 C 編譯器。
文章拆解了如何以高品質測試、任務鎖定及 GCC 作為編譯器參照,讓多個 Claude 智能體分工處理大型編譯任務,呈現長時間自主協作的實作方法。
由我們 Safeguards 團隊的研究員 Nicholas Carlini 撰寫。
我一直在試驗一種監督語言模型的新方法,我們稱之為「Agent 團隊」。
透過 Agent 團隊,多個 Claude 實例可在沒有人工主動介入的情況下,並行處理同一個程式碼庫。這種方法大幅擴展了 LLM Agent 能夠完成的工作範圍。
為了對此進行壓力測試,我安排 16 個 Agent 從零開始編寫一個以 Rust 編寫的 C 編譯器,並使其能夠編譯 Linux 核心。歷經近 2,000 次 Claude Code 工作階段及 $20,000 的 API 費用後,Agent 團隊製作出一個 100,000 行的編譯器,可在 x86、ARM 和 RISC-V 上建置 Linux 6.9。
這個編譯器本身就是一項有趣的成果,但本文著重於我在設計長時間運作的自主 Agent 團隊執行框架方面的心得:如何編寫測試,讓 Agent 在沒有人監督下仍能按計劃工作;如何安排工作,讓多個 Agent 能並行推進;以及這種方法的侷限所在。
讓 Claude 長時間運作
現有的 Agent 執行架構(例如 Claude Code)要求操作者在線,並隨時準備與 Agent 協同工作。若要求模型解決一個漫長而複雜的問題,它或許能完成其中一部分,但最終會停下來,等待進一步輸入——例如問題、狀態更新或要求澄清。
為了促使 Claude 持續自主地推進工作,我建立了一個執行框架,讓 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
在 Agent 提示詞中,我會告訴 Claude 要解決甚麼問題,並要求它把問題拆解成小部分、追蹤目前的工作、找出下一步工作,並持續推進,直至完美。(至於最後一點,Claude 沒有選擇餘地。循環會無限運行——不過有一次,我確實看到 Claude 意外地 pkill -9 bash,結果令它自行終止,並結束循環。糟糕!)。
並行執行 Claude
單一 Agent 執行框架有兩個弱點,可透過並行執行多個實例來改善:
- 一個 Claude Code 工作階段一次只能做一件事。尤其當專案範圍擴大時,並行除錯多個問題效率高得多。
- 執行多個 Claude Agent 可實現專門分工。少數 Agent 負責解決當前問題,其他專門 Agent 則可負責(例如)維護文件、留意程式碼品質,或處理專門的子任務。
我的 Claude 並行執行方案非常精簡。系統會建立一個新的裸 Git 儲存庫,並為每個 Agent 啟動一個 Docker 容器,將儲存庫掛載到 /upstream。每個 Agent 會將本機副本複製到 /workspace,完成後再從自己的本機容器推送至上游。
為避免兩個 Agent 同時嘗試解決同一問題,執行框架採用簡單的同步演算法:
- Claude 會在 current_tasks/ 寫入文字檔,藉此對任務加上「鎖定」(例如,一個 Agent 可能會鎖定 current_tasks/parse_if_statement.txt,另一個則鎖定 current_tasks/codegen_function_definition.txt)。如果兩個 Agent 嘗試認領同一項任務,git 的同步機制會迫使第二個 Agent 改選其他任務。
- Claude 會處理任務,然後從上游拉取,合併其他 Agent 的變更、推送自己的變更,並解除鎖定。合併衝突時有發生,但 Claude 足夠聰明,能自行處理。
- 無限 Agent 生成循環會在全新的容器中啟動一個新的 Claude Code 工作階段,然後循環重複。
這是一個非常早期的研究原型。我尚未實作 Agent 之間的其他通訊方式,也沒有強制執行任何管理高層目標的流程。我沒有使用編排 Agent。
相反,我讓每個 Claude Agent 自行決定如何行動。在大多數情況下,Claude 會接手「下一個最顯而易見」的問題。遇到錯誤而卡住時,Claude 通常會持續記錄失敗的做法和剩餘任務。在專案的 git 儲存庫中,你可以查看歷史記錄,看看它如何為不同任務取得鎖定。
使用 Claude Agent 團隊編程的心得
基礎架構會讓 Claude 循環運行,但只有 Claude 知道如何取得進展時,這個循環才有用。我花了大部分心力設計 Claude 周邊的環境——測試、環境和回饋——讓它不需要我協助也能自行掌握方向。以下是我在協調多個 Claude 執行個體時,發現最有用的方法。
編寫極高質素的測試
Claude 會自主解決我交給它的任何問題。因此,任務驗證器必須近乎完美,否則 Claude 便會解決錯誤的問題。要改進測試框架,我需要尋找高質素的編譯器測試套件,為開源軟件套件編寫驗證器和建置指令碼,並留意 Claude 犯下的錯誤,再在識別出失效模式時設計新測試。
例如,在專案接近尾聲時,Claude 開始在每次實作新功能時頻繁破壞現有功能。為瞭解決這個問題,我建立了持續整合管道,並實施更嚴格的檢查,讓 Claude 能更好地測試自己的工作,確保新的提交不會破壞現有程式碼。
站在 Claude 的立場思考
我必須不斷提醒自己,這套測試框架是為 Claude 而非自己編寫的,這意味着我需要重新思考自己對測試應如何傳達結果的許多假設。
例如,每個 Agent 都會被放進一個全新的容器,沒有任何上下文,因此需要花不少時間瞭解情況,尤其是在大型專案中。在進行測試之前,為了讓 Claude 能自行掌握情況,我加入了指示,要求它維護詳盡的 READMEs 和進度檔案,並頻繁更新當前狀態。
我也考慮到語言模型本身的限制,並需要以這些限制為前提來設計。限制包括:
- 上下文視窗污染:測試框架不應輸出數千個無用位元組。最多隻應輸出數行,並將所有重要資訊記錄到檔案,讓 Claude 在需要時可以查找。日誌檔案應易於自動處理:如果有錯誤,Claude 應寫入 ERROR,並在同一行列出原因,讓 grep 可以找到。預先計算彙總統計數據也有幫助,這樣 Claude 就不必重新計算。
- 時間盲點:Claude 無法判斷時間;若任由它自行運作,便會樂於花上數小時執行測試,卻沒有任何進展。測試框架會偶爾輸出進度更新(以免污染上下文),並提供預設的
--fast選項,執行 1% 或 10% 的隨機抽樣。每個 Agent 的子樣本都是固定的,但不同 VM 之間的抽樣則是隨機的,因此 Claude 仍會涵蓋所有檔案,而每個 Agent 都能準確識別回歸問題。
讓平行處理變得容易
當有許多不同的測試失敗時,平行處理很簡單:每個 Agent 各自挑選一項失敗的測試來處理。測試套件的通過率達到 99% 後,每個 Agent 便各自負責讓不同的小型開源專案(例如 SQlite、Redis、libjpeg、MQuickJS、Lua)成功編譯。
但當 Agent 開始編譯 Linux 核心時,便遇上了瓶頸。與包含數百項獨立測試的測試套件不同,編譯 Linux 核心是一項龐大的整體任務。每個 Agent 都會遇上同一個錯誤、修好該錯誤,然後覆寫彼此的修改。即使有 16 個 Agent 同時執行也沒有幫助,因為它們都卡在解決同一項任務上。
解決方法是使用 GCC 作為線上已知正常的編譯器參照。我編寫了一個新的測試框架,隨機使用 GCC 編譯核心的大部分檔案,只用 Claude 的 C 編譯器編譯其餘檔案。如果核心能正常運作,問題就不在 Claude 負責編譯的那部分檔案中。如果核心無法正常運作,便可以再挑選其中一些檔案,以 GCC 重新編譯,進一步縮小問題範圍。這讓每個 Agent 可以平行處理,在不同檔案中修正不同錯誤,直到 Claude 的編譯器最終能夠編譯所有檔案。(這個方法奏效後,仍有必要使用 delta debugging 技術,找出哪些檔案組合在一起會出錯,但各自獨立時卻能正常運作。)
多種 Agent 角色
平行處理亦能讓工作專門化。LLM 編寫的程式碼經常會重新實作現有功能,因此我安排一個 Agent 合併它發現的重複程式碼。我讓另一個 Agent 負責提升編譯器本身的效能,並讓第三個 Agent 負責輸出高效的編譯程式碼。我請另一個 Agent 從 Rust 開發者的角度評論專案設計,並對專案作出結構性修改,以提升整體程式碼品質;另有一個 Agent 負責撰寫文件。
對 Agent 團隊的能力極限進行壓力測試
這個專案是為了作為能力基準測試而設計。我有興趣對 LLM 今天勉強能做到的事情進行壓力測試,從而協助我們為模型未來能穩定做到的事情作好準備。
我一直以 C 編譯器專案作為整個 Claude 4 模型系列的基準測試。跟以往的專案一樣,我先草擬了所需的目標:從零開始製作一個最佳化編譯器,沒有依賴項、與 GCC 相容、能夠編譯 Linux 核心,並且支援多個後端。我有指定設計的某些方面(例如,它應該具備 SSA IR,以支援多個最佳化階段),但沒有詳細説明如何實現。
之前的 Opus 4 模型勉強能製作出可運作的編譯器。Opus 4.5 首次跨過某個門檻,能製作出可運作並通過大型測試套件的編譯器,但仍然無法編譯任何真正的大型專案。我對 Opus 4.6 的目標是再次測試能力極限。
評估
在兩週內近 2,000 次 Claude Code 工作階段中,Opus 4.6 消耗了 20 億個輸入 token,並產生了 1.4 億個輸出 token,總成本略低於 $20,000。即使與最昂貴的 Claude Max 方案相比,這個項目的成本也極高。但這筆總額只是我親自製作這項成果所需成本的一小部分,更不用説由整個團隊製作了。
這是一項潔淨室實作(Claude 在整個開發過程中任何時候都無法存取互聯網);它只依賴 Rust 標準程式庫。這個有 100,000 行程式碼的編譯器,能在 x86、ARM 和 RISC-V 上編譯出可啟動的 Linux 6.9。它也能編譯 QEMU、FFmpeg、SQlite、postgres 和 redis;在大多數編譯器測試套件中,包括 GCC torture test suite,通過率達 99%。它還通過了開發人員的終極試金石:能夠編譯並執行 Doom。
不過,這個編譯器並非沒有侷限,包括:
- 它缺少讓 Linux 從實模式啟動所必需的 16 位元 x86 編譯器。為此,它會改為呼叫 GCC(x86_32 和 x86_64 編譯器則是它自己的)。
- 它沒有自己的組譯器和連結器;Claude 到最後才開始自動化這些部分,而且目前仍有一些錯誤。示範影片使用 GCC 的組譯器和連結器製作。
- 這個編譯器能成功編譯不少項目,但並非全部。它還未能直接取代真正的編譯器。
- 產生的程式碼效率不高。即使啟用了所有最佳化功能,它產生的程式碼效率仍不及 GCC 在所有最佳化功能均停用時所產生的程式碼。
- Rust 程式碼的質素尚算合理,但遠不及專業 Rust 程式設計師可能寫出的水平。
這個編譯器已幾乎達到 Opus 的能力極限。我曾努力嘗試修正上述幾項限制,但未能完全成功。新功能和錯誤修正經常會令現有功能失效。
其中一個特別棘手的例子是,Opus 無法實作讓系統以 16 位元實模式啟動所需的 16 位元 x86 程式碼產生器。雖然編譯器能透過 66/67 操作碼前綴輸出正確的 16 位元 x86 程式碼,但編譯後的輸出超過 60kb,遠遠超出 Linux 設定的 32k 程式碼限制。Claude 在這一步乾脆作弊,改為呼叫 GCC(這只適用於 x86。對於 ARM 或 RISC-V,Claude 的編譯器可以完全自行編譯。)
編譯器的原始碼已開放下載。下載後,閲讀程式碼,再用你最喜愛的 C 專案試用。我一直認為,要了解語言模型能做到甚麼,最佳方法就是把它們推至極限,再研究它們從哪裏開始失效。接下來幾天,我會繼續讓 Claude 加入新修改;如果你想跟進 Claude 繼續嘗試克服這些限制的過程,敬請留意。
展望未來
每一代語言模型都帶來與之協作的新方式。早期模型適用於 IDE 中的 Tab 補全。不久之後,模型已能根據函式的文件字串補全函式主體。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 眾多其他同事的協助和貢獻。
來源:Anthropic:Engineering · anthropic.com