简

理解 Tool Search、Programmatic Tool Calling 與 Tool Use Examples:按需加載工具定義,用代碼組織調用和處理數據,再用示例説明覆雜參數的用法。

Advanced Tool Use:Agent 怎樣高效發現和調用工具?
26 分鐘
5154 字

上一篇關注工具接口的質量:怎樣劃分能力,怎樣寫名稱、參數和返回值,以及怎樣驗證 Agent 能否用對。工具本身設計清楚後,還有另一組問題:工具定義要不要一次全部交給模型?連續查詢得到的大量數據,要不要每次都經過模型?複雜參數的正確用法,又怎樣讓模型看得更直觀?

Anthropic 的 《Introducing advanced tool use》介紹了三個機制。它們改變的不是同一個環節:

  • Tool Search Tool: 先發現相關能力,再按需加載工具定義。
  • Programmatic Tool Calling: 讓代碼組織調用、處理中間數據,再把必要結果交給模型。
  • Tool Use Examples: 用有效調用樣例,補充參數組合與使用慣例。

下面繼續用一個假設的訂單排查場景:查清某位客户最近兩週的訂單是否存在重複扣款,並列出需要跟進的訂單。已有 orders_search 和 orders_get_payment_context 兩個查詢工具;現在把它們放進更大的工具庫,也讓排查涉及更多訂單。例子用於解釋機制,不對應一套已上線的訂單系統。

一、工具規模擴大後有哪些問題h2

假設 Agent 接入訂單、支付、物流、客服和內部知識庫。工具定義不只有名稱,還包含説明、參數 Schema 和示例。如果把整個目錄一次交給模型,即使任務只涉及付款排查,物流和知識庫的定義也會佔據輸入空間。

找到工具以後,問題還沒有結束。一次訂單查詢可能返回多頁,每筆訂單又需要補查支付記錄。如果模型每看到一批數據就再決定一次“取下一頁”“查下一筆”,大量工作其實只是重複執行已經確定的步驟。

還有一種錯誤與規模無關:模型選對了工具,參數也滿足類型約束,卻沒有遵守正確的調用約定。例如翻頁時沿用了游標,卻改了原來的客户或時間範圍。

我把這三種開銷分別理解為:發現能力的開銷、組織執行的開銷,以及理解用法的開銷。 因而,解決方案也不只是繼續改工具名稱,或把工具合併得更大。

發生問題的環節訂單排查中的表現對應機制
定義進入模型之前無關服務的工具説明佔據輸入Tool Search Tool
調用與數據處理過程中翻頁、補查和篩選反覆經過模型Programmatic Tool Calling
模型組織參數時參數合法,但組合或續查方式不合適Tool Use Examples

二、Agent 怎樣發現、調用和理解工具h2

三個機制分別作用於定義加載、調用執行和參數使用,可以沿着同一條訂單排查路徑理解。

1. Tool Search:按需發現和加載工具定義h3

工具目錄與定義加載

在訂單排查任務裏,模型首先需要的是“按客户和時間查訂單”“取得訂單的付款證據”,而不是所有服務的完整接口説明。

Tool Search 在這裏增加了一次發現過程:

用户提出付款排查任务
↓
模型搜索相关工具
↓
搜索结果给出工具引用
↓
加载匹配工具的完整定义
↓
模型按照定义调用订单与支付工具

搜索工具返回的是可調用能力的引用,不是訂單數據。 找到 orders_search 並不等於執行了訂單查詢;模型仍然需要讀懂它的輸入要求,組織參數,再發出業務工具調用。

Anthropic 的實現通過 defer_loading 延後向模型呈現工具定義。工具庫仍由應用提供,模型起初只看到搜索入口以及沒有延後加載的工具;找到的引用隨後展開成完整定義。這區分了兩件容易混在一起的事:應用知道有哪些工具,不代表模型當前已經讀過它們。 Tool Search 文檔

例如,訂單工具可以被設為延後加載,而少量高頻入口直接保留。無需把所有能力一視同仁:每次任務都需要的工具,再搜索一次反而增加步驟。

發現過程也不意味着模型偷偷讀完了整個目錄。平台提供正則匹配和 BM25 檢索等搜索入口,在工具名稱、説明及參數描述中尋找匹配能力。前者適合明確的文本模式,後者可以接收自然語言查詢;應用也可以提供自己的搜索實現。目錄如何檢索,與模型拿到定義後如何調用,是兩層工作。

定義維護、適用條件與執行授權

defer_loading 改變的是定義何時進入模型上下文,不是讓應用不再維護 Schema,也不保證整個 API 請求只發送一個小目錄。對 Anthropic 的工具搜索接口,完整工具定義仍需隨請求提供;被推遲的是模型側的加載。

工具是否能被找到,也繼續依賴上一篇討論的名稱與説明。一個叫 query、描述只有“查詢信息”的接口,即使進入搜索系統,也很難準確表達它能按客户檢索訂單。

因此,Tool Search 不會替代 Tool Design。它只是把清晰的能力描述變成可檢索目錄,讓當前任務先接觸相關的那部分。

搜索還增加了一次交互,也可能漏掉需要的能力。如果工具很少、定義很短,或者任務本來就要使用其中大多數工具,直接加載可能更簡單。判斷收益時,應同時看加載量、發現成功率和額外耗時,而不是隻看工具總數。

最後,“被搜索出來”不等於“被允許執行”。 搜索負責發現能力,實際調用仍應經過應用原有的執行檢查。

2. Programmatic Tool Calling:用代碼組織調用與處理數據h3

工具橋接與執行流程

訂單排查有一段可以明確寫成程序的過程:按固定條件翻完訂單頁,逐筆取得付款證據,篩選需要跟進的記錄,彙總失敗項。這些步驟不必每次都讓模型重新判斷。

Programmatic Tool Calling(PTC)允許模型先寫出調用程序,再由代碼執行環境運行。程序可以使用循環、條件和數據處理邏輯,把業務工具當作可調用能力組合起來。

這裏也要接上 Agent Loop 的邊界:模型寫出調用代碼,仍不等於模型親自查詢了數據庫。 在 Anthropic 的 PTC 流程中,代碼運行到客户端工具調用時會等待;應用收到請求,執行真正的業務工具並返回結果,程序再繼續。中間結果交給運行中的代碼處理,程序輸出才回到模型。 PTC 文檔

圖 1 · 程序化調用:工具結果先回到代碼,再把必要輸出交給模型
代碼組織工具調用,模型接收程序輸出 模型生成程序。代碼請求客户端執行業務工具,結果回到代碼進行處理;需要繼續時再次調用,完成後彙總輸出交給模型。 提交程序 請求執行 結果回到代碼 繼續調用 完成 輸出回到模型 模型生成程序客户端執行工具運行調用代碼處理工具結果 確定調用與處理邏輯查詢真實業務數據發出請求,等待返回分頁、過濾與彙總 模型繼續判斷輸出必要證據 解釋結果與回應用户範圍、候選與失敗項

這不是“一次模型調用,所有工作就免費完成了”。業務查詢次數、執行時間以及客户端處理請求的往返仍然存在。減少的是部分中間模型推理,以及把大量原始數據反覆放進模型上下文的需要。

普通工具調用也可以在一次模型輸出中提出多個獨立請求,並不天然等於“一次只能調用一個工具”。PTC 更進一步:把可程序化的循環、分支和數據加工,放進一段持續執行的代碼中。

訂單排查中的模型與代碼分工

先約定一個簡單篩選條件:訂單存在兩個及以上不同的成功扣款記錄,且每筆金額都等於訂單金額,就列為需要跟進的候選。它只是排查入口,不直接證明重複扣款,更不自動決定退款。

下面是機制偽代碼。tools.call 表示執行環境提供的工具橋接,find_candidates 是本地篩選函數;它們不是 Anthropic SDK 的實際方法。

query = {
"customer_id": "cus_demo_42",
"created_from": "2026-09-28T00:00:00+08:00",
"created_before": "2026-10-12T00:00:00+08:00",
"page_size": 20,
}
candidates = []
failed_order_ids = []
checked_orders = 0
seen_cursors = set()
while True:
page = await tools.call("orders_search", query)
checked_orders += len(page["orders"])
for order in page["orders"]:
try:
evidence = await tools.call(
"orders_get_payment_context",
{"order_id": order["order_id"]},
)
except ToolExecutionError:
failed_order_ids.append(order["order_id"])
continue
candidates.extend(find_candidates(order, evidence))
if not page["has_more"]:
break
cursor = page["next_cursor"]
if not cursor or cursor in seen_cursors:
raise IncompleteScanError("无效或重复的分页游标")
seen_cursors.add(cursor)
query = {**query, "cursor": cursor}
print({
"checked_orders": checked_orders,
"candidates": candidates,
"failed_order_ids": failed_order_ids,
"complete": not failed_order_ids,
})

這裏值得關注的不是代碼長短,而是數據流:付款記錄先進入程序,程序完成明確的篩選,模型接收候選證據與掃描範圍,而不是逐筆閲讀全部流水。發生查詢失敗時,也把未核對的訂單帶回來,不能悄悄當成“沒有異常”。

find_candidates 應保留訂單 ID、付款記錄 ID、金額與幣種、退款狀態等後續判斷依據。模型據此解釋哪些訂單需要進一步核對;只返回一個 true,雖然短,卻把判斷依據一起丟掉了。

這個分工同樣説明了 PTC 的適用邊界。固定條件的篩選、分頁、關聯和統計適合交給代碼;證據不足、業務含義不明確時,應把問題交回模型或人工判斷。若任務只是查一筆訂單,生成並運行程序可能比直接調用更繞。

執行結果與完整性檢查

PTC 省去的是不必要的數據中轉,不是正確性檢查。模型生成的代碼仍可能漏掉最後一頁、錯誤處理退款,或者把不同幣種金額直接相加。

返回格式也因此更重要。模型有時能從一段文字裏理解付款狀態,代碼卻需要知道結果是數組還是對象、金額單位是什麼、失敗怎樣表示。讓程序處理工具結果,必須先提供穩定且有説明的輸出約定,而不是把一段隨意變化的自然語言當作接口。

同樣,如果程序最後把所有原始結果全部打印出來,大量數據還是會回到模型,原本的收益也就減弱了。合理輸出應同時滿足兩件事:比原始數據更聚焦,又足以支撐結論。

我會保留掃描範圍、候選證據、失敗項和完成狀態,而不只保留一句“發現三筆異常”。這樣,模型既能組織回應,也能看見結論的邊界。

3. Tool Use Examples:用示例説明參數組合h3

Schema 與調用示例

orders_search 的 Schema 已經説明 customer_id 是字符串,page_size 是有範圍的整數,cursor 是可選參數。説明文字還規定:第一頁省略游標;續查時沿用返回的游標,並保持查詢條件一致。

這些要求可以寫清楚,但模型面對實際調用時,仍要把它們組合成一個輸入對象。Tool Use Examples 用少量有效樣例,把這種組合直接呈現出來。

在 Anthropic 的工具定義中,input_examples 與 input_schema 同級,每個樣例都必須符合 Schema。以下只是加到上一篇工具定義上的字段片段,不是完整請求: Tool Use Examples 文檔

{
"input_examples": [
{
"customer_id": "cus_demo_42",
"created_from": "2026-09-28T00:00:00+08:00",
"created_before": "2026-10-12T00:00:00+08:00"
},
{
"customer_id": "cus_demo_42",
"created_from": "2026-09-28T00:00:00+08:00",
"created_before": "2026-10-12T00:00:00+08:00",
"page_size": 20,
"cursor": "cursor_demo_page2"
}
]
}

第一項展示最小查詢:沒有 cursor,page_size 省略時由工具實現使用默認值 20。第二項展示續查:假設上一頁返回了 cursor_demo_page2,就保留原來的客户、時間範圍和實際頁大小,再帶上這個游標。樣例中的 ID 和游標只是演示值,實際調用必須使用查詢得到的真實值。

這比堆十個只有客户 ID 不同的樣例更有價值,因為它展示的是兩種不同使用方式,而不是同一種結構的重複。

規則校驗與示例選擇

不能簡單地説“JSON Schema 只能約束類型,表達不了參數關係”。Schema 也能描述枚舉、條件和依賴;工具實現則能校驗更具體的業務規則。示例的作用,是把正確調用長什麼樣展示給模型,不是替代這些機制。

例如,“結束時間晚於開始時間”應該在説明中明確,並由執行端檢查,不能只在樣例裏默默出現。游標是否屬於當前查詢,也不能因為模型見過示例就不再驗證。

更復雜的工具可能有嵌套過濾條件、幾組可選參數,或不同操作對應不同字段。此時,最小輸入、常用組合和容易誤用的邊界樣例,能夠幫助模型理解調用慣例。即使工具庫只有幾個接口,這個機制也有用。

示例本身也會佔用輸入空間。因此,重點不是給每個工具配一大串樣例,而是為真正有歧義的組合提供少量有區分度的示範,並保證它們與當前定義一致。

三、三種機制怎樣組合與驗證h2

把三個機制放回同一個訂單任務,可以看到一條完整但不必每次都走滿的路徑:

  1. 發現能力: 在大目錄中找到訂單查詢與付款證據工具,加載相關定義。
  2. 理解用法: 依據説明、Schema 和樣例,確定時間範圍、客户 ID 與分頁方式。
  3. 組織執行: 若涉及多頁和大量補查,用代碼承接重複調用與篩選。
  4. 返回證據: 將掃描範圍、候選訂單與未完成項交給模型,形成可解釋的回應。

它們不是必須綁在一起的套餐。工具很多、每次只調用一兩次,可能主要需要搜索;工具不多但數據量很大,可能主要需要程序化調用;只有一個接口但參數組合複雜,也可能值得加示例。

這也把第五篇和第六篇的邊界區分開了:前者改善模型面對的接口,後者改善模型接觸接口和處理調用的過程。 如果工具説明本來就模糊,或者結果字段缺少業務含義,換成搜索或代碼執行仍然會遇到問題。

是否更高效,還要回到任務中比較。可以沿用同一份訂單數據與目標,分別觀察:

機制不只看什麼還要檢查什麼
Tool Search初始定義是否變少必需工具是否被找到,額外發現步驟是否值得
PTC中間數據是否減少總耗時、真實調用次數、分頁完整性與篩選結果
Examples參數格式是否正確複雜組合是否用對,樣例增加的輸入是否有收益

對於這個案例,候選訂單是否正確、失敗項是否被保留,比單看某次 token 消耗更重要。更少的輸入與模型輪次應服務於任務完成,而不是掩蓋漏查。

從這裏看 Context Engineering,也有了具體入口:哪些定義值得現在加載,哪些中間數據需要讓模型看到,哪些證據不能在壓縮結果時丟掉? 工具使用機制已經在影響上下文的內容,但上下文質量還包括任務歷史和其他信息的組織,並不等於把工具輸出一律縮短。

幾個關鍵問題,串起發現、調用與參數用法h2

工具越多,就越應該使用 Tool Search 嗎?

工具總數只是一個信號。更重要的是定義佔用多少輸入、當前任務通常需要多少能力,以及搜索能否穩定找到它們。大量工具中每次只用很少一部分,按需加載更有價值;如果大多數工具每次都需要,搜索反而可能增加步驟。高頻工具直接保留,也可以和延後加載組合。

搜索到工具後,模型是不是已經拿到了業務數據?

不是。發現階段得到的是工具引用及隨後加載的定義,回答“有什麼能力可以使用”。訂單、付款等業務數據,要在模型按定義發出實際調用、業務工具執行之後才能獲得。發現成功與執行成功是兩個不同檢查點。

PTC 和普通並行工具調用有什麼不同?

普通調用可以讓模型一次提出多個獨立工具請求,再把結果交回模型。PTC 則讓代碼表達連續調用、循環、條件和數據處理,結果先回到程序,模型不必介入每個中間步驟。兩者都可能並行執行獨立查詢;區別不只在併發,而在誰組織後續步驟、誰先處理返回數據。

為什麼 PTC 不能簡單理解成“一次調用替代很多次調用”?

程序內部仍會發出真實工具請求,客户端仍要執行並返回結果。可能減少的是模型推理輪次與進入上下文的中間數據,不一定減少業務調用次數。重複查詢、錯誤循環和低效算法甚至會增加工作量,所以需要同時檢查代碼行為與任務結果。

有了調用示例,Schema 和參數校驗還重要嗎?

重要。Schema 提供結構約束,説明明確語義,執行端檢查實際條件,示例幫助模型看懂有效組合。示例不是強制規則:它既不能保證模型照做,也不能阻止無效輸入被執行。幾者要表達一致的接口,而不是互相替代。

只把最終彙總交給模型,會不會漏掉重要信息?

會,因此輸出設計不能只追求短。訂單排查至少需要保留核對範圍、候選的付款證據、查詢失敗項和完成狀態。把無關流水留在代碼裏,與把支撐判斷的證據刪掉,是兩回事。模型需要的是足夠得出可靠結論的信息,不是最多或最少的信息。

參考資料h2