Claude Certified Architect — Foundations(CCA-F)考試任務說明 2.3 的內容是:「在各 agent 之間適當分配工具,並設定 tool_choice。」它隸屬於 Domain 2(工具設計與 MCP 整合,佔考試計分 18%),儘管領域比重看似不高,卻是社群通過題庫中陷阱題密度最高的區域之一。原因很直接:工具分配與 tool_choice 橫跨 agent 架構(Domain 1)、提示工程(Domain 4)與可靠性(Domain 5)三個面向。此處一個錯誤的設計決策,會連鎖引發工具選擇錯誤、幻覺函式呼叫、結構化輸出偏移,以及失控的 agentic loop——而這些全都會在考試其他地方計分。把任務 2.3 做對,就是槓桿。
這份學習筆記涵蓋 CCA-F 考生需要在架構層級設計的完整面向:決定每個 agent 應擁有哪些工具的原則、coordinator 與 subagent 的分工、tool_choice 參數的四個值(auto、any、指定工具物件(forced)、none)及各自對應的使用情境、用於 schema 強制執行的 forced tool call 模式、跨工作流程狀態的動態工具可用性、讓 agent 在自身職責範圍內運作的存取控制機制,以及工具目錄過大對效能的可量測影響。最後以常見考試陷阱章節、與考試情境掛鉤的練習錨點,以及五道 FAQ 收尾。
工具分配原則 — 只將相關工具指派給各 Agent
工具分配是架構層面的決策——決定系統中每個 agent 被允許看見哪些工具。這不是執行期的問題;它是你在每次 Messages API 呼叫中傳入 tools 陣列時,以及在每個 subagent 定義的 allowed_tools 清單中所設定的 schema。這個原則說起來幾乎簡單到可笑,但實踐起來卻出乎意料地困難:只給每個 agent 完成其指定任務所需的工具,不多給一個。
為什麼「只給相關工具」是生產需求
每個 agent 被允許看見的工具,都會消耗三種稀缺資源:
- Context token — 每個工具定義(名稱、描述、
input_schema)都會在每次請求中注入系統 context。一份 40 個工具的目錄,會在每輪迴圈迭代的每個 turn 增加數千個 token。 - 選擇認知負荷 — Claude 必須讀取完整目錄,與使用者目標比對,再做出選擇。目錄越大,相近選擇出錯的機率就越高(例如本該呼叫
search_accounts,卻選了search_customers)。 - 爆炸半徑 — agent 能呼叫的每個工具,就是 agent 可能誤用的工具。一個同時擁有正式資料庫寫入權限的研究 subagent,就是一個可以損毀正式資料庫的研究 subagent。
縮小工具集能同時降低以上三種壓力。這正是 Anthropic 官方的工具撰寫指南將積極縮限範圍視為一級設計原則,而非效能微調的原因。
工具分配(Tool distribution)是在 multi-agent 系統中將工具指派給各 agent 的架構決策。每個 agent 收到一個刻意縮限範圍的 tools 陣列(或 subagent 定義中的 allowed_tools 清單),只包含其任務所需的工具。分配決策在設計時做出,而非執行期,並直接控制 context 成本、工具選擇準確性與爆炸半徑安全性。CCA-F 任務 2.3 測試考生能否以情境題的形式,說明分配決策的理由,而不只是背誦原則。
Source ↗
以角色為起點的分配捷思法
在列舉工具之前,先為 agent 的角色寫一句話描述。「退款 agent 負責處理客戶的退款請求。」從這句話中,列出必須可達的名詞與動詞——refund(退款)、charge(扣款)、customer(客戶)、account(帳戶)、policy_document(政策文件)——再將每個項目對應到唯一一個工具。任何角色描述中未提及的內容,都應省略。從「這是我們的工具庫,每個 agent 可以用哪些」出發的考生,往往得到過大的目錄;從角色描述出發的考生,往往得到精簡的目錄。
為什麼每個 Agent 的工具越少越好 — 降低歧義、提升選擇準確性
「每個 agent 工具越少越好」背後的實測觀察是:隨著工具目錄增長,Claude 的工具選擇準確性會下降,且下降並非線性——一旦目錄超過模型的有效選擇範圍,下降速度就會加速。這既符合直覺(面對四十個幾乎一樣的按鈕,人也更容易按錯),也在生產 trace 中直接可觀察到。
三種導致準確性下降的機制
- 近似工具混淆 — 名稱或描述重疊的工具(
search_users、lookup_accounts、find_customers)在使用者措辭模糊時,容易讓 Claude 選到錯誤的一個。 - 描述稀釋 — 目錄越長,每個工具的描述在系統 context 中的位置就越往後;「迷失在中間」效應會降低工具邊界的召回率。
- 過度工具呼叫 — 可見工具越多,Claude 越容易在直接從 context 回答才是正確行為時,卻呼叫了某個工具。這是工具版本的「給木匠更大的工具箱,他就會找到更多東西可以敲」。
工具越少的規則與良好描述相輔相成
工具分配是必要條件,但不充分。即使目錄精簡,若描述模糊,依然會失效——這是 Domain 2.1 的關注點。正確的心理模型是:任務 2.1 讓每個工具的邊界清晰;任務 2.3 確保一開始只有正確的工具對各 agent 可見。兩個槓桿都必須同時拉動。
社群通過報告一致指出「讓 agent 的工具數量過多」是 CCA-F 最高頻的錯誤之一。當情境答案選項中有「給這個 agent 存取所有五十個平台工具以應對邊緣情況」時,那個選項幾乎總是錯的。正確答案是將目錄縮減到涵蓋角色的最低限度。 Source ↗
Coordinator 工具集 vs Subagent 工具集 — 關注點分離
在 coordinator-subagent 架構中,coordinator 和每個 subagent 各自擁有獨立的工具目錄。分配決策因此是兩層的:coordinator 一個目錄,每個 subagent 角色一個目錄。將它們視為單一共享目錄,是常見的設計失誤。
Coordinator 應擁有的工具
Coordinator 的職責是拆解任務、派遣 subagent、組裝最終答案。其工具集應反映這一點:
- Subagent 派遣工具(coordinator 的主要介面——啟動研究 subagent、啟動擷取 subagent)。
- 狀態管理工具,用於追蹤整體計畫(任務清單讀寫、session 檢查點)。
- 最終答案組裝工具,對聚合後的 subagent 輸出進行操作。
Coordinator 幾乎不應直接存取 subagent 使用的底層工具(檔案讀取、資料庫寫入、外部 API 呼叫)。若 coordinator 能直接完成 subagent 的工作,那 subagent 就是多餘的,整個架構已然崩潰。
每個 Subagent 應擁有的工具
每個 subagent 的目錄限定在其單一職責範圍內。研究 subagent 得到網路搜尋與摘要工具。擷取 subagent 得到文件讀取與結構化輸出工具。驗證 subagent 得到查詢與比對工具。除非架構明確設計為超過兩層的層級結構,否則 subagent 不應擁有啟動其他 subagent 的權限。
為什麼這個分工在 CCA-F 上很重要
考試情境經常呈現一個 multi-agent 研究系統,並詢問哪個 agent 應擁有哪個工具。Coordinator 直接擁有檔案讀取權限,在情境其他部分清楚分工的情況下,是一個陷阱答案——正確設計應將檔案讀取推入研究 subagent。同樣地,subagent 擁有啟動其他 subagent 的權限,也是陷阱答案,除非情境明確描述了三層層級結構。
在考試中繪製 coordinator-subagent 情境圖時,先在讀取答案選項之前為每個工具標上其正確的擁有者。根據選項而非第一原則來決定分配方式的考生,更容易被相近的干擾選項所騙。 Source ↗
tool_choice 設定 — auto、any 與 Forced(指定工具名稱)模式
tool_choice 是 Messages API 參數,用於控制 Claude 在下一個 turn 被允許呼叫哪個工具,以及是否需要呼叫。該參數有四種合法的形式:auto、any、明確的工具物件(forced)和 none。誤解其中任何兩者之間的語義差異,是 Domain 2 中最反覆出現的陷阱之一。
四種形式
{ "type": "auto" }— Claude 根據對話自行決定是否使用工具,以及使用哪一個。這是預設值。{ "type": "any" }— Claude 必須使用目錄中的某個工具;本次 turn 不能以純文字回應。{ "type": "tool", "name": "<tool_name>" }— Claude 在本次 turn 必須呼叫指定名稱的工具。{ "type": "none" }— Claude 不得呼叫任何工具;必須以純文字回應。
tool_choice 是 Messages API 參數,用於約束 Claude 在下一次回應中的工具呼叫行為。四個值——auto、any、forced 工具物件 { type: "tool", name: "..." } 和 none——各自表達不同的架構意圖。auto 是預設值,讓 Claude 自行決定;any 強制發出工具呼叫但不指定哪個;forced 物件則完全移除 Claude 的選擇判斷,直接指名工具;none 在本次 turn 停用工具使用。該參數在每次 API 呼叫中單獨設定,因此在同一個 agentic loop 的不同 turn 中可以有所不同。
Source ↗
tool_choice 是 Per-Call,而非 Per-Agent
考試中的一個常見誤解是:tool_choice 是一次性的 agent 設定。事實並非如此。tool_choice 在每次 Messages API 呼叫中獨立設定,這意味著同一個 agentic loop 可以合理地在第一個 turn 設定 tool_choice: any 以強制初始工具呼叫,然後在後續 turn 切換到 auto 讓 Claude 自行決定,最後在最終 turn 切換到 forced 物件以輸出符合 schema 的答案。跨迴圈動態設定 tool_choice,是任務 2.3 與任務 4.3 多個情境背後的設計槓桿。
tool_choice: auto — 由模型決定是否呼叫工具以及呼叫哪個
tool_choice: auto 是預設值,也是大多數開放式 agentic 情境的正確答案。在 auto 模式下,Claude 讀取使用者目標、與工具目錄比對,然後自主決定:
- 是否需要工具呼叫,或直接以文字回答就夠了。
- 要呼叫哪個具體工具。
- 是否在同一條訊息中發出多個並行工具呼叫。
什麼時候 auto 是正確選擇
auto 適用於工作流程是探索性或多分支的情況——客服解決方案 agent 處理難以預測的工單、code-generation-with-claude-code agent 在未知檔案中調查 bug、multi-agent-research-system coordinator 決定派遣哪個 subagent。在這些情況下,Claude 對是否呼叫工具以及呼叫哪個工具的判斷,是設計特性而非缺陷。
什麼時候 auto 是錯誤選擇
當你的架構要求一定要有工具呼叫時,auto 就是錯的——例如,結構化擷取工作流程的最後一個 turn,唯一可接受的輸出形狀是某個特定工具的 schema。在 auto 模式下,Claude 可能判斷答案已完整,並發出不符合任何工具 schema 的純文字回應。這正是擷取 pipeline 在最後一個 turn 切換到 forced tool_choice 的原因。
auto 與並行工具呼叫
在 auto 模式下,現代 Claude 模型會積極並行化彼此獨立的工具呼叫。一個要查找四個不相關事實的研究 agent,通常會在一條訊息中發出四個 tool_use 區塊。這是預設行為;tool_choice 不控制這個開關。
tool_choice: any — 模型必須使用某個工具(防止純文字回應)
tool_choice: any 表示「Claude 必須呼叫某個工具,但我不指定哪個」。它比 forced 工具物件弱,但比 auto 強。它在一個狹窄的情境範圍內才是正確選擇,在更廣泛的情境中則是陷阱答案。
any 的合理使用案例
any 適用於以下情況:
- 本次 turn 的工作流程必須採取工具介導的行動(例如「務必透過某個日誌工具記錄此事件」),但具體的行動取決於 context。
- Agent 還不能直接回應使用者,因為業務規則是「在調用某個調查工具之前,不得直接對使用者回覆」。
- 你想防止 Claude 以一個聽起來很有把握、但調查不足的文字答案跳過研究階段。
any 不能保證什麼
any 不保證 Claude 會選擇哪個工具。若目錄中同時有 search_knowledge_base 和 escalate_to_human,Claude 可能選任一個,你的應用程式必須同時處理兩種結果。描述 any 為「強制 Claude 使用正確的工具」或「強制 Claude 保持在任務上」的答案,是誇大了其保證範圍。any 只移除了純文字回應的選項;工具選擇仍然在 Claude 的判斷之中。
any 是錯誤選擇的情況
在考試中,以下情況 any 是錯誤答案:
- 情境要求特定工具(應改用 forced 工具物件)。
- 情境只是希望行為良好(應改用更好的工具描述搭配
auto——any不改善選擇品質,只移除文字選項)。 - 情境是開放式調查,拒絕文字回應會阻斷合理輸出(應用
auto)。
CCA-F 社群題庫中出現頻率最高的 tool_choice 陷阱,是將 any 當作強制指定工具的方式。any 只強制某個工具;它不指定是哪個。若情境需要精確的工具強制執行,正確答案是 { type: "tool", name: "<specific>" },而不是 any。將 any 等同於「強制正確的工具呼叫」的答案,永遠是錯的。
Source ↗
tool_choice: forced — 模型必須呼叫指定名稱的工具
Forced tool_choice 的值是形如 { "type": "tool", "name": "<tool_name>" } 的物件。它完全移除 Claude 在當前 turn 的工具選擇判斷:下一次回應必須包含剛好一個帶有指定工具名稱的 tool_use 區塊。沒有協商空間,沒有退回文字的後路,沒有替代工具。
Forced tool_choice 的用途
Forced tool_choice 是以下場景的標準機制:
- 最終步驟的 schema 強制執行 — 在擷取工作流程結束時,強制呼叫
emit_structured_record工具,確保輸出符合工具的input_schema。 - 確定性的 pipeline 階段 — 在固定的多步驟 pipeline 中,當步驟 N 必須始終呼叫
classify_intent時,在步驟 N 強制使用該工具。 - 打破震盪迴圈 — 當 Claude 在兩個工具之間來回切換時,強制其中一個可以終止震盪。
Forced tool_choice 不適用的情況
Forced tool_choice 不是讓 Claude 對某個工具「思考更深入」的方式;它明確地繞過 Claude 的選擇判斷。若強制呼叫的工具對當前狀態而言是錯誤的,Claude 仍然會以它能構造出的任何輸入呼叫它,而那些輸入可能毫無意義。Forced tool_choice 是對形狀的約束,而非對正確性的約束。
與並行工具呼叫的互動
當 tool_choice 是 forced 工具物件時,Claude 會輸出剛好一個帶有指定工具名稱的 tool_use 區塊。並行多工具輸出被抑制。這對比較 forced tool pipeline 與 auto pipeline 延遲的情境題很重要——在 forced 模式下,並行化能力會喪失。
與 strict 模式的互動
Forced tool_choice 與工具定義上的 strict: true 天然配對。strict: true 保證工具的 input_schema 被精確執行;forced tool_choice 保證被呼叫的就是這個特定工具。兩者結合,可產生 schema 有保證的結構化輸出——這是任務 4.3 情境的標準模式。
Forced tool_choice 是參數的 { type: "tool", name: "..." } 形式。它在一個 turn 中完全移除 Claude 的工具選擇判斷,強制規定下一次回應必須呼叫指定的工具。它用於強制執行符合 schema 的最終輸出、固定確定性的 pipeline 階段,以及打破 agentic loop 中的震盪。它與 any 不同——後者只禁止文字回應而不指定工具。它繞過——而非增強——Claude 的選擇邏輯。
Source ↗
Forced Tool Choice 的使用案例 — Schema 強制執行、透過工具輸出結構化資料
Forced tool_choice 在 CCA-F 上的主要使用案例,是透過工具使用來強制執行結構化輸出。這是 Domain 2.3 負責設定的 Task 4.3 標準模式。
模式:將 input_schema 定義為你要的輸出 Schema 的工具
與其在提示中要求 Claude「以符合此 schema 的 JSON 回傳」,不如定義一個工具,讓其 input_schema 就是你要的輸出 schema。以它所代表的行動來命名工具——emit_customer_record、submit_bug_report、record_extracted_entities。將 tool_choice 設為指名此工具的 forced 工具物件,並(最好)在工具定義上設 strict: true。
因為 forced tool_choice 讓 Claude 呼叫的一定是那個工具,而 strict: true 保證工具輸入符合 schema,最終的 tool_use 區塊中的 input 欄位就是一個可直接使用的符合 schema 的 JSON 物件。沒有解析歧義,沒有包裹在 JSON 外面的散文,沒有缺少的欄位。
為什麼這比基於提示的 JSON 指令更好
基於提示的「請以此格式回傳 JSON」指令有三個反覆出現的失效模式:欄位缺失或多餘、JSON 外包裹著結尾散文,以及邊緣情況下的 schema 漂移。Forced tool_choice 加上 strict: true 消除了這三者,將執行從提示指令合規(軟性)移至 API 層級的 schema 驗證(硬性)。社群通過報告一致將此列為 CCA-F 上「最重要的五個心理模型」之一。
何時套用此模式
在以下情況套用 forced tool_choice 的結構化輸出模式:
- 下游消費者要求嚴格的 schema 合規(pipeline 解析、資料倉庫載入、契約 API)。
- 你的業務量很高,無法承擔每筆記錄驗證並重試的成本。
- 輸出形狀穩定且事先已知。
以下情況不要套用此模式:輸出形狀因請求而異(改用 auto 讓 Claude 從小工具集中選擇適合的工具),或輸出應在結構化資料旁附上自由格式的說明(考慮兩個 turn 的模式——forced 工具用於記錄,auto 用於說明)。
Forced tool_choice 與指名工具上的 strict: true 的組合,是 CCA-F 標準答案,用於「保證結構化輸出合規」。提出「在系統提示中加入更嚴格的指令」或「事後驗證 JSON 並重試」的答案,幾乎總是劣於 forced tool 模式,因為它們依賴提示合規而非 API 層級的執行。程式化執行勝過提示指引。
Source ↗
動態工具可用性 — 根據工作流程狀態啟用或停用工具
工具可用性不必在 agentic loop 的整個生命週期中保持靜態。設計良好的迴圈經常在 turn 與 turn 之間變換可見的工具集,使每次只有符合當前工作流程狀態的工具才被暴露出來。
為什麼動態可用性存在
單一 agent 可能經歷幾個截然不同的階段——規劃、執行、驗證、回報。不同的工具適合不同的階段。在規劃階段暴露執行工具,會招致過早行動;在執行階段暴露回報工具,會引誘 Claude 跳過步驟、輸出片段摘要。將可見工具限定在該階段的意圖範圍內,能讓 Claude 保持在正確的概念軌道上。
兩種變換工具可用性的機制
- Per-call
tools陣列 — 最簡單的機制。你的應用程式根據當前工作流程狀態,在每次 Messages API 呼叫中傳入不同的tools陣列。狀態機越小,這個做法越容易實作。 - Per-call
tool_choice— 較柔性的機制。保持tools陣列不變,但變換tool_choice——規劃階段用auto,執行階段用 forced 工具物件強制指名「執行」呼叫,最終摘要階段用none。兩種機制可以同時使用。
具體範例 — 三階段擷取 Pipeline
第 1 個 turn(規劃):tools = [list_documents, read_document],tool_choice = auto。Claude 列出並讀取相關文件。第 2 個 turn(擷取):tools = [read_document, emit_record],tool_choice = { type: "tool", name: "emit_record" }。Claude 被強制執行符合 schema 的記錄輸出。第 3 個 turn(關閉):tools = [],tool_choice = none。Claude 撰寫人類可讀的摘要,不再可能有任何工具呼叫。
這個範例說明動態工具可用性不是微調;它是讓 Claude 的行為與工作流程當前意圖保持一致的結構性技術。
在 CCA-F 情境中,「agent 在調查階段完成前不得採取行動」這句話,預告的是動態工具可用性答案。在調查期間從目錄中移除執行工具(或設定 tool_choice: none),之後再恢復。試圖用更強硬的系統提示達到相同效果的答案較差,因為它們依賴提示合規而非 API 層級的保證。
Source ↗
工具存取控制 — 防止 Agent 存取範圍外的工具
工具分配決策同時也是存取控制決策。無法看見工具的 agent,無論多巧妙的提示如何說服它,也無法呼叫那個工具。這正是 agent 系統中的存取控制為什麼要在工具定義層實作,而不是在提示層實作的原因。
工具存取控制的三個層次
- 分配時縮限範圍 — 每次 Messages API 呼叫的
tools陣列,或每個 subagent 定義的allowed_tools清單,精確列舉 agent 可以看見哪些工具。不在陣列中的工具,對 Claude 而言是不可見的。 - 伺服器端授權 — 你的工具實作依然需要對每次呼叫進行授權。一個因為「agent 應該被範圍限制住了」就信任呼叫者的
delete_user工具,是個責任。縱深防禦。 - Hook 攔截 — Agent SDK 的
PreToolUsehook 可以在執行期拒絕特定的工具呼叫(例如,拒絕任何引用rm -rf的Bash呼叫)。Hook 正式屬於任務 1.5 的概念,但它們補全了存取控制的閉環。
為什麼基於提示的存取控制會失敗
「除非使用者是管理員,否則不要呼叫 delete_user 工具」是基於提示的約束。Claude 通常會遵守,但「通常」不是存取控制的保證。以分配方式表達的同一個約束(非管理員 agent 的 tools 陣列中根本沒有 delete_user),是一個硬性邊界。CCA-F 一致偏好硬性邊界的答案。
Subagent allowed_tools 作為存取控制介面
Claude Code 中的自訂 subagent 定義暴露了一個 allowedTools 清單。這是縮限 subagent 能力的結構性方式。以 allowedTools: [Read, Grep, Glob] 定義的「research」subagent,實體上無法呼叫 Write、Edit 或 Bash,即使其行為提示不小心引導它那麼做。這是任務 2.3 的槓桿,也會影響任務 1.3(subagent 呼叫)。
三種工具存取控制機制,各用一句話:
tools陣列 /allowedTools— 分配時縮限範圍;不可見的工具無法被呼叫。- 工具實作中的伺服器端授權 — 執行期執行;縱深防禦。
PreToolUsehook — 在執行前對特定呼叫的程式化否決。
經驗法則:結構性約束(agent 角色、多租戶隔離)優先用分配時縮限範圍;資料層級約束用伺服器端授權;動態政策檢查用 hook。 Source ↗
工具集大小對效能的影響 — 大型工具目錄的認知負荷
目前沒有官方公布的工具選擇準確性崩潰閾值,考試也不測試確切數字。考試測試的是效應的方向以及緩解模式。
效應的方向
隨著目錄中的工具數量增加,三件可量測的事情同時變差:
- 選擇準確性 — Claude 為給定使用者目標選擇正確工具的機率下降。
- input schema 遵循度 — context 中有更多工具時,工具輸入欄位名稱和型別更容易在相似工具之間交叉污染。
- 過度工具呼叫頻率 — Claude 更容易在直接回答本已足夠的情況下去呼叫工具。
這些效應會互相影響。一份有幾個近似工具、描述模糊的 40 個工具目錄,產生的 agent 行為質量明顯劣於一份有清晰描述的 10 個工具目錄——而且即使修正 40 個工具目錄中的描述,也只能挽回部分失去的準確性。根本的制約因素是目錄大小本身。
三種緩解方式,按偏好順序排列
- 合併重疊的工具 — 若
search_users和lookup_accounts都在目錄中,將它們合併為一個邊界更清晰的search_accounts工具。 - 拆分 agent — 若單一 agent 需要很多工具,因為它扮演了多個角色,就將它拆分為 coordinator 加上各角色的 subagent,並相應地分配工具。
- 使用動態工具可用性 — 若同一個 agent 扮演相同角色但會經歷不同階段,就按階段變換可見工具。
無法縮減目錄時
某些合理的使用案例確實需要大型目錄——例如 IDE 風格的程式碼助理,會暴露數十個內建工具。在這些情況下,緩解策略轉向工具搜尋模式:MCP connector 支援工具搜尋,將工具定義的載入延遲到 Claude 查詢時。這讓 in-context 目錄保持精簡,同時仍能存取龐大的實體工具庫。工具搜尋是任務 2.4 的主題,但其動機在此處。
在 CCA-F 上,任何以「加入更多工具來涵蓋更多情況」來解決「agent 一直選到錯誤的工具」問題的答案,都是錯的。正確的修正方向是更少、範圍更精確的工具——透過合併、拆分為 subagent,或動態可用性來實現。更多工具從不會讓選擇準確性更好。 Source ↗
與 strict 模式的互動 — Forced 加 strict 模式的組合
strict 模式(工具定義上的 strict: true)是一個正交機制,保證工具的 input_schema 在 API 層級被精確執行。它與 tool_choice 組合,形成 CCA-F 最重要的結構化輸出模式。
strict 模式的作用
設定 strict: true 時:
- 工具的
input_schema必須是封閉的(不允許超出已宣告欄位的額外屬性)。 - 型別與 enum 約束由 API 執行;Claude 無法輸出無效的工具輸入。
- 標記為 required 的欄位必須存在。
Forced 加 strict 模式的組合
tool_choice: { type: "tool", name: "emit_record" } 加上 emit_record 上的 strict: true 這個組合,提供三項保證:
- Claude 將呼叫
emit_record,而不是其他工具。 - Claude 對該呼叫的
input將完全符合 schema。 - 你的應用程式可以直接使用
input,無需驗證開銷。
這是任務 4.3(「使用工具使用與 JSON schema 強制執行結構化輸出」)的架構答案,而它存在於任務 2.3 中,因為 forced tool_choice 是該模式的選擇層面。分開學習這兩個部分的考生,會錯過與考試相關的組合。
strict 模式不夠的情況
strict 模式執行形狀,不執行語義。一個帶有 discount_percent: number 欄位的 strict: true 工具,會拒絕字串輸入,但會毫無異議地接受 -500 作為數字。語義驗證——折扣必須在 0 到 100 之間——仍然屬於你工具的伺服器端實作。Claude 可以被信任產生形狀正確的輸入;但不能被信任產生永遠正確的輸入。
tool_choice 與 none — 完全抑制工具呼叫
tool_choice: none 禁止 Claude 在下一個 turn 呼叫任何工具。回應必須是純文字。這個值的存在,是為了在不修改 tools 陣列的情況下乾淨地停用工具使用。
何時使用 none
- 最終答案摘要階段 — 在調查和結構化輸出之後,最終的人類可讀摘要不應再觸發任何工具呼叫。
- 安全敏感的 turn — 當 agent 正在產生人類即將讀取並採取行動的回應時,停用工具可防止任何最後一秒的行動。
- 說明 turn — 「解釋你做了什麼」的回應不應再採取進一步行動。
何時不要使用 none
- 若要在「規劃」階段防止工具使用——改用動態工具可用性(縮小
tools陣列),因為none可以在每次呼叫中被覆蓋,而分配是結構性邊界。 - 若要在任何工具呼叫都不適合時強制純文字回應——這確實是
none的用途,但再想想auto是否能以更少的儀式做到同樣的事(當工具無用時,Claude 本來就會輸出文字)。
白話說明
工具分配與 tool_choice 是同一枚設計硬幣的兩面:一面決定每個 agent 能看見哪些工具,另一面決定 agent 在給定的 turn 是否被允許呼叫工具,以及呼叫哪個。以下三個類比分別從不同角度涵蓋完整面向。
類比一:醫院急診部門 — 分配即角色縮限範圍
想像一間醫院急診部門。分診護理師能存取生命徵象監測器、病歷系統和一份「轉介給專科醫師」的內部表單。分診護理師沒有手術室的手術刀、放射科的電腦斷層掃描儀,或藥局的管制藥品調劑器——不是因為護理師不值得信任,而是因為這些工具屬於其他角色,將它們放在分診站只會造成混淆,並暴露出護理師執行自身工作根本不需要的操作介面。心臟科醫師、放射科醫師和藥師各自有自己的工具集,縮限在其角色範圍內。這正是 coordinator-subagent 架構中的工具分配。每個 agent(角色)只看到與其職責相關的工具。急診科主治醫師(coordinator)將工作派給專科醫師(subagent),但不直接使用專科醫師的工具。一間每位臨床人員都擁有所有工具的醫院會是災難;一個每個 agent 都擁有所有工具的 agent 系統只是低效且容易出錯——但道理是一樣的。
類比二:自動販賣機選擇器 — tool_choice 模式
一台自動販賣機有三種不同的「購買執行」設定,與 tool_choice 完美對應。在 auto 模式下,你可以自由走近、瀏覽目錄,決定是否要買任何東西——你可能只是在看看。在 any 模式下,有人給了你一張必須在離開前用完的禮物卡;你必須買某樣東西,但你仍然可以選擇買哪個點心。在 forced 模式下,有人伸手過來、替你按下了按鈕,說「你要買花生巧克力——沒得商量」。none 是第四種設定:機器停止服務,任何選擇都不被允許。每種模式都有其存在的理由。auto 適合可選擇性購買的情況;any 適合必須買某樣東西但選哪樣由你決定的情況;forced 適合特定品項不容協商的情況;none 適合你應該完全走過機器不做任何事的情況。把「any」與「forced」混淆,就像以為禮物卡鎖定你只能買某個特定點心——它並不會;它只是強制一次購買。
類比三:工地進場許可 — 許可窗口的存取控制
在受管制的工地上,每位工人攜帶一張許可證,上面精確列舉他們被認證可以操作的設備。木工組有鋸子和打釘槍的許可。電氣組有電管和斷路器的許可。吊車操作員有吊車的許可,其他什麼都沒有。當工人刷卡進入某台設備時,讀卡機比對許可與機器。許可不符的工人實體上無法啟動設備——連鎖機制拒絕了他。這是以「進場許可」形式表達的工具存取控制。識別證(allowedTools 清單)決定工人(agent)能碰什麼。塗在吊車上的「未經認證請勿操作」是基於提示的約束;在點火開關處執行的許可驗證是基於分配的約束。考試一致偏好第二種,因為第一種依賴遵守,第二種在結構上不可能被違反。沒有許可的 agent 無法誤用一個工具。
哪個類比對應哪種考試題目
- 關於每個 agent 應擁有哪個工具的題目 → 醫院急診部門類比。
- 關於**選擇
auto、any、forced 或none**的題目 → 自動販賣機類比。 - 關於防止範圍外工具使用的題目 → 工地許可類比。
常見考試陷阱
CCA-F 任務 2.3 在考試大綱中列出兩個具名陷阱,加上社群通過報告記錄的幾個高頻隱性陷阱。
陷阱一:將 any 視為「強制指定工具」
考試大綱明確點名這一點:tool_choice: any 不保證特定工具。它只禁止文字回應。若兩個或更多工具可見,而業務邏輯要求其中恰好一個,any 是不夠的——正確的值是 forced 工具物件 { type: "tool", name: "<specific>" }。干擾答案經常將 any 描述為「讓 agent 保持在任務上」或「強制正確的工具呼叫」。兩種說法都是錯的。any 比 forced 弱,不得以 any 替代 forced。
陷阱二:將 Forced tool_choice 視為「讓 Claude 對此工具思考更深入」
同樣來自考試大綱:forced tool_choice 完全繞過 Claude 的選擇判斷。它不改善 Claude 對當前狀態下工具是否正確的推理;它只是強制呼叫,並相信你的架構已將狀態設定正確。若強制呼叫的工具對當前 turn 是錯誤的,Claude 仍然會以它能構造出的最佳輸入發出呼叫。描述 forced 模式為「幫助 Claude 選擇正確工具」的答案,誤述了機制。
陷阱三:將過大的工具目錄視為「安全」選擇
一個反覆出現的干擾選項說「給 agent 存取所有平台工具以應對邊緣情況」。社群通過報告一致認定這是錯誤答案。過大的目錄會降低選擇準確性、膨脹 context 成本、擴大爆炸半徑。正確的修正方向永遠是更緊的範圍——合併、拆分 subagent 或動態可用性。
陷阱四:以基於提示的存取控制取代分配
另一個反覆出現的干擾選項提出「加入系統提示,指示 agent 不要呼叫 delete_user」。這是依賴合規的基於提示的約束。正確答案是完全從 agent 的 tools 陣列中移除 delete_user。分配是硬性邊界;提示是軟性邊界。考試偏好存取控制的硬性邊界。
陷阱五:在 auto 足夠時使用 any
考生有時會將 any 作為防禦性預設——「確保 agent 使用其工具」。在開放式工作流程中,auto 幾乎總是正確答案。Claude 在工具有用時會使用工具,在文字適合時會以文字回應。在不需要工具的情境下,透過 any 強制工具呼叫,會產生輸入品質低劣的工具呼叫。any 是窄用途設定,而非安全預設。
練習錨點
工具分配與 tool_choice 的概念出現在每個 CCA-F 情境叢集中,但在以下兩個情境中佔有最高比重。
Developer-Productivity-With-Claude 情境
開發者使用 SDK 驅動的 agent 在大型程式碼庫上執行自主任務。不同角色需要不同的工具集:調查 agent 需要 Read、Grep 和 Glob;重構 agent 需要 Edit 和 Write;測試撰寫 agent 需要 Write、Read 和 Bash。預期情境題會測試分配決策——coordinator-subagent 分工中哪個 agent 應擁有 Bash、哪個應擁有 Edit、哪個應只擁有 Read。也預期會有 tool_choice 的 pipeline 階段題:調查階段使用 auto,最終摘要階段使用 none,任何必須輸出特定結構化製品(例如重構計畫記錄)的階段使用 forced tool choice 加 strict: true。
Multi-Agent-Research-System 情境
在 multi-agent-research-system 情境中,coordinator 派遣研究 subagent、收集其發現,並組裝最終報告。工具分配決策是架構的主軸:coordinator 擁有 subagent 派遣工具和狀態管理;每個研究 subagent 擁有網路搜尋和摘要工具;兩者不應交叉污染。預期會有測試 coordinator 對比 subagent 工具集分工的題目、在最終報告輸出步驟使用 forced tool_choice 強制執行 schema 的決策,以及使用動態工具可用性防止 subagent 啟動其他 subagent 的決策。Customer-support-resolution-agent 情境也經常測試分配(退款 agent 應擁有 issue_refund 工具,還是只能提議退款?)以及 tool_choice(當置信度低時,強制呼叫 escalate_to_human)。
FAQ — 工具分配與 tool_choice 前五大問題
tool_choice: any 與 forced 工具物件有什麼差別?
tool_choice: any 表示「Claude 必須從目錄中呼叫某個工具,但我不指定哪個」。Claude 仍然在所有可見工具中行使選擇判斷。Forced 工具物件 { type: "tool", name: "<specific>" } 表示「Claude 必須呼叫這個特定工具」。在 forced 形式下,沒有選擇判斷。這個區別之所以重要,是因為 any 適用於需要工具呼叫但哪幾個都可以接受的情況,而 forced 適用於 schema 強制執行或確定性 pipeline 階段只需要一個特定工具的情況。將兩者視為可互換,是 CCA-F 任務 2.3 中出現頻率最高的陷阱之一——any 從不保證特定工具。
如何強制 Claude 輸出結構化 JSON?
CCA-F 標準模式結合三個機制:(1)定義一個 input_schema 符合你要的輸出 schema 的工具,(2)在工具定義上設 strict: true,(3)在 pipeline 的最後一個 turn,將 tool_choice 設為指名該工具的 forced 工具物件。這三者合起來提供三項保證:Claude 呼叫正確的工具、工具的輸入完全符合 schema,以及你的應用程式可以直接使用輸出,無需解析或驗證開銷。像「以符合此 schema 的 JSON 回傳」這樣的提示指令,因依賴提示合規而非 API 層級的執行,是較差的方案——程式化約束勝過提示指引。
一個 agent 應該有幾個工具?
考試不指定數字閾值,但方向毫無疑義:越少越好,前提是能涵蓋 agent 的角色。從 agent 的一句話角色描述出發,列舉必須可達的名詞與動詞,並為每個可達概念指派恰好一個工具。超出角色需求的目錄,會降低選擇準確性、膨脹 context 成本、擴大爆炸半徑。若 agent 需要大型工具集,考慮將它拆分為 coordinator 加 subagent、合併重疊工具,或使用動態工具可用性將可見工具縮限到當前工作流程階段。
在同一個 agentic loop 中,tool_choice 可以跨 turn 變換嗎?
可以,而且這是一個一級設計模式。tool_choice 在每次 Messages API 呼叫中設定,因此單一迴圈可以合理地在探索性調查 turn 使用 auto,切換到 forced 工具物件以強制執行符合 schema 的輸出 turn,再切換到 none 用於最終自然語言摘要 turn。這個模式用於結構化擷取 pipeline、多階段研究 agent,以及任何不同 turn 帶有不同行為約束的工作流程。動態 tool_choice 與動態工具可用性(per-call 變換 tools 陣列)是正交的;兩者可以一起使用,實現強力的狀態依賴約束。
如何防止 agent 呼叫它不應存取的工具?
從 agent 的 tools 陣列(或其 subagent allowedTools 清單)中移除那個工具。分配層的不可見性是一個硬性的結構邊界——工具無法被呼叫,因為 Claude 看不到它。「除非使用者是管理員,否則不要呼叫 delete_user 工具」這類提示指令,是依賴合規的軟性邊界,偶爾會設計性地失敗。為了縱深防禦,將分配時縮限範圍與工具實作內部的伺服器端授權結合,並(可選)加上可以在執行期否決特定呼叫的 PreToolUse hook。CCA-F 一致偏好硬性邊界答案,而非基於提示的存取控制。
延伸閱讀
- Define tools — best practices for tool descriptions and tool_choice: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/implement-tool-use
- Tool use with Claude — overview and agentic loop: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview
- Handle tool calls — tool_result format and error responses: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
- Create custom subagents — Claude Code Docs: https://docs.anthropic.com/en/docs/claude-code/sub-agents
- Strict tool use — schema-guaranteed output: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/strict-tool-use
- Writing tools for agents — Anthropic Engineering Blog: https://www.anthropic.com/engineering/writing-tools-for-agents
Related ExamHub topics: 工具介面設計 — 描述與邊界, Multi-Agent Orchestration 與 Coordinator-Subagent 模式, Subagent 呼叫、Context 傳遞與啟動, MCP Server 整合進 Claude Code.