所有入門單元免費開放 · 課程內容持續更新中

定義工具:寫給模型看的說明書

模型怎麼知道有哪些工具可以用、什麼時候該用?全靠你寫的工具定義。這堂課教你寫出名稱清楚、說明完整、參數明確的工具,並看看模型怎麼回應。

第 11.2 堂約 14 分鐘

上一堂課我們說,工具就像遞給模型的遙控器。但模型怎麼知道遙控器上每個按鈕是做什麼的?答案是:你要寫說明書給它看。

這份說明書寫得好不好,會直接決定 Agent 好不好用。說明不清楚,模型就會用錯工具、帶錯參數,或者乾脆不用。

工具定義的三個部分

工具定義包含 name、description、input_schema 三部分;模型讀完後回傳一個 tool_use 區塊,包含工具名稱與參數

你寫左邊的說明書,模型回傳右邊的請求。中間沒有任何程式被執行。

在 Python 裡,一個工具就是一個字典:

read_file_tool = {
    "name": "read_file",
    "description": (
        "讀取工作資料夾中一個文字檔的完整內容。"
        "當你需要知道某個檔案寫了什麼時使用。"
        "path 是相對於工作資料夾的路徑,例如 notes/todo.txt。"
        "回傳檔案的文字內容;檔案不存在時回傳錯誤訊息。"
    ),
    "input_schema": {
        "type": "object",
        "properties": {
            "path": {
                "type": "string",
                "description": "要讀取的檔案路徑,相對於工作資料夾",
            }
        },
        "required": ["path"],
        "additionalProperties": False,
    },
}

一個一個來看。

name:簡短、動詞開頭

用英文小寫加底線,像函式名稱一樣,例如 read_file、search_orders、send_email。看名字就知道它會「做什麼動作」。

description:最值得花時間的地方

模型決定要不要用工具時,主要就是看這一段。好的說明要回答四個問題:

  1. 它做什麼? 讀取一個文字檔的內容。
  2. 什麼時候用? 需要知道檔案內容時。
  3. 參數怎麼給? 相對路徑,並舉一個例子。
  4. 會回傳什麼? 包含出錯時會怎樣。

比較看看:

寫法 問題
"讀檔" 讀哪裡的檔?路徑怎麼寫?讀不到會怎樣?模型只能猜
上面範例的寫法 用途、時機、參數格式、回傳內容都說清楚了

把模型想成一位第一天上班的新同事:你不在旁邊,他只能看這份說明書做事。凡是他可能會問你的問題,都先寫進去。

input_schema:參數的規格

這部分用的是 JSON Schema,一種描述「資料長什麼樣子」的標準格式。上一個單元的結構化輸出,背後也是同一套東西。

  • properties:列出每個參數、它的型別,以及參數本身的說明。
  • required:哪些參數一定要給。
  • additionalProperties: False:不允許出現沒定義過的參數。

常用的型別有 string(文字)、integer(整數)、number(數字)、boolean(是或否)、array(清單)。如果某個參數只能是幾個固定值,可以用 enum 列出來,例如排序方式只能是 "name" 或 "date"。

把工具交給模型,看它怎麼回應

把工具放進 tools 參數,問一個需要讀檔才答得出來的問題:

from dotenv import load_dotenv
import anthropic

load_dotenv()
MODEL = "claude-sonnet-5-5"  # 可以換成其他模型 ID
client = anthropic.Anthropic()

response = client.messages.create(
    model=MODEL,
    max_tokens=16000,
    tools=[read_file_tool],
    messages=[{"role": "user", "content": "notes.txt 裡面寫了哪些待辦事項?"}],
)

print("停止原因:", response.stop_reason)
for block in response.content:
    if block.type == "text":
        print("文字:", block.text)
    elif block.type == "tool_use":
        print("想用的工具:", block.name)
        print("參數:", block.input)
        print("這次請求的 id:", block.id)

執行後你會看到類似這樣的輸出:

停止原因: tool_use
想用的工具: read_file
參數: {'path': 'notes.txt'}
這次請求的 id: toolu_01...

注意三件事:

  • stop_reason 是 tool_use,意思是「我先停下來,等你幫我執行工具」。
  • block.input 已經是 Python 字典,可以直接用 block.input["path"] 取值。
  • 你的電腦上還沒有任何檔案被讀取。模型只是提出請求,要不要執行、怎麼執行,是你的程式決定的。

模型拿不到結果就沒辦法回答,所以下一步就是:執行工具、把結果交回去、讓它繼續。這就是下一堂課的 Agent 迴圈。

你可能會遇到的狀況

  • 模型沒有用工具,直接回答了:可能是問題本身不需要工具,或說明沒寫清楚什麼時候該用。試著在 description 加上使用時機。
  • 參數格式不對:例如給了絕對路徑。把格式要求和例子寫進參數的 description。如果需要更嚴格的保證,可以在工具定義加上 "strict": True,讓參數一定符合規格。

OpenAI、Google 的 API 也是用「名稱、說明、JSON Schema 參數」來定義工具,欄位名稱略有不同,這堂課寫說明書的原則完全通用。

可以這樣問 AI

我要替一個 AI Agent 定義工具,功能是「在指定資料夾裡列出所有檔案,可以用副檔名篩選」。請用 Anthropic 的工具格式幫我寫出 name、description、input_schema,description 要說明用途、使用時機、參數格式與回傳內容。

行動練習
  1. 執行上面的程式,確認 stop_reason 是 tool_use,並看看模型給了什麼參數。
  2. 把 description 改成只有「讀檔」兩個字,再問幾個不同的問題,觀察模型的行為有沒有變化。
  3. 自己寫一個 list_files 工具定義,參數包含資料夾路徑,以及一個選填的副檔名篩選。把兩個工具都放進 tools,問「我的資料夾裡有哪些 txt 檔?」,看模型選了哪個工具。

讀完了嗎?

標記完成後,單元與專案的進度會自動更新(只存在這台裝置的瀏覽器)。

卡住了?讓 AI 當你的家教複製這段提問範本,貼到 Claude 或其他 AI 工具,再補上你卡住的地方。

留言與討論

卡關了、有心得,或發現內容需要更新?都歡迎留言。留言使用 GitHub 帳號登入。

留言區即將開放。現在可以先到 GitHub 討論區 發問,或看看 交流頁 的其他管道。