上個月我在幫一個客服系統接 AI,工具列表長到我自己看了都頭痛——查訂單、退款、修改地址、查庫存、轉人工、寄信、查物流……加起來 47 個 function definition。每次 API 呼叫,光是把這些工具塞進 prompt 就吃掉 8,000 多個 token。使用者問一句「我的包裹到哪了」,模型還得先讀完退款政策和寄信格式才能回答。

GPT-5.4 在三月初發布時帶來的 Tool Search 機制,直接解決了這個問題。

問題的根源:你付錢讓模型讀它用不到的東西

傳統的 function calling 很直觀——你把所有工具的 JSON schema 丟進 tools 陣列,模型看完後決定要呼叫哪個。問題是,模型不管用不用,都得讀。

算一筆帳:

1
2
3
一個工具定義 ≈ 150-300 tokens
30 個工具 ≈ 4,500-9,000 tokens
每次對話 10 輪 ≈ 45,000-90,000 tokens 花在重複讀工具定義

這些 token 不產生任何價值。它們只是讓模型知道「我有這些能力」,但 90% 的對話只會用到 2-3 個工具。

更糟的是,工具太多會讓 prompt cache 失效。每次你改動一個工具的定義,整個 cache 就得重建。

Tool Search 怎麼運作

核心概念很簡單:模型一開始只拿到工具的「目錄」(名稱和簡短描述),需要的時候再查完整定義。

運作流程:

  1. 你把工具標記為 defer_loading: true
  2. 模型收到的是輕量清單——每個工具只有名稱和一行描述
  3. 使用者問問題時,模型根據描述判斷需要哪些工具
  4. 模型發出 tool search 請求,系統才載入完整的參數定義
  5. 模型用載入的工具完成任務

OpenAI 用 Scale 的 MCP Atlas benchmark 測過——250 個任務、36 個 MCP server,Tool Search 省下 47% 的 token,準確率不變。

實際怎麼用

最小範例:延遲載入單一函式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from openai import OpenAI

client = OpenAI()

response = client.responses.create(
model="gpt-5.4",
input="我的訂單 ORD-12345 到哪了?",
tools=[
{
"type": "function",
"name": "track_order",
"description": "用訂單編號查詢物流狀態和預計到貨時間",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string"}
},
"required": ["order_id"]
},
"defer_loading": True # 關鍵:延遲載入
},
{
"type": "function",
"name": "process_refund",
"description": "處理退款申請,需要訂單編號和退款原因",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string"},
"reason": {"type": "string"}
},
"required": ["order_id", "reason"]
},
"defer_loading": True
}
],
tool_search=True
)

使用者問物流,模型只會載入 track_order 的完整 schema。process_refund 的參數定義從頭到尾沒被讀過。

進階用法:Namespace 分組

兩個工具看不出差異。真正的價值在你有 30+ 工具的時候——用 namespace 分組:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
tools = [
{
"type": "namespace",
"name": "order_management",
"description": "訂單相關操作:查詢、修改、取消、退款",
"functions": [
{"name": "get_order", "description": "查詢訂單詳情", "defer_loading": True, "parameters": {... }},
{"name": "cancel_order", "description": "取消未出貨訂單", "defer_loading": True, "parameters": {... }},
{"name": "modify_address", "description": "修改收貨地址", "defer_loading": True, "parameters": {... }},
{"name": "process_refund", "description": "處理退款", "defer_loading": True, "parameters": {... }},
]
},
{
"type": "namespace",
"name": "logistics",
"description": "物流追蹤:包裹狀態、預計到貨、配送異常",
"functions": [
{"name": "track_package", "description": "追蹤包裹即時位置", "defer_loading": True, "parameters": {... }},
{"name": "report_issue", "description": "回報配送異常", "defer_loading": True, "parameters": {... }},
]
},
{
"type": "namespace",
"name": "customer_support",
"description": "客服操作:轉接人工、滿意度調查、工單建立",
"functions": [
{"name": "transfer_agent", "description": "轉接人工客服", "defer_loading": True, "parameters": {... }},
{"name": "create_ticket", "description": "建立客服工單", "defer_loading": True, "parameters": {... }},
{"name": "send_survey", "description": "發送滿意度調查", "defer_loading": True, "parameters": {... }},
]
}
]

使用者問「包裹到哪了」→ 模型只載入 logistics namespace 裡的函式。order_managementcustomer_support 完全不碰。

OpenAI 的建議是每個 namespace 不超過 10 個函式。這不是硬限制,但超過後模型挑選工具的準確率會下降。

搭配 MCP Server

Tool Search 和 MCP 是天生搭配。MCP server 本身就是一組工具的集合,直接延遲載入整個 server:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
tools = [
{
"type": "mcp",
"server_label": "inventory",
"server_url": "https://mcp.example.com/inventory",
"description": "庫存管理系統:查詢庫存、預留庫存、庫存異動歷史",
"defer_loading": True
},
{
"type": "mcp",
"server_label": "crm",
"server_url": "https://mcp.example.com/crm",
"description": "客戶關係管理:客戶資料、互動紀錄、標籤管理",
"defer_loading": True
}
]

模型看到的只有兩行描述。背後可能各有 20 個 endpoint,但在用到之前,一個 token 都不浪費。

什麼時候該用、什麼時候不用

適合用的場景:

  • 工具超過 10 個的應用(token 節省開始有感)
  • 多租戶系統,不同客戶有不同工具集
  • 整合多個 MCP server 的 agent 系統
  • 對話輪數多的應用(累積節省可觀)

不需要的場景:

  • 工具在 5 個以內,定義也短——延遲載入的 overhead 不值得
  • 每次對話都會用到所有工具(比如一個專門做資料分析的 agent,固定用 query + chart + export 三件套)
  • 用的不是 GPT-5.4(目前只有這個模型支援)

幾個容易踩的坑

描述寫太爛,模型找不到正確工具。 Tool Search 的準確度完全取決於你怎麼寫 description。「處理訂單」太模糊,「取消未出貨的訂單並觸發退款流程」才夠精確。模型是靠描述做語意搜尋,不是靠函式名稱。

Namespace 太大。 把 30 個函式塞進一個 namespace 等於沒分。保持每個 namespace 3-8 個函式,讓模型能快速定位。

混用延遲和非延遲工具時的 cache 行為。 非延遲的工具定義會進 prompt cache,延遲的不會。如果你有 3 個核心工具每次都用,把它們設成非延遲,其他的延遲載入。這樣核心工具享受 cache,其餘的享受 token 節省。

忘記處理 tool_search 事件。 如果你用 streaming,Tool Search 會產生一個新的事件類型。確認你的事件處理邏輯有覆蓋到,不然會 silent fail。

這個模式的更大意義

Tool Search 不只是一個省 token 的技巧。它反映了 AI 應用架構正在從「靜態配置」走向「動態發現」。

傳統做法是預先定義好模型能做什麼。Tool Search 讓模型在執行時才決定需要什麼能力。這和微服務架構裡的 service discovery 是同一個思路——你不需要在啟動時知道所有服務的位置,runtime 去問 registry 就好。

對開發者來說,這意味著你可以建造工具數量不受限的 agent 系統。一個企業級 agent 接 50 個 MCP server、每個有 10 個 endpoint,總共 500 個工具——傳統做法要 75,000-150,000 tokens 只是為了告訴模型「你能做什麼」。Tool Search 把這個數字壓到幾千。

當然,前提是你的 namespace 分得好、描述寫得準。垃圾進、垃圾出,這條鐵律在 AI 工具設計上一樣成立。