Claude Code 開發經驗談:代理設計與工具系統的藝術
日期: Fri Feb 27 19:20:11 +0000 2026
標籤:
Claude CodeAgent 設計工具整合
來源: @trq212 (Thariq)標籤:
Claude CodeAgent DesignTool SystemProgressive Disclosure
構建 Claude Code 最困難的部分之一是建構其動作空間(action space)。
Claude 透過 Tool Calling 來行動,但在 Claude API 中有多種方式可以構建工具,包括 bash、skills 和最近的 code execution 等基本元件(可以在 @RLanceMartin 的新文章中閱讀更多關於 Claude API 程式化工具呼叫的內容)。
面對這些選項,你該如何設計代理的工具?你只需要一個工具,比如 code execution 或 bash 嗎?如果有 50 個工具,每個工具對應代理可能遇到的一個使用場景,會怎樣?
為了讓自己進入模型的思維,我喜歡想像被給予一個困難的數學問題。為了解決它,你會想要什麼工具?這取決於你自己的技能!
紙筆是最低要求,但你會受限於手動計算。計算機會更好,但你需要知道如何操作更進階的選項。最快且最強大的選項是電腦,但你必須知道如何使用它來編寫和執行程式碼。
這是一個設計代理的有用框架。你想給它符合其自身能力的工具。但你如何知道這些能力是什麼?你要注意觀察、閱讀它的輸出、實驗。你要學會像代理一樣思考。
以下是我們在構建 Claude Code 時,透過觀察 Claude 學到的一些經驗。
改進引導(Elicitation)與 AskUserQuestion 工具
在構建 AskUserQuestion 工具時,我們的目標是改進 Claude 提問的能力(通常稱為 elicitation)。
雖然 Claude 可以用純文字提問,但我們發現回答這些問題感覺需要不必要的時間。我們如何降低這種摩擦並增加使用者與 Claude 之間的溝通頻寬?
嘗試 #1 - 編輯 ExitPlanTool
我們首先嘗試在 ExitPlanTool 中添加一個參數,讓它在計畫旁邊包含一個問題陣列。這是最容易實現的,但它讓 Claude 感到困惑,因為我們同時要求一個計畫和一組關於計畫的問題。如果使用者的答案與計畫中所說的衝突怎麼辦?Claude 需要呼叫 ExitPlanTool 兩次嗎?我們需要另一種方法。
(你可以在我們關於 prompt caching 的文章中閱讀更多關於為什麼我們製作 ExitPlanTool 的內容)
嘗試 #2 - 改變輸出格式
接下來,我們嘗試修改 Claude 的輸出指令,提供一個稍微修改過的 markdown 格式,讓它可以用來提問。例如,我們可以要求它輸出一個帶有括號中替代選項的項目符號問題列表。然後我們可以解析並將該問題格式化為使用者的 UI。
雖然這是我們可以做的最通用的改變,而且 Claude 似乎還可以輸出這個,但這並不能保證。Claude 會附加額外的句子、省略選項,或完全使用不同的格式。
嘗試 #3 - AskUserQuestion 工具
最後,我們決定創建一個 Claude 可以在任何時候呼叫的工具,但特別提示它在計畫模式期間這樣做。當工具觸發時,我們會顯示一個模態框來顯示問題,並阻止代理的循環,直到使用者回答。
這個工具允許我們提示 Claude 進行結構化輸出,並幫助我們確保 Claude 給使用者多個選項。它還為使用者提供了組合此功能的方式,例如在 Agent SDK 中呼叫它或在 skills 中引用它。
最重要的是,Claude 似乎喜歡呼叫這個工具,我們發現它的輸出效果很好。即使是設計最好的工具,如果 Claude 不理解如何呼叫它,也無法發揮作用。
這是 Claude Code 中 elicitation 的最終形式嗎?我們不確定。正如你將在下一個例子中看到的,對一個模型有效的方法可能不是另一個模型的最佳選擇。
隨能力更新 - Tasks & Todos
當我們首次推出 Claude Code 時,我們意識到模型需要一個 Todo 列表來保持它在正軌上。Todos 可以在開始時編寫,並在模型工作時勾選。為此,我們給了 Claude TodoWrite 工具,它會編寫或更新 Todos 並顯示給使用者。
但即使如此,我們經常看到 Claude 忘記它必須做什麼。為了適應,我們每 5 個回合插入系統提醒,提醒 Claude 它的目標。
但隨著模型的改進,它們不僅不需要被提醒 Todo List,還可能發現它是有限制的。被發送 todo list 的提醒讓 Claude 認為它必須堅持列表,而不是修改它。我們還看到 Opus 4.5 在使用 subagents 方面變得更好,但 subagents 如何在共享的 Todo List 上協調?
看到這一點,我們用 Task Tool 取代了 TodoWrite(在這裡閱讀更多關於 Tasks 的內容)。Todos 是關於讓模型保持在正軌上,而 Tasks 更多是關於幫助代理彼此溝通。Tasks 可以包含依賴關係、在 subagents 之間共享更新,模型可以修改和刪除它們。
隨著模型能力的提升,你的模型曾經需要的工具現在可能正在限制它們。不斷重新審視關於需要什麼工具的先前假設是很重要的。這也是為什麼堅持支援一小組具有相當相似能力檔案的模型是有用的。
設計搜尋介面
對 Claude 來說,一組特別重要的工具是可以用來構建自己上下文的搜尋工具。
當 Claude Code 首次推出時,我們使用 RAG 向量資料庫為 Claude 尋找上下文。雖然 RAG 強大且快速,但它需要索引和設定,並且在各種不同的環境中可能很脆弱。更重要的是,Claude 被給予這個上下文,而不是自己找到上下文。
但如果 Claude 可以在網路上搜尋,為什麼不搜尋你的程式碼庫?通過給 Claude 一個 Grep 工具,我們可以讓它搜尋檔案並自己構建上下文。
這是我們看到的一個模式,隨著 Claude 變得更聰明,如果給它正確的工具,它在構建自己的上下文方面變得越來越好。
當我們引入 Agent Skills 時,我們正式化了漸進式揭露(progressive disclosure)的概念,它允許代理通過探索逐步發現相關上下文。
Claude 可以讀取 skill 檔案,這些檔案然後可以引用模型可以遞迴讀取的其他檔案。事實上,skills 的一個常見用途是為 Claude 添加更多搜尋能力,比如給它關於如何使用 API 或查詢資料庫的指令。
在一年的時間裡,Claude 從不太能夠構建自己的上下文,到能夠在幾層檔案中進行嵌套搜尋,找到它需要的確切上下文。
漸進式揭露現在是我們用來在不添加工具的情況下添加新功能的常見技術。
漸進式揭露 - Claude Code Guide Agent
Claude Code 目前有大約 20 個工具,我們不斷問自己是否需要所有這些工具。添加新工具的門檻很高,因為這給模型多了一個要考慮的選項。
例如,我們注意到 Claude 對如何使用 Claude Code 了解不夠。如果你問它如何添加 MCP 或斜線命令做什麼,它無法回答。
我們可以把所有這些資訊放在系統提示中,但考慮到使用者很少問到這個,它會增加上下文腐爛並干擾 Claude Code 的主要工作:編寫程式碼。
相反,我們嘗試了一種漸進式揭露的形式。我們給了 Claude 一個指向其文件的連結,然後它可以載入以搜尋更多資訊。這有效,但我們發現 Claude 會將大量結果載入上下文以找到正確答案,而實際上你只需要答案。
所以我們構建了 Claude Code Guide subagent,當你詢問關於它自己的問題時,Claude 被提示呼叫它,這個 subagent 有關於如何搜尋文件以及返回什麼的詳細指令。
雖然這並不完美,當你問它關於如何設定自己時,Claude 仍然可能會感到困惑,但它比以前好多了!我們能夠在不添加工具的情況下將東西添加到 Claude 的動作空間中。
一門藝術,而非科學
如果你希望得到一套關於如何構建工具的嚴格規則,不幸的是,這不是那種指南。為你的模型設計工具既是一門藝術,也是一門科學。它在很大程度上取決於你使用的模型、代理的目標以及它運行的環境。
經常實驗、閱讀你的輸出、嘗試新事物。像代理一樣思考。