在本文中,我將涵蓋程式碼代理和代理框架的整體設計:它們是什麼、如何運作,以及不同的組件在實踐中如何結合在一起。
我的《從零開始建構大型語言模型》和《從零開始建構大型推理模型》書籍的讀者經常詢問關於代理的問題,因此我認為撰寫一篇我可以引用的參考資料會很有用。
更廣泛地說,代理已成為一個重要主題,因為近期實用 LLM 系統的進展不僅在於更好的模型,還在於我們如何使用它們。
在許多實際應用中,周邊系統,例如工具使用、上下文管理和記憶,與模型本身的作用同等重要。
這也有助於解釋為什麼像 Claude Code 或 Codex 這樣的系統,其能力會比在純聊天介面中使用相同模型時感覺更強大。
在本文中,我將概述程式碼代理的六個主要建構塊。
你可能熟悉 Claude Code 或 Codex CLI,但為了鋪墊,它們本質上是代理式程式碼工具,將 LLM 包裹在一個應用程式層,即所謂的代理式框架(agentic harness),以提高程式碼任務的便利性和效能。
程式碼代理專為軟體工作而設計,其重要部分不僅是模型選擇,還包括周邊系統,例如儲存庫上下文、工具設計、提示快取穩定性、記憶和長會話連續性。
這種區別很重要,因為當我們談論 LLM 的程式碼能力時,人們經常將模型、推理行為和代理產品混為一談。
但在深入探討程式碼代理的細節之前,讓我簡要地提供更多關於這些更廣泛概念之間差異的背景資訊:LLM、推理模型和代理。
LLM 是核心的下一個 token 模型。
推理模型仍然是 LLM,但通常是經過訓練和/或提示,使其在推論時花費更多計算時間在中間推理、驗證或候選答案的搜尋上。
代理是其上層,可以理解為圍繞模型的控制迴路。
通常,給定一個目標,代理層(或框架)決定下一步檢查什麼、呼叫哪些工具、如何更新其狀態以及何時停止等。
粗略地說,我們可以這樣看待它們之間的關係:LLM 是引擎,推理模型是升級版的引擎(更強大,但使用成本更高),而代理框架則幫助我們更好地利用模型。
這個類比並不完美,因為我們也可以將傳統 LLM 和推理 LLM 作為獨立模型使用(在聊天 UI 或 Python 會話中),但我希望它能傳達主要觀點。
換句話說,代理是在環境中重複呼叫模型的系統。
所以,簡而言之,我們可以這樣總結:
推理模型:優化以輸出中間推理軌跡並進行自我驗證的 LLM
代理:使用模型、工具、記憶和環境回饋的迴路
代理框架:圍繞代理的軟體腳手架,負責管理上下文、工具使用、提示、狀態和控制流程
程式碼框架:代理框架的特例;即,專為軟體工程設計的任務特定框架,負責管理程式碼上下文、工具、執行和迭代回饋
如上所述,在代理和程式碼工具的上下文中,我們還有兩個流行術語:代理框架和(代理式)程式碼框架。
程式碼框架是模型周圍的軟體腳手架,有助於其有效編寫和編輯程式碼。
而代理框架則更廣泛,不限於程式碼(例如,考慮 OpenClaw)。
Codex 和 Claude Code 可以被視為程式碼框架。
總之,一個更好的 LLM 為推理模型(涉及額外的訓練)提供了更好的基礎,而框架則能從這個推理模型中獲得更多。
當然,LLM 和推理模型本身也能解決程式碼任務(無需框架),但程式碼工作僅部分涉及下一個 token 生成。
其中很大一部分是儲存庫導航、搜尋、函數查找、差異應用、測試執行、錯誤檢查以及將所有相關資訊保持在上下文中。
(程式設計師可能知道這是一項艱難的腦力勞動,這就是為什麼我們不喜歡在程式碼會話期間被打斷 :))。
這裡的重點是,一個好的程式碼框架可以使推理和非推理模型感覺比在純聊天框中更強大,因為它有助於上下文管理等。
如前一節所述,當我們說框架時,我們通常指的是模型周圍的軟體層,它組裝提示、暴露工具、追蹤檔案狀態、應用編輯、運行命令、管理權限、快取穩定前綴、儲存記憶等等。
如今,在使用 LLM 時,與直接提示模型或使用網頁聊天 UI(更接近「與上傳的檔案聊天」)相比,這一層塑造了大部分使用者體驗。
由於在我看來,如今 LLM 的標準版本功能非常相似(例如,GPT-5.4、Opus 4.6 和 GLM-5 的標準版本),因此框架通常是使一個 LLM 比另一個 LLM 工作得更好的區別因素。
這有點推測,但我懷疑,如果我們將一個最新、最能幹的開源 LLM(例如 GLM-5)放入類似的框架中,它很可能在 Codex 中與 GPT-5.4 或在 Claude Code 中與 Claude Opus 4.6 表現相當。
也就是說,一些特定於框架的後續訓練通常是有益的。
例如,OpenAI 歷史上曾維護過單獨的 GPT-5.3 和 GPT-5.3-Codex 變體。
在下一節中,我將更深入地探討細節,並使用我的 Mini Coding Agent 討論程式碼框架的核心組件:https://github.com/rasbt/mini-coding-agent 。
順帶一提,在本文中,為了簡化起見,我將「程式碼代理」和「程式碼框架」這兩個術語有些互換使用。
(嚴格來說,代理是模型驅動的決策迴路,而框架是提供上下文、工具和執行支援的周邊軟體腳手架。)
總之,以下是程式碼代理的六個主要組件。
你可以查看我這個極簡但功能齊全、從頭開始構建的 Mini Coding Agent 的原始碼(純 Python 實現),以獲取更具體的程式碼範例。
程式碼通過程式碼註釋標註了下面討論的六個組件:
這也許是最明顯的組件,但它也是最重要的組件之一。
當使用者說「修復測試」或「實現 xyz」時,模型應該知道它是否在 Git 儲存庫中,它在哪個分支上,哪些專案文件可能包含指令等等。
因為這些細節經常會改變或影響正確的操作。
例如,「修復測試」並不是一個獨立的指令。
如果代理看到 AGENTS.md 或專案 README,它可能會學到運行哪個測試命令等。
如果它知道儲存庫的根目錄和佈局,它就可以在正確的位置查找,而不是猜測。
此外,git 分支、狀態和提交可以提供更多關於當前正在進行的變更以及應關注重點的上下文。
重點是,程式碼代理在執行任何工作之前,會預先收集資訊(「穩定事實」作為工作區摘要),這樣它就不會在每次提示時都從零開始、沒有上下文。
一旦代理有了儲存庫視圖,下一個問題是如何將該資訊饋送給模型。
前面的圖表顯示了一個簡化的視圖(「組合提示:前綴 + 請求」),但在實踐中,每次使用者查詢時組合和重新處理工作區摘要相對浪費。
也就是說,程式碼會話是重複的,代理規則通常保持不變。
工具描述通常也保持不變。
甚至工作區摘要通常也(大部分)保持不變。
主要變化通常是最新的使用者請求、最近的對話記錄,以及可能的短期記憶。
「智能」運行時不會在每次輪次時將所有內容構建為一個巨大的、無差別的提示,如下圖所示。
與第一節的主要區別在於,第一節是關於收集儲存庫事實。
在這裡,我們現在有興趣將這些事實打包並高效地快取起來,以便重複的模型呼叫。
「穩定」的「穩定提示前綴」意味著其中包含的資訊變化不大。
它通常包含通用指令、工具描述和工作區摘要。
如果沒有重要內容發生變化,我們不想在每次互動時浪費計算資源從頭開始重建它。
其他組件更新更頻繁(通常是每個輪次)。
這包括短期記憶、最近的對話記錄和最新的使用者請求。
簡而言之,「穩定提示前綴」的快取方面就是一個智能運行時會嘗試重用該部分。
工具存取和工具使用是它開始感覺不像聊天而更像代理的地方。
一個純粹的模型可以在散文中建議命令,但程式碼框架中的 LLM 應該做一些更狹窄、更有用的事情,並且實際上能夠執行命令並檢索結果(而不是我們手動呼叫命令並將結果貼回聊天中)。
但是,與讓模型隨意編寫任意語法不同,框架通常提供一個預定義的允許工具列表,這些工具具有名稱、清晰的輸入和明確的邊界。
(當然,像 Python 的 subprocess.call 這樣的東西可以包含在其中,以便代理也可以執行任意廣泛的 shell 命令。)
工具使用流程如下圖所示。
為說明這一點,以下是使用我的 Mini Coding Agent 時通常會出現的範例。
(這不像 Claude Code 或 Codex 那樣漂亮,因為它非常簡潔,並且使用純 Python 而沒有任何外部依賴。)
在這裡,模型必須選擇一個框架能夠識別的動作,例如列出檔案、讀取檔案、搜尋、運行 shell 命令、寫入檔案等。
它還必須以框架可以檢查的形狀提供參數。
因此,當模型要求執行某項操作時,運行時可以停止並運行程式碼檢查,例如:
「請求的路徑是否在工作區內?」
只有在這些檢查通過後,才會實際執行任何操作。
雖然運行程式碼代理當然帶有某些風險,但框架檢查也提高了可靠性,因為模型不會執行完全任意的命令。
此外,除了拒絕格式錯誤的操作和批准門控之外,還可以通過檢查檔案路徑將檔案存取限制在儲存庫內。
在某種意義上,框架給予模型的自由度較小,但同時也提高了可用性。
上下文膨脹並非程式碼代理獨有的問題,而是 LLM 的普遍問題。
當然,如今 LLM 支持越來越長的上下文(我最近寫了關於使計算上更可行的注意力變體),但長上下文仍然很昂貴,並且還可能引入額外的噪音(如果存在大量不相關資訊)。
由於重複的檔案讀取、冗長的工具輸出、日誌等,程式碼代理在多輪聊天中比普通 LLM 更容易受到上下文膨脹的影響。
如果運行時以完整保真度保留所有這些內容,它將很快耗盡可用的上下文 token。
因此,一個好的程式碼框架通常非常複雜,能夠處理上下文膨脹,而不僅僅是像普通聊天 UI 那樣裁剪或總結資訊。
概念上,程式碼代理中的上下文壓縮可能如下圖所示。
具體來說,我們將進一步放大前一節圖 8 的剪輯(步驟 6)部分。
一個最小化的框架至少使用兩種壓縮策略來處理這個問題。
第一種是剪輯(clipping),它縮短長文件片段、大型工具輸出、記憶筆記和對話記錄條目。
換句話說,它防止任何單一文本片段僅僅因為冗長就佔用提示預算。
第二種策略是對話記錄縮減或摘要,它將完整的會話歷史(下一節將詳細介紹)轉換為更小的可提示摘要。
這裡的一個關鍵技巧是保持近期事件更豐富,因為它們更有可能對當前步驟很重要。
我們對較舊的事件進行更積極的壓縮,因為它們可能不太相關。
此外,我們還會對舊的檔案讀取進行去重,這樣模型就不會因為在會話早期被讀取多次而一遍又一遍地看到相同的檔案內容。
總體而言,我認為這是良好程式碼代理設計中被低估的、無聊的部分之一。
許多表面的「模型品質」實際上是上下文品質。
在實踐中,這裡涵蓋的所有 6 個核心概念都高度交織在一起,不同的章節和圖表以不同的焦點或縮放級別來涵蓋它們。
在前一節中,我們涵蓋了提示時間的歷史使用以及如何構建緊湊的對話記錄。
那裡的問題是:下一輪應該將多少過去的內容送回模型?
因此,重點是壓縮、剪輯、去重和時效性。
現在,這一節「結構化會話記憶」是關於歷史的儲存時間結構。
這裡的問題是:代理會隨著時間保留什麼作為永久記錄?
因此,重點是運行時將完整的對話記錄作為持久狀態保留,同時還有一個更輕量的記憶層,它更小,並且被修改和壓縮,而不是僅僅追加。
總結來說,程式碼代理將狀態分為(至少)兩層:
工作記憶:代理明確保留的小型、精煉狀態
完整對話記錄:這涵蓋了所有使用者請求、工具輸出和 LLM 回應
上圖說明了兩個主要的會話檔案:完整對話記錄和工作記憶,它們通常作為 JSON 檔案儲存在磁碟上。
如前所述,完整對話記錄儲存了整個歷史記錄,如果我們關閉代理,它可以恢復。
工作記憶更像是一個精煉版本,包含當前最重要的資訊,這與緊湊的對話記錄有些關聯。
但是,緊湊的對話記錄和工作記憶有略微不同的職責。
緊湊的對話記錄用於提示重建。
它的職責是為模型提供近期歷史的壓縮視圖,以便它可以在沒有每個輪次都看到完整對話記錄的情況下繼續對話。
工作記憶更用於任務連續性。
它的職責是保留一個小型的、明確維護的、跨輪次重要的資訊摘要,例如當前任務、重要檔案和近期筆記。
按照上圖的步驟 4,最新的使用者請求以及 LLM 回應和工具輸出將在下一輪中記錄為「新事件」,同時記錄在完整對話記錄和工作記憶中,圖中未顯示以減少混亂。
一旦代理擁有工具和狀態,下一個有用的功能之一就是委派。
原因是它允許我們通過子代理將某些工作並行化為子任務,從而加快主任務。
例如,主代理可能正在處理一項任務,但仍需要一個側面的答案,例如,哪個檔案定義了一個符號,配置說明了什麼,或者為什麼一個測試失敗。
將其拆分為一個有界子任務而不是強迫一個迴路同時處理所有工作線程很有用。
(在我的 mini coding agent 中,實現更簡單,子代理仍然同步運行,但基本思想是相同的。)
只有當子代理繼承了足夠的上下文來執行實際工作時,它才有用。
但如果我們不限制它,我們就會有多個代理重複工作、觸碰相同的檔案,或者產生更多子代理,等等。
因此,棘手的設計問題不僅是如何生成子代理,還有如何綁定一個子代理。
這裡的技巧是,子代理繼承了足夠的上下文使其有用,同時也受到限制(例如,只讀和遞歸深度受限)。
Claude Code 長期以來支持子代理,而 Codex 最近也添加了它們。
Codex 通常不會強制子代理進入只讀模式。
相反,它們通常繼承主代理沙箱和批准設置的大部分內容。
因此,邊界更多地是關於任務範圍、上下文和深度。
上面的部分試圖涵蓋程式碼代理的主要組件。
如前所述,它們在實現上或多或少地深度交織在一起。
然而,我希望逐一介紹它們有助於對程式碼框架的工作方式形成整體心智模型,以及為什麼它們可以使 LLM 比簡單的多輪聊天更有用。
如果你有興趣看到這些在簡潔、極簡的 Python 程式碼中實現,你可能會喜歡我的 Mini Coding Agent 。
OpenClaw 可能是一個有趣的比較,但它並非完全是同一類型的系統。
OpenClaw 更像是一個本地的、通用的代理平台,也可以編寫程式碼,而不是一個專門的(終端)程式碼助手。
它與程式碼框架仍有幾個重疊之處:
它在工作區中使用提示和指令檔案,例如 AGENTS.md、SOUL.md 和 TOOLS.md
它維護 JSONL 會話檔案,並包含對話記錄壓縮和會話管理
它可以生成輔助會話和子代理
然而,如前所述,重點不同。
程式碼代理針對在儲存庫中工作並要求程式碼助手有效檢查檔案、編輯程式碼和運行本地工具的人進行了優化。
OpenClaw 更針對跨聊天、頻道和工作區運行許多長期存在的本地代理進行了優化,其中程式碼是多個工作負載中的一個重要工作負載。
我很高興地宣布,我已經完成了《從零開始建構推理模型》的寫作,所有章節都已進入早期預覽。
出版商目前正在處理排版,預計將於今年夏天上市。
這可能是我迄今為止最雄心勃勃的書。
我花了約 1.5 年的時間寫作,並進行了大量的實驗。
這也可能是我在時間、精力和潤色方面投入最多的一本書,我希望你會喜歡。
關於 LLM 中的「推理」,有很多討論,我認為理解它在 LLM 上下文中真正含義的最佳方法是從頭開始實現一個!
Manning(完整書籍早期預覽,預最終排版,528 頁)
你是否閱讀了 Claude Code 的原始碼來寫這篇文章?時機非常吻合。
這裡與交易系統人們試圖構建的系統有很強的相似之處。
每個人都痴迷於模型——信號、指標、「優勢」。
但在實踐中,圍繞它的框架才是決定它是否真正起作用的關鍵。
一個好的交易者已經憑直覺知道了這一點。
想法本身是不夠的。
你需要結構——執行規則、過去錯誤的記憶、行為約束、過濾噪音並只關注重要事項的方法。
沒有這些,即使是強大的信號也會被上下文、猶豫或過度反應所稀釋。
你這裡描述的基本上是同一件事的正式化。
模型是直覺。
框架是紀律。
而大部分實際表現來自這兩者隨時間的互動。
這就是為什麼兩個人可以看著相同的市場、相同的水平、相同的設置——而一個人提取了一致性,另一個人卻一團糟。
區別不在於他們看到什麼。
在於他們圍繞所見所聞建立的系統。