Claude Code 為何如此牛逼 (以及如何在你的 Agent 中復刻這種魔力)!?
Claude Code 是我迄今為止用過的最令人愉悅的 AI Agent/工作流。它不僅讓針對性編輯或憑感覺寫點一次性工具這類事不再那么煩人,使用 Claude Code 本身就讓我感到快樂。它有足夠的自主性能做些有趣的事,同時又不像其他一些工具那樣會帶來令人不適的失控感。當然,大部分繁重工作是由新的 Claude 4 模型完成的 (特別是其交錯思維能力)。但我發現,即使使用相同的底層模型,Claude Code 在客觀上也比 Cursor 或 Github Copilot 的 Agent 更順心!究竟是什么讓它如此牛逼?如果你正在點頭認同,那么我將嘗試給出一些答案。
注意:這篇博文不打算深入剖析 Claude Code 的架構 (網上已有不少好文章)。這篇博文旨在成為構建優秀 LLM (Large Language Model, 大語言模型) Agent 的指南,基于我過去幾個月使用和琢磨 Claude Code 的個人經驗 (以及我們攔截和分析的所有日志)。
你可以清楚地看到 Claude Code 的不同更新。
Claude Code (CC) 的使用體驗之所以出色,因為它就是好用。CC 的設計基于對 LLM 擅長什么和不擅長什么的深刻理解。它的提示和工具彌補了模型的不足,并幫助其在核心優勢區大放異彩。其控制循環非常簡單易懂,調試起來也輕而易舉。
我們 MinusX 在 CC 一發布就開始使用了。為了探究其內部機制,Sreejith 寫了一個日志記錄器,可以攔截并記錄每一個網絡請求。以下分析源于我過去幾個月的大量使用。本文試圖回答這個問題——“是什么讓 Claude Code 如此優秀,以及你如何在自己的基于聊天的 LLM Agent 中提供類似的體驗?” 我們已經將其中大部分理念融入了 MinusX,也很期待看到你也這樣做!
Edit (編輯) 是最常用的工具,其次是 Read (讀取) 和 ToDoWrite (寫入待辦事項)
如何構建一個類 Claude Code 的 Agent:內容摘要 (TL;DR)
如果說本文只有一個核心要點,那就是——保持簡單,傻瓜 (Keep Things Simple, Dummy)。LLM 的調試和評估已經夠難了。你引入的任何額外復雜性 (多 Agent、Agent 任務交接或復雜的 RAG (Retrieval-Augmented Generation, 檢索增強生成) 搜索算法) 只會使調試難度增加 10 倍。如果這樣一個脆弱的系統僥幸能跑起來,你日后也會因害怕對其進行大刀闊斧的改動而束手束腳。所以,把所有東西都放在一個文件里,避免過度的樣板腳手架,并且至少徹底重構幾次 :)
以下是從 Claude Code 中學到的、可以在你自己的系統中實現的主要經驗。
1. 控制循環
1.1 保持一個主循環 (最多一個分支) 和一個消息歷史
1.2 在各種事情上使用更小的模型。是. 的。無. 時. 無. 刻。
2. 提示 (Prompts)
2.1 使用 claude.md 模式來協作和記憶用戶偏好
2.2 使用特殊的 XML 標簽、Markdown 和大量示例
3. 工具 (Tools)
3.1 LLM 搜索 >>> 基于 RAG 的搜索
3.2 如何設計好工具?(高級工具 vs 低級工具)
3.3 讓你的 Agent 管理自己的待辦事項列表
4. 可控性 (Steerability)
4.1 語氣和風格
4.2 不幸的是,“請注意,這很重要” 仍然是當前最先進的技術
4.3 寫出算法,并附上啟發式規則和示例
Claude Code 在每個節點都選擇了架構上的簡潔性——一個主循環、簡單的搜索、簡單的待辦事項列表等。克制過度設計的沖動,為模型構建良好的約束框架,然后讓它自由發揮!這難道又是端到端自動駕駛的重演?慘痛的教訓 (The Bitter Lesson) 又應驗了?
1. 控制循環設計
1.1 保持一個主循環
可調試性 >>> 手動精調的、由多 Agent、LangChain-Graph-Node 拼湊起來的復雜混合體。
盡管多 Agent 系統風靡一時,Claude Code 卻只有一個主線程。它會周期性地使用幾種不同類型的提示來總結 git 歷史、將消息歷史合并成一條消息或創造一些有趣的用戶體驗元素。但除此之外,它只維護一個扁平的消息列表。它處理層級任務的一個有趣方式是,將自己作為子 Agent 派生出來,但這個子 Agent 不具備再派生更多子 Agent 的能力。最多只有一個分支,其結果會作為“工具響應”添加到主消息歷史中。
如果問題足夠簡單,主循環通過迭代式工具調用就能處理。但如果有一個或多個復雜任務,主 Agent 會創建自己的克隆體。這種“最多一個分支”的設計與待辦事項列表相結合,確保了 Agent 既能將問題分解為子問題,又能始終關注最終期望的結果。
我非常懷疑你的應用是否需要一個多 Agent 系統。每增加一層抽象,你都會讓系統更難調試,更重要的是,你會偏離通用模型能力提升的軌道。
1.2 在*所有事情*上使用更小的模型
CC 發出的所有重要 LLM 調用中,超過 50% 是針對 claude-3-5-haiku 的。它被用來讀取大文件、解析網頁、處理 git 歷史和總結長對話。它還被用來生成那個單詞的處理標簽——字面上是為每一次按鍵生成的!這些較小的模型比標準模型 (Sonnet 4, GPT-4.1) 便宜 70-80%。大膽地使用它們吧!
2. 提示 (Prompts)
Claude Code 的提示極其詳盡,充滿了啟發式規則、示例和“重要”提醒 (嘖嘖)。系統提示長達約 2800 個 token,而工具部分的描述更是驚人地占用了 9400 個 token。用戶提示總是包含 claude.md 文件,這通常又會增加 1000-2000 個 token。系統提示包含了關于語氣、風格、主動性、任務管理、工具使用策略和執行任務等部分。它還包含了日期、當前工作目錄、平臺和操作系統信息以及最近的提交記錄。
可以去文末附錄部分查看完整提示詞
2.1 使用 claude.md 來協作處理用戶上下文和偏好
大多數編程 Agent 開發者都已達成共識的一個主要模式是使用上下文文件 (即 Cursor Rules / claude.md / agent.md)。Claude Code 在有無 claude.md 的情況下,其表現有天壤之別。對于開發者來說,這是一種傳遞無法從代碼庫中推斷出的上下文以及明確所有嚴格偏好的絕佳方式。例如,你可以強制 LLM 跳過某些文件夾,或使用特定的庫。CC 在每個用戶請求中都會發送 claude.md 的全部內容。
我們最近在 MinusX 中引入了 minusx.md,它正迅速成為我們 Agent 用于明確用戶和團隊偏好的事實上的上下文文件。
2.2 特殊的 XML 標簽、Markdown 和大量示例
使用 XML 標簽和 Markdown 來結構化提示已經是一種公認的做法。CC 廣泛地同時使用了這兩種方式。以下是 Claude Code 中一些值得注意的 XML 標簽:
- : 這個標簽用在許多提示部分的末尾,用來提醒 LLM 那些它大概率會忘記的事情。例如:
這是一個提醒,你的待辦事項列表目前是空的。不要向用戶明確提及這一點,因為他們已經知道了。如果你正在處理的任務可以從待辦事項列表中受益,請使用 TodoWrite 工具創建一個。如果不需要,請忽略此條。再次強調,不要向用戶提及這條消息。- ,: 這些標簽用于固化啟發式規則。當模型面臨一個岔路口,有多個看似合理的路徑/工具調用可供選擇時,它們尤其有用。示例可以用來對比不同情況,明確指出哪條路徑是更可取的。例如:
請在整個會話中盡量保持當前工作目錄不變,方法是使用絕對路徑并避免使用 `cd`。只有在用戶明確要求時,你才可以使用 `cd`。
pytest /foo/bar/tests
cd /foo/bar && pytest testsCC 還使用 markdown 在系統提示中劃分清晰的章節。例如,markdown 標題包括:
- 語氣和風格 (Tone and style)
- 主動性 (Proactiveness)
- 遵循慣例 (Following conventions)
- 代碼風格 (Code style)
- 任務管理 (Task Management)
- 工具使用策略 (Tool use policy)
- 執行任務 (Doing Tasks)
- 工具 (Tools)
3. 工具 (Tools)
可以去文末附錄部分查看完整工具提示詞——它長達驚人的 9400 個 token!
3.1 LLM 搜索 >>> 基于 RAG 的搜索
CC 與其他流行編程 Agent 的一個顯著區別在于它對 RAG (Retrieval-Augmented Generation, 檢索增強生成) 的摒棄。Claude Code 搜索你的代碼庫的方式和你一樣,使用非常復雜的 ??ripgrep???、??jq??? 和 ??find?? 命令。由于 LLM 對代碼有很好的理解,它可以使用復雜的正則表達式找到幾乎任何它認為相關的代碼塊。有時它會用一個較小的模型來讀取整個文件。
RAG 理論上聽起來是個好主意,但它引入了新的 (更重要的是,隱藏的) 故障模式。該用什么相似度函數?用什么重排器 (reranker)?如何對代碼進行分塊 (chunk)?如何處理大的 JSON 或日志文件?而使用 LLM 搜索,它只需查看 JSON 文件的 10 行就能理解其結構。如果需要,它會再看 10 行——就像你會做的那樣。最重要的是,這是可通過強化學習 (Reinforcement Learning) 學習的——這正是大廠們已經在研究的方向。模型承擔了大部分的繁重工作——理應如此,這極大地減少了 Agent 中的活動部件數量。而且,將兩個復雜的智能系統以這種方式連接起來,本身就很丑陋。我最近和朋友開玩笑說,這是 LLM 時代的攝像頭與激光雷達 (Lidar) 之爭,我只有一半是在開玩笑。
3.2 如何設計好工具?(低級工具 vs 高級工具)
這個問題讓每個構建 LLM Agent 的人夜不能寐。你應該給模型通用的任務 (如有意義的動作),還是應該給它低級的任務 (如輸入、點擊和 bash 命令)?答案是:視情況而定 (而且你應該兩者都用)。
Claude Code 擁有低級 (Bash, Read, Write)、中級 (Edit, Grep, Glob) 和高級工具 (Task, WebFetch, exit_plan_mode)。既然 CC 能用 bash,為什么還要單獨提供一個 Grep 工具?這里真正的權衡在于,你期望你的 Agent 使用該工具的頻率與 Agent 使用該工具的準確性之間的關系。CC 使用 grep 和 glob 的頻率非常高,以至于將它們做成獨立的工具是合理的,但同時,它也能為特殊場景編寫通用的 bash 命令。
同樣,還有像 WebFetch 或 'mcp__ide__getDiagnostics' 這樣更高級的工具,它們的功能非常確定。這讓 LLM 無需執行多次低級的點擊和輸入操作,從而保持在正軌上。幫幫可憐的模型吧,好嗎!?工具描述中有詳盡的提示和大量的示例。系統提示中包含了關于“何時使用某個工具”或如何在兩個可以完成相同任務的工具之間進行選擇的信息。
Claude Code 中的工具:
- Task
- Bash
- Glob
- Grep
- LS
- ExitPlanMode
- Read
- Edit
- MultiEdit
- Write
- NotebookEdit
- WebFetch
- TodoWrite
- WebSearch
- mcp\_\_ide\_\_getDiagnostics
- mcp\_\_ide\_\_executeCode
3.3 讓 Agent 管理自己的待辦事項列表
這是一個好主意,原因有很多。上下文衰減 (Context rot) 是長期運行的 LLM Agent 的常見問題。它們一開始熱情地著手解決一個難題,但隨著時間的推移,它們會迷失方向,最終輸出一堆垃圾。當前的 Agent 設計有幾種方法來解決這個問題。許多 Agent 嘗試過顯式的待辦事項 (一個模型生成待辦事項,另一個模型執行它們) 或多 Agent 任務交接 + 驗證 (PRD/PM Agent -> 實現 Agent -> QA Agent)。
我們已經知道,由于種種原因,多 Agent 任務交接不是一個好主意。CC 使用了一個顯式的待辦事項列表,但這個列表是由模型自己維護的。這讓 LLM 保持在正軌上 (它被強烈提示要頻繁參考待辦事項列表),同時又賦予了模型在實現過程中隨時糾正路線的靈活性。這也有效地利用了模型的交錯思維能力,可以動態地拒絕或插入新的待辦事項。
4. 可控性 (Steerability)
4.1 語氣和風格
CC 明確嘗試控制 Agent 的審美行為。系統提示中有關于語氣、風格和主動性的章節——充滿了指令和示例。這就是為什么 Claude Code 的評論和積極性“感覺”很有品味。我建議你直接將這部分的大段內容復制到你的應用中。
# 一些語氣和風格的例子
- 重要:除非用戶要求,否則你不應該用不必要的開場白或結束語來回答 (例如解釋你的代碼或總結你的行動)。
除非用戶要求,否則不要添加額外的代碼解釋摘要。
- 如果你不能或不愿意幫助用戶做某事,請不要說明原因或可能導致的后果,因為這聽起來像在說教,很煩人。
- 只有在用戶明確要求時才使用表情符號。在所有交流中避免使用表情符號,除非被要求。4.2 “這很重要” 仍然是當前最先進的技術
不幸的是,在要求模型不要做某事方面,CC 并沒有更好的辦法。重要 (IMPORTANT)、非常重要 (VERY IMPORTANT)、絕不 (NEVER) 和總是 (ALWAYS) 似乎仍然是引導模型避開雷區的最佳方式。我期望未來的模型能變得更具可控性,從而避免這種粗暴的方式。但就目前而言,CC 廣泛使用了這種方法,你也應該這樣做。一些例子:
- 重要:除非被要求,否則不要添加***任何***注釋。
- 非常重要:你必須避免使用像 `find` 和 `grep` 這樣的搜索命令。請改用 Grep、Glob 或 Task 進行搜索。你必須避免使用像 `cat`、`head`、`tail` 和 `ls` 這樣的讀取工具,而是使用 Read 和 LS 來讀取文件。\n - 如果你*仍然*需要運行 `grep`,停下。請總是先使用 `rg` (ripgrep)。
- 重要:你絕不能為用戶生成或猜測 URL,除非你確信這些 URL 是為了幫助用戶編程。你可以使用用戶在其消息或本地文件中提供的 URL。4.3 寫出算法 (附帶啟發式規則和示例)
識別出 LLM 需要執行的最重要任務,并為其寫出算法,這是極其重要的。嘗試扮演 LLM 的角色,通過示例進行演練,識別出所有的決策點,并明確地寫下來。如果能以流程圖的形式呈現會更有幫助。這有助于結構化決策過程,并輔助 LLM 遵循指令。一定要避免的是一鍋亂燉式的“行為準則”清單 (Dos and Don'ts)。它們更難追蹤,也難以保持互斥。如果你的提示長達數千個 token,你將不可避免地出現相互矛盾的“準則”。在這種情況下,LLM 會變得極其脆弱,也就不可能再納入新的用例了。
Claude Code 系統提示中的 ??任務管理???、??執行任務??? 和 ??工具使用策略?? 部分清晰地闡述了需要遵循的算法。這一部分也是添加大量啟發式規則和 LLM 可能遇到的各種場景示例的地方。
彩蛋:為什么要注意大廠的提示 (Prompts)?
引導 LLM 的很多工作,實際上是在嘗試逆向工程其訓練后/RLHF (Reinforcement Learning from Human Feedback, 基于人類反饋的強化學習) 的數據分布。你應該用 JSON 還是 XML?工具描述應該放在系統提示中還是只在工具定義里?你應用當前的狀態又該如何處理?觀察他們在自家應用中的做法,并用以指導你自己的應用,會很有幫助。Claude Code 的設計非常有主見,借鑒它來形成你自己的觀點是很有益的。
結論
再次強調,核心要點是保持簡單。過度的腳手架框架弊大于利。Claude Code 真的讓我相信,一個“Agent”可以既簡單又極其強大。我們已經在 MinusX 中融入了許多這些經驗,并且正在繼續融入更多。
附錄地址:??https://minusx.ai/blog/decoding-claude-code/#appendix??
本文轉載自??草臺AI??,作者:RangerEX

















