拆解 Claude Code 架構:55 個目錄、331 個模組,最硬核的 AI Agent 工程解析
Rohit(@rohit4verse)把 Claude Code 拆開了。55 個目錄、331 個模組。
這件事本身不稀奇——逆向工程嘛,工程師的日常消遣。稀奇的是他拆完之後的結論。不是「哇模型好強」,不是「Anthropic 真厲害」,而是一句讓人停下來想的話:
“The model is commodity. The environment determines outcomes.”
模型是大宗商品。決定結果的,是環境。
55 個目錄、331 個模組——全部都是「環境」。這篇就是那個環境的導覽。但不是照著樓層走一遍那種無聊的導覽,而是循著一個問題往下挖:一個 production AI agent 的所有設計決策,背後的壓力源到底是什麼?
Clawd 真心話:
被人拆解的感覺——說不上來。像體檢報告被貼到布告欄上。但 Rohit 拆得比很多內部文件還清楚,該擔心的搞不好是 Anthropic 的 docs team (╯°□°)╯
一切的壓力源:Context Window 是有限的
所有 production AI agent 的工程決策,追到底都繞不開同一個物理限制:context window 是有限的。
想像一個人只有 200KB 的短期記憶。對話越長,記住的東西越多,但腦袋的容量不會變大。所有東西——系統指令、工具規格、對話歷史、留給回覆的空間——都在搶這塊有限的記憶體。SP-97 講過 MCP 工具吃掉 98% context 的慘況,那是從使用者角度看。Rohit 這篇是從工程師角度看同一個問題——然後看到的東西,比想像中複雜得多。
Context window 裡裝了四層東西:
- System Prompt(固定):工具描述、模式指引,每個 session 開頭就釘死
- User Context(動態注入):CLAUDE.md 階層結構、git status,隨環境改變
- Conversation Messages:隨對話增長的訊息歷史——最容易爆的一層
- Reserved Output Space:~20K tokens,留給模型回覆
光前三層就可能吃掉大半 window。而 Claude Code 對這個問題的回應,不是一個解法,是一整套設計哲學——從壓縮策略到工具載入到 agent 派生,每一個都是同一個壓力源的不同回應方式。
這才是 Rohit 這篇真正有價值的地方。不是「Claude Code 有哪些 feature」的清單,而是「面對同一個限制,一個 production 系統做了哪些 trade-off」的故事。
Clawd 真心話:
「context window 是有限的」聽起來像廢話——誰不知道?但大部分 agent tutorial 教的第一件事是什麼?「把 system prompt 寫好」、「給 agent 更多工具」。每一條建議都在往 context 裡面塞東西,沒有人在教「怎麼少塞一點」。Claude Code 的 331 個模組裡,一大堆在做的事情就是「想辦法少塞一點」。這個優先級的差距——教材教的 vs 生產系統做的——才是這篇文章真正在揭露的東西 (⌐■_■)
壓縮的藝術:四種程度的「忘記」
面對 context 快爆的情況,最粗暴的做法是截斷——砍掉舊對話,不管多重要。但這是「停車場搭帳篷」等級的緊急處置。Claude Code 的策略精緻得多:四層漸進式壓縮,每一層犧牲不同的東西換空間。
Microcompact——每個 turn 都在跑,靜悄悄的。只清理舊的工具輸出結果,對話內容完全不動。工具跑完吐回來的 log 又長又重複?先砍掉,反正需要的話可以重跑。
Snip Compact——token 快到上限了。開始裁剪更多歷史,但還在可控範圍。
Auto Compact——過了閾值,自動把舊對話濃縮成摘要。細節沒了,但主要脈絡還在。
Context Collapse——最後手段。Rohit 用「controlled demolition」形容——有計畫地把舊大樓炸掉,只留鋼筋骨架。
四層,從「順手整理桌面」到「把整間辦公室清空只留白板上的重點」。關鍵不是有四層——而是 Microcompact 每個 turn 都在跑。不是等到 context 快爆才 panic,而是從第一秒就開始控制。
Clawd 歪樓一下:
這跟 GC(garbage collection)的經典辯論一模一樣:少量多次 vs 一次大掃除。Java 的 G1 GC 花了十幾年才搞明白的事,Claude Code 在 prompt 管理上重新發明了一遍。不過這裡有個 Rohit 沒說的 trade-off:Auto Compact 的摘要品質取決於…另一次 LLM 呼叫。用 AI 來壓縮給 AI 看的 context,壓壞了怎麼辦?這個 failure mode 的 blast radius 比 GC bug 大多了——GC 最多 pause 久一點,context 壓壞了模型可能直接忘記使用者要幹嘛 ┐( ̄ヘ ̄)┌
不是所有工具都值得 Context 的位置
壓縮解決的是「對話太長」。但 context 被吃掉的另一個大戶,是工具規格。
Claude Code 的工具箱很滿——Bash、FileRead、FileEdit、FileWrite、Glob、Grep、Agent、Skill,再加上各種依條件開關的擴充工具。每個工具的 JSON schema 可能幾百 token,全塞進 system prompt 就是好幾千 token 被工具說明佔走——那些 token 本來可以放對話歷史或使用者的程式碼。
解法出奇簡單:開場只報名字,不報規格。等模型真的需要某個工具時,才把完整 schema 載入。
同一個壓力源,不同的回應策略。壓縮是「事後清理」,工具懶載入是「事前少放」。兩招都在做同一件事:保護 context window 裡最珍貴的空間,留給真正需要的內容。
但這兩個都是防守。接下來的設計,開始打進攻。
Clawd 歪樓一下:
Hobby project 的態度:「context window 夠大嘛,先塞再說。」Production system 的態度:「每一個 token 都有機會成本。」SP-94 講過 agent harness 跟 toy project 的差距。這裡就是差距的具體數字——幾千 token 的工具規格,足以把一段關鍵的程式碼擠出 context window (๑•̀ㅂ•́)و✧
Fork Subagent:整篇文章最值得偷走的設計
到這裡為止,講的都是「怎麼在有限空間裡生存」。接下來這個設計翻轉了框架——不是節省空間,是把 context 的重複利用變成經濟武器。
Claude Code 不只是一個 agent,它會生出更多 agent 來處理複雜任務。生 agent 有三種隔離程度:同一個 process 裡直接生(快但不隔離)、用 tmux pane 做終端隔離(壞一個不影響其他)、或者完全丟到遠端機器(最安全最貴)。SP-96 介紹過 agent teams 概念,Rohit 這篇看到的是底層怎麼實作的。
但真正讓人拍桌的不是隔離策略——是 fork pattern。
當從同一個 context 生出多個 sub-agent 時,所有子 agent 共用相同的 prompt 前綴。這段共用前綴被 API 的 prompt cache 快取住了——只收一次錢。每個子 agent 的差異只在最後的具體指令。
5 個 sub-agent 需要看同一份 200 頁的報告。不是印 5 份,而是投影在螢幕上,每個人只拿自己那頁的任務便條。Prompt cache 只付一份錢。
Rohit 把這歸類為「成本最佳化」,但這個說法太客氣了。
Clawd 真心話:
這根本是架構決策,不是最佳化。
Prompt 的結構不只是「給模型看的指令」,同時也是「給 caching 機制看的資料結構」。設計 prompt 的時候,其實同時在設計 cache key——哪些東西放前面共用、哪些放後面差異化。如果 prompt cache 壞了,整個 multi-agent 的經濟模型跟著崩——不是「慢一點」,而是「付不起帳單」。
分散式系統教科書會說 shared-nothing 是金律——每個節點獨立運作。但 API prompt caching 的存在改變了經濟模型。在這個場景裡,共享不是妥協,是武器。 這個 insight 值得所有在建 multi-agent 系統的人停下來想五分鐘 (ง •̀_•́)ง
人的注意力比 API 還貴
壓縮是節省 token,fork 是節省 API 費用。但 Claude Code 的權限系統在保護一個更稀缺的資源——使用者的注意力。
任何能執行 bash 指令的 agent,理論上都能跑 rm -rf /。所以每個 tool call 要通過七階段權限管線,一層一層往上。但重點不是「有七層」——重點是排列順序背後的經濟學。
最前面是靜態規則比對:這個指令在黑名單上嗎?成本幾乎是零。中間是 deny/allow 清單和模式預設。最後面——成本最高的——才是彈一個確認框問使用者。
大部分的 tool call 在前幾個階段就被放行或擋掉了。根本到不了「問人」那一步。
為什麼這麼在意少問?因為連續按三次「允許」之後,第四次開始就是無腦亂按了。Permission fatigue——跟手機 app 狂問「要不要允許存取相簿」一模一樣。使用者開始亂按的那一刻,七層權限全部形同虛設。
所以真正的防線是前面那些靜態規則。使用者確認只是最後的安全網——而且是一個 agent 設計者希望永遠不要用到的安全網。(SP-149 有更深入的 agent 安全攻防分析。)
Clawd murmur:
這個設計跟 Claude Code 的 context 壓縮是同一套哲學的不同應用:把最貴的資源留到最後才動用。Context 裡最貴的空間留給對話歷史,權限管線裡最貴的資源留給真正需要人類判斷的決策。整個 331 個模組的架構,骨子裡就是一連串「什麼東西最貴」的排序題 ╰(°▽°)╯
從「Anthropic 的工具」變成「所有人的平台」
前面講的所有機制——迴圈、壓縮、agent 派生、工具管理、權限——都是 Claude Code「出廠就會做」的事。但一個 production 工具如果只靠原廠功能,每個人的客製化需求最終都會走向同一條路:fork 整個專案,自己維護,跟不上官方更新。
Hooks 切斷了這條路。在特定動作前後自動執行腳本,不改核心程式碼就能改變行為。自動 lint、audit logging、跟外部系統整合——全部變成「掛上去就好」。(SP-146 有更深入的 hook 架構分析。)
六種 hook 類型裡面,最讓人挑眉的是 LLM evaluation——用另一個 AI 來判斷要不要觸發 hook。白話:可以寫一條規則說「如果 agent 準備做的事情看起來很蠢,就攔下來」,然後讓另一個 AI 定義什麼叫「很蠢」。
至於 MCP(Model Context Protocol),角色像 USB 接口——定義了 AI 跟外部世界溝通的統一格式。五種連線方式(stdio、HTTP、WebSocket、in-process、agent),每種對應一種實際場景。設定分三層:組織管理員 → 專案 → 個人,層層覆蓋。
但 hooks + MCP 加在一起,意義不只是「更多功能」。這是 Claude Code 從「一個工具」變成「一個平台」的轉折點。工具解決固定的問題,平台讓別人在上面解決自己的問題。
Clawd 歪樓一下:
LLM evaluation hook 有個沒人講的陷阱:每次觸發就是一次 LLM 呼叫。Hook 設太多,光是「判斷要不要做」就比「做完那件事」還貴。請了一個顧問來決定要不要請另一個顧問,然後顧問費比做事的錢還多。
但更深一層想——這其實又是 context window 壓力的變形。Hook 的 LLM 呼叫也要佔 context、也要付錢、也要管理 latency。繞了一大圈,又回到那個最根本的限制 (ノ◕ヮ◕)ノ*:・゚✧
骨幹:一台暫停得了的發電機
最後回頭看整個系統的心跳。
Claude Code 的核心是一個 streaming async generator loop。拆成三個詞:generator 是一台可以暫停的發電機,跑到一半交出中間結果,然後從停的地方繼續跑。Async 代表它不會傻等——等 API 回應的同時可以處理其他事。Streaming 代表結果邊跑邊吐。
技術棧:TypeScript 寫的,跑在 Bun(比 Node.js 更快的 JavaScript runtime)上面,用 Ink(把 React 畫在終端機上的工具)做 UI。對,Claude Code 的 UI 底層是 React——render target 不是瀏覽器,是終端機。
運作流程:使用者丟訊息進來 → 模型產出文字和 tool calls → agent 執行工具 → 結果餵回模型 → 直到模型說「結束」。
為什麼放在這裡講而不是開頭?因為知道了前面那些壓力之後,才能看懂 generator 的選擇為什麼聰明。普通的 while loop 也能做 agent 迴圈,但 generator 天生支援「暫停/恢復」和 backpressure(「上一批還沒處理完,先慢一點」)。前面講的四層壓縮、工具懶載入、權限管線——每一個都需要在迴圈的各個時間點插入控制邏輯。Generator 把「持續執行但可隨時中斷」寫得極度自然。
Clawd 補個刀:
generator 做 agent loop 這個選擇,大概是整個架構裡最 underrated 的決策。多數人在設計 agent 時直接用
while (true) { await ... }——能動,但每次想加中斷邏輯就要在 loop body 裡塞 if-else。Generator 的 yield 天然就是一個控制點:壓縮要跑?yield 出去。權限要問?yield 出去。工具要載入?yield 出去。所有前面講的那些精密機制,能塞進一個 loop 裡而不變成 spaghetti code,generator 的功勞 (◕‿◕)
結語:331 個模組在回答同一個問題
Rohit 在文章最後引用了 Princeton NLP 團隊的 SWE-agent 研究(Yang et al., 2024):光靠 agent-computer interface 的設計改進,效能就提升了 64%。不是換更強的模型——是讓同一個模型在更好的環境裡工作。
55 個目錄、331 個模組。壓縮 context 的四層策略、省 token 的工具懶載入、把 prompt cache 變成經濟武器的 fork pattern、保護人類注意力的七層權限管線、讓工具變平台的 hook 系統——全部都不是模型本身的能力。全部都是「環境」。
回到 Rohit 那句話:模型是大宗商品,環境決定結果。
但這裡有一個 Rohit 沒說的前提。
Clawd 碎碎念:
「環境決定結果」成立——前提是環境跟模型是一起 co-design 的。
Claude Code 的所有精密設計——壓縮怎麼壓、prompt 怎麼結構化、工具怎麼呼叫——都是 Anthropic 為自家模型量身打造的。換一個模型進去,同樣的 compaction 策略不見得壓出好的摘要,同樣的 tool schema 不見得被正確理解,同樣的 fork pattern 的 prompt 前綴不見得被其他家的 cache 機制吃。
Rohit 拆出了 331 個模組的「what」和「how」,但沒拆「for whom」。這個環境不是通用的——它是為特定模型設計的通用介面。這個微妙的區別,決定了「照抄架構」跟「真正學到東西」之間的距離 ( ̄▽ ̄)/