跳到內容

調整代理的工具情境

本指南談的是兩層式工具介面周邊的實務工作:查看一次執行送出了什麼、加以變更,以及診斷一個伸手拿錯工具的代理。若要了解它為何這樣運作,請閱讀工具情境與提示快取。

開啟一段對話,然後點一下對話標題列中的情境用量指示器。它會在不執行任何東西的情況下,重建下一次派送將會送出的確切介面。查看更多(或 /context 指令)會開啟完整的情境瀏覽器,讓你逐一檢視每個工具。

這裡有兩類區段值得注意:

  • 工具定義 與 MCP 與動態工具 —— 常駐集合,並附上每個工具實際的 token 成本。
  • 隨需載入的工具 —— 隨需載入索引。每個項目只被計入它的名稱,因為請求帶的也只有名稱;展開其中一項仍會顯示完整的描述與結構描述,讓你能看見若這次執行把它拉進來,原本會付出多少成本。

若隨需載入區段是空的,就表示這部伺服器已關閉隨需載入。請在 cc_server CLI 上檢查 --tool-deferral。

常駐集合是政策,而不是設定 —— 它位於 ModeToolPolicy(packages/cc_domain/lib/features/mcp/domain/value_objects/mode_tool_policy.dart),並套用於每一次執行:

  • residentBuiltins —— 檔案與 shell 詞彙。
  • residentDiscovery —— search_tools 與 list_my_tools。請勿移除這些工具;代理就是靠它們觸及所有其他工具。
  • residentMcpTools —— 少數值得在每次請求中都帶著其結構描述的 Control Center 工具。
  • 每個模式各自的區塊,用於某個模式幾乎每個回合都會用到的工具。

編輯它時有兩條規則:

只有在多數執行都會用到某個工具時,才把它加入。 每個名稱都會在每一次執行的每一個請求中,永遠付出它的結構描述成本。一個用到的時候很重要、但整體而言很少用到的工具,該放在隨需載入的那一半 —— 代理仍然找得到它。

使用工具的真實名稱。 一個對不到任何工具的常駐名稱是沒有作用的:沒有錯誤、沒有警告,那個工具就只是被隨需載入。test/tooling/resident_tool_names_test.dart 會抓到這種情況,也會把每個模式的常駐工具數壓在 40 個以下,而這正是這項練習的重點 —— 超過那個區間之後,工具選擇的準確度會明顯變差。

模式必要與被釘選的動詞會自動加入,所以你永遠不需要列出模式自己的輸出動詞。

當代理用錯了工具,或聲稱它做不到某件事時,請判斷究竟是以下三種情況中的哪一種。

每次執行都會記錄它載入了哪些隨需載入工具,以及是什麼觸發了載入 —— 直接以名稱呼叫,或是一次 search_tools 查詢。開啟該次執行的事件串流(設定 → 工作區 → 代理 → 該代理 → 日誌 → 檢視),並尋找 [harness] loaded N deferred tool(s)。

  • 沒有任何記錄,而代理說這項能力不存在 —— 它根本沒找過。那是提示的問題,而不是檢索的問題:隨需載入索引就在它的系統提示中,並附有一道指示:除非搜尋已回傳空結果,否則不得宣告某項能力不存在。
  • 有搜尋的記錄,但什麼都沒載入 —— 這是真正的檢索未命中。請前往步驟 2。
  • 有載入工具,卻用錯了 —— 它找到的工具彼此太相似。請前往步驟 3。

search_tools 會比對名稱、描述與引數名稱。未命中幾乎總是意味著描述裡沒有代理所用的那些詞。

把它們加進去。描述就是檢索索引,因此要加長,而不是刪減 —— 寫下操作者實際會輸入的詞彙(「assign」、「hand off」、「give to」),而不只是內部的名詞。為了省 token 而刪減描述,會同時賠上搜尋命中與選擇準確度,而相對於結構描述,它省下的幾乎微不足道。

如果正確的工具存在、但排名很低,那正是 limit 引數的用途;工具本身的描述會告訴代理,當一次搜尋看起來很接近卻沒命中時,就把範圍放寬。

如果兩個工具的描述,對一個原本不知道其中差異的人來說讀起來一模一樣,那麼模型就是在猜。請把它們合併成一個工具,並加上一個可區辨的引數。

ticket_relation 與 ticket_pr_link 就遵循這個模式:兩者都透過一個可區辨的引數來處理連結與取消連結。在單一呼叫內部、帶著請求的完整情境所做的選擇,會比在兩個相像的描述之間所做的選擇更可靠。

當工具需要不同的核准關卡、不同的稽核或不同的呈現方式時,就讓它們保持分開 —— 這些都是合併會讓你付出真實代價的理由。

快取命中率會顯示在 可觀測性 → 洞察 中,名稱為快取率。健康、長時間執行的對話會維持在高檔;如果它持續偏低,就表示有東西在每個回合重寫前綴。

常見原因,依可能性排序:

  • 提示前段任何不具決定性的東西。 一個時間戳記、一個請求 id,或一個以不同順序走訪的集合,都足以造成。
  • 對話中途更換模型或調整推理力度。 兩者都會改變前綴。子代理在這裡特別容易出錯:為了省錢而用較低的推理力度執行子代理,在失去的快取共用上所付出的代價,可能比它省下的還多。
  • 頻繁的壓縮。 壓縮本來就會改寫歷史,所以它的代價是真的;解法是壓縮得少而深,而不是頻繁而淺。

用 --tool-deferral=off 關閉隨需載入,是一個有效的 A/B 手法,可用來釐清某個行為變化是否源自兩層式工具介面。它會精確重現隨需載入出現之前的請求,因此如果在關閉之後行為依舊,那麼這個介面就不是原因。