一行 JSON,讓 Claude 從「只會聊天」變成「會查資料庫、打 API、寄信」。

這就是 Tool Use 在做的事。你寫好函式,告訴 Claude 這些函式叫什麼、吃什麼參數、幹什麼用——然後 Claude 自己決定什麼時候該呼叫哪個函式。你不用寫 if-else 判斷使用者意圖,不用做 NLP 解析。AI 自己看得懂。

聽起來很玄?其實整個機制就像你去一間餐廳。


餐廳類比:Tool Use 的運作邏輯

你坐下來,服務生(Claude)遞給你菜單。菜單上每道菜都有名字、食材說明、價格(這是你定義的 tools)。你跟服務生說「我今天想吃清爽一點的」(這是 user message)。

服務生不會把所有菜都端出來。他會根據你的需求,選一道適合的菜,寫在點菜單上交給廚房(這是 tool_use 回應)。廚房做完之後把菜端回來(這是 tool_result)。服務生看到菜來了,跟你說「這是您的凱薩沙拉,搭配的是今天的特選醬汁」(這是最終回答)。

整個流程就四步:

  1. 你給菜單(定義 tools)
  2. 服務生點菜(Claude 回傳 tool_use
  3. 廚房出菜(你執行函式,回傳 tool_result
  4. 服務生上菜(Claude 根據結果回答使用者)

就這樣。沒有更多了。


第一個完整範例:會查天氣的 AI

廢話不多說,直接上 code。這個範例用 Python Anthropic SDK,從定義工具到取得最終回答,完完整整跑一遍。

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import anthropic
import json

client = anthropic.Anthropic()

# 步驟 1:定義工具(菜單)
tools = [
{
"name": "get_weather",
"description": "取得指定城市的目前天氣。需要提供城市名稱,可選擇溫度單位。",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名稱,例如 Taipei, Taiwan"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "溫度單位"
}
},
"required": ["location"]
}
}
]

# 步驟 2:發送請求,讓 Claude 決定要不要用工具
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "台北現在天氣怎樣?"}]
)

print(f"Stop reason: {response.stop_reason}")

# 步驟 3:檢查 Claude 是否要呼叫工具
if response.stop_reason == "tool_use":
tool_block = next(b for b in response.content if b.type == "tool_use")
print(f"Claude 想呼叫:{tool_block.name}")
print(f"參數:{json.dumps(tool_block.input, ensure_ascii=False)}")

# 步驟 4:你來執行函式(這裡用假資料模擬)
weather_data = {"temperature": 28, "condition": "多雲", "humidity": 75}

# 步驟 5:把結果餵回去
final_response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=[
{"role": "user", "content": "台北現在天氣怎樣?"},
{"role": "assistant", "content": response.content},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": tool_block.id,
"content": json.dumps(weather_data, ensure_ascii=False)
}
]
}
]
)

print(final_response.content[0].text)

跑起來大概長這樣:

1
2
3
4
Stop reason: tool_use
Claude 想呼叫:get_weather
參數:{"location": "Taipei, Taiwan", "unit": "celsius"}
目前台北天氣多雲,氣溫 28°C,濕度 75%。建議帶把傘出門。

注意看——你從頭到尾沒有寫任何「如果使用者問天氣就呼叫天氣 API」的邏輯。Claude 自己從對話內容判斷該用哪個工具、填什麼參數。這是 Tool Use 最核心的價值。


工具定義的秘訣

工具定義裡最重要的欄位不是 name,不是 input_schema——是 description

Claude 用 description 來決定「什麼時候該用這個工具」。寫太短,Claude 會在不該用的時候用;寫太模糊,Claude 會在該用的時候跳過。官方建議每個工具至少寫 3-4 句描述。

踩坑經驗:我曾經把 description 寫成 "查天氣",結果使用者問「台北好玩嗎」Claude 也去查天氣。改成 "取得指定城市的目前天氣狀況,包含溫度、濕度、天氣描述。只在使用者明確詢問天氣資訊時使用" 之後就正常了。

另一個好東西是 input_examples——你可以直接給 Claude 看「正確的呼叫長什麼樣」:

1
2
3
4
5
6
7
8
9
10
11
12
tools = [
{
"name": "get_weather",
"description": "取得指定城市的目前天氣...",
"input_schema": { ... },
"input_examples": [
{"location": "Taipei, Taiwan", "unit": "celsius"},
{"location": "Tokyo, Japan", "unit": "celsius"},
{"location": "New York, NY"}
]
}
]

每個 example 大概吃 20-50 tokens,複雜的 100-200 tokens。不算貴,但對工具使用準確率的提升很明顯。


進階玩法

同時定義多個工具

一次可以給 Claude 很多工具,它會自己挑適合的:

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
tools = [
{
"name": "get_weather",
"description": "取得目前天氣...",
"input_schema": { ... }
},
{
"name": "calculate",
"description": "執行數學計算。支援加減乘除、次方、開根號。",
"input_schema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "數學表達式,例如 '(3 + 5) * 2'"
}
},
"required": ["expression"]
}
},
{
"name": "search_database",
"description": "搜尋內部資料庫的客戶資料...",
"input_schema": { ... }
}
]

使用者問「23 乘以 47 是多少」,Claude 會自動選 calculate。問天氣就選 get_weather。問客戶資料就選 search_database。你完全不用寫 routing 邏輯。

官方文件有個很妙的建議:把相關操作合併成一個工具,而不是拆成一堆小工具。與其做 create_prreview_prmerge_pr 三個工具,不如做一個 github_pr 工具加上 action 參數。工具越少,Claude 選錯的機率越低。

強制使用特定工具

有時候你就是要 Claude 用某個工具,不管它自己怎麼想:

1
2
3
4
5
6
7
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
tool_choice={"type": "tool", "name": "get_weather"},
messages=[{"role": "user", "content": "跟我聊聊台北"}]
)

tool_choice 有四種模式:

模式 行為
auto(預設) Claude 自己決定要不要用工具
any 強制使用某個工具,但 Claude 自己選哪個
tool 強制使用你指定的那個工具
none 禁止使用任何工具

要注意:用 anytool 的時候,Claude 不會在工具呼叫前加自然語言解釋。如果你想要 Claude 邊解釋邊用工具,保持 auto 然後在 prompt 裡引導比較好。

保證參數格式正確

加一個 strict: true,Claude 的工具呼叫就會 100% 符合你的 JSON Schema。不會再出現缺參數、型別錯誤的狀況:

1
2
3
4
5
6
7
8
tools = [
{
"name": "get_weather",
"description": "...",
"input_schema": { ... },
"strict": True
}
]

搭配 tool_choice: {"type": "any"} 一起用,你就有了雙重保證:一定會呼叫工具,而且參數格式一定對。在生產環境這個組合超好用。


串聯多輪工具呼叫:Agentic Loop

真正強大的用法不是單次呼叫,是讓 Claude 連續使用多個工具來完成複雜任務。這就是所謂的 agentic loop。

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
import anthropic
import json

client = anthropic.Anthropic()

def run_agent(user_message, tools, available_functions):
messages = [{"role": "user", "content": user_message}]

while True:
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
tools=tools,
messages=messages
)

messages.append({"role": "assistant", "content": response.content})

if response.stop_reason == "end_turn":
return next(
(b.text for b in response.content if hasattr(b, "text")),
""
)

tool_results = []
for block in response.content:
if block.type == "tool_use":
func = available_functions[block.name]
result = func(**block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result, ensure_ascii=False)
})

messages.append({"role": "user", "content": tool_results})

這個 run_agent 函式會一直跑,直到 Claude 覺得資訊夠了、不再呼叫工具為止。你可以丟一個複雜的問題給它——「查台北天氣,算攝氏轉華氏,然後告訴我適不適合跑步」——它會自己串起多個工具呼叫來回答。


Tool Use 跟 MCP 的關係

如果你聽過 MCP(Model Context Protocol),可能會搞混。區分很直白:

Tool Use 是引擎,MCP 是公路系統。

Tool Use 是 Claude API 內建的底層機制——你定義工具、Claude 呼叫、你回傳結果。它是點對點的,你跟 Claude 之間的直接溝通。

MCP 是建在 Tool Use 之上的開放協定。它標準化了「工具要怎麼被發現、怎麼被描述、怎麼被連接」的流程。有了 MCP,你寫一個 Server,所有支援 MCP 的 AI 都能用你的工具——不只 Claude,Cursor、Copilot、Kiro 都行。

所以學 Tool Use 是基本功。不管你之後要直接寫 API 整合、還是走 MCP 生態系,Tool Use 的運作原理都是一樣的。


跟其他 AI 的 Function Calling 比較

OpenAI 的 Function Calling 跟 Claude 的 Tool Use 概念幾乎一樣——定義函式、AI 決定呼叫、你執行回傳。主要差異在 API 格式:OpenAI 用 functions 參數和 function_call 回應,Claude 用 tools 參數和 tool_use content block。

Google Gemini 也有 Tool Use,格式又略有不同,但核心概念一致。

從遷移的角度來看,三家的工具定義都用 JSON Schema,所以 schema 本身是可以共用的。需要改的主要是 API 呼叫的 wrapper code。

有個值得注意的差異:Claude 的 strict: true 模式保證回傳的參數 100% 符合 schema。在需要高可靠性的生產環境(金融交易、醫療查詢),這個保證很值錢。


收尾

Tool Use 改變的不是 AI 能做什麼——是你怎麼設計系統。

以前做一個「幫使用者查天氣然後建議穿搭」的功能,你得寫意圖辨識、寫 routing、寫 fallback。現在你只需要定義兩個工具(天氣 API + 穿搭建議 API),Claude 自己串起來。

你的程式碼從「控制流程」變成「提供能力」。不再告訴 AI「先做 A 再做 B」,而是告訴它「你有 A 和 B 可以用」,讓它自己決定順序和組合。

這種轉變的後果比表面看起來深。當 AI 能自己選工具、自己串流程,你寫的不是 app——你寫的是 AI 的工具箱。工具箱設計得好不好,決定了 AI 能不能真正幫上忙。

好的工具定義比好的 prompt 更重要。因為 prompt 是一次性的,工具是可重用的。

參考來源:Tool use with Claude - Anthropic Docs
參考來源:Define tools - Anthropic Docs
參考來源:Handle tool calls - Anthropic Docs