API 開發
定義 tool schema 與接住 tool call:實作細節全走一遍
定義 tool schema 與接住 tool call:實作細節全走一遍
上一篇我們把工具函式寫好了,但 Claude 還不知道它的存在。這一篇處理兩件事:用 JSON schema 把工具介紹給 Claude,以及接住它發出的 tool call,把結果正確送回去。
這是 tool use 實作裡最容易踩坑的一段:訊息從單純的文字變成多區塊結構,id 要對得上,歷史要留完整。我們一步一步來。
你將學到什麼
schema 的三個組成
name、description、input_schema,各自扮演什麼角色。
讓 Claude 代寫 schema
貼上函式與官方文件,schema 草稿直接生出來。
讀懂多區塊訊息
text 區塊給人看,tool use 區塊給你的程式看。
tool result 的細節
id 對應、內容序列化、錯誤旗標,一個都不能錯。
Tool schema:Claude 要讀的說明書
JSON Schema 不是 AI 圈的發明,它是行之有年的資料驗證規格;AI 社群採用它,純粹因為拿來描述函式參數又方便又成熟。你可以把整份工具規格想成給 Claude 讀的說明書:它讀了,才知道世界上有這個工具、什麼時候該用、參數要怎麼填。一份完整的工具規格有三個部分:
- name:清楚好懂的工具名稱,例如
get_weather。 - description:這個工具做什麼、什麼時候該用、會回傳什麼。
- input_schema:描述函式參數的 JSON schema 本體。
description 是整份 schema 的靈魂
Claude 是靠 description 判斷「這個工具現在該不該用」的,所以它值得你多花幾句話:用 3 到 4 句說明工具做什麼、什麼情境該用、回傳什麼樣的資料,每個參數也各自給詳細描述。描述寫得含糊,Claude 就會在該用的時候不用、不該用的時候亂用。
我自己的經驗是,把 description 當成寫給一位新同事的交接文件來寫,效果最好:他沒看過你的程式碼,只能靠這幾句話決定要不要用這個工具、參數該填什麼。能讓人看懂的描述,Claude 通常也判斷得準。
偷吃步:請 Claude 幫你寫 schema
schema 不必從零手寫。把工具函式的程式碼貼給 Claude,附上 Anthropic 官方的 tool use 文件當脈絡,請它「為這個函式寫一份符合最佳實務的 tool calling JSON schema」,就能拿到一份格式正確的草稿。命名慣例上,建議 schema 變數跟著函式走:函式叫 get_current_datetime,schema 就叫 get_current_datetime_schema,一眼對得上。
get_current_datetime_schema = {
"name": "get_current_datetime",
"description": "Returns the current date and time formatted according to the specified format",
"input_schema": {
"type": "object",
"properties": {
"date_format": {
"type": "string",
"description": "A string specifying the format of the returned datetime. Uses Python's strftime format codes.",
"default": "%Y-%m-%d %H:%M:%S"
}
},
"required": []
}
}
想要更穩,可以從 anthropic.types 匯入 ToolParam 型別把 schema 包起來,讓型別檢查在開發階段就幫你擋掉格式錯誤。對功能來說不是必要,但 schema 拼錯欄位名這種錯誤,寧可在編輯器裡被抓到,也不要等到執行時才發現。
帶著工具呼叫 API:迎接多區塊訊息
messages = []
messages.append({
"role": "user",
"content": "What is the exact time, formatted as HH:MM:SS?"
})
response = client.messages.create(
model=model,
max_tokens=1000,
messages=messages,
tools=[get_current_datetime_schema],
)
在 API 呼叫加上 tools 參數後,回應的形狀就變了。Claude 決定用工具時,回傳的 assistant 訊息不再是單一文字,而是 content 清單裡裝著多個區塊:一個 text 區塊(給人看的說明,例如「我來幫你查現在的時間」),加上一個 tool use 區塊(給你的程式看的指令)。
tool use 區塊裡有四樣東西:追蹤用的 id、要呼叫的函式名稱、參數字典,以及型別標記 tool_use。
有一件事絕對不能忘:Claude 不會自己記得對話歷史,歷史是你在維護的。把這則多區塊訊息塞回歷史時,必須原封不動保留整個 content 結構,text 區塊和 tool use 區塊一個都不能少,後續的呼叫才有完整脈絡。
messages.append({
"role": "assistant",
"content": response.content
})
如果你之前寫過 add_user_message、add_assistant_message 這類輔助函式,這裡也要跟著升級:舊版大概假設內容永遠是一段純文字,現在它們得能接住多區塊的 content 結構,字串、區塊清單、完整訊息物件都要能塞進歷史。這一步不起眼,卻是後面多輪工具對話能不能順利跑起來的地基。
執行工具,把結果送回去
接下來換你動手:從 tool use 區塊取出參數字典。因為函式收的是關鍵字引數而不是字典,用 Python 的解包語法餵進去執行,再把結果用 tool result 區塊包好,放進一則 user 訊息送回。注意角色的安排:工具結果是以 user 的身分回給 Claude 的,因為對它來說,這是「外界告訴它的新資訊」,而不是它自己說過的話。
args = response.content[1].input
result = get_current_datetime(**args)
messages.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": response.content[1].id,
"content": "15:04:22",
"is_error": False
}]
})
- tool_use_id:必須和對應的 tool use 區塊的 id 完全一致。
- content:工具的輸出,序列化成字串。
- is_error:執行出錯時設為 True,讓 Claude 知道發生了什麼。
幾個一定會踩到的細節
- Claude 可能一次要求多個工具呼叫:例如一句話問兩題算術,就會回兩個 tool use 區塊。每個呼叫都有獨立 id,回傳結果時逐一對上,就算結果順序亂了也不怕。
- 送後續請求時,tools 參數還是要帶。就算你不預期它再呼叫工具,Claude 也需要 schema 才能理解歷史裡的工具往返。
- 此時完整的歷史應該是三段:原始 user 訊息、帶 tool use 區塊的 assistant 訊息、帶 tool result 區塊的 user 訊息。
把這些做對,送出後續請求,Claude 就會回傳最後一則訊息,把工具結果自然地織進回答裡:使用者問幾點,它回的不再是「我查不到」,而是帶著剛拿到的時間好好回答。到這裡,一次完整的 tool use 往返已經走通;下一篇我們讓它連續呼叫多個工具,處理更複雜的請求。
延伸學習
高效思維與腦內模擬:30 日練習與行動系統
每天一件事,三十天把「想到就做」換成「先在腦中跑一遍再動手」。六週依序練目標設定、腦內模擬、結果檢查、反饋與應變、知識萃取、總結與新目標,每天一課圖文,附可以直接填的練習表。週一給概念、週二實作、週三看案例、週四反思、週五收束,跟著節奏走就好,不必自己安排。
NT$ 1,599
知識變現切割地圖(高清版下載,不含講義)
《知識變現切割地圖》的高清完整版。一張圖把語氣、心理、內容、產品、再利用五層模組攤在同一個平面上,讓你回頭盤點已有內容、規劃新的轉化節奏。課程附上地圖本身的完整解說與應用指南,教你怎麼讀這張圖、從哪一層開始用。完整版 PDF 可下載,放大看細節不會糊。
NT$ 680

