給 Agent 的工具 (Tool) 怎麼設計?函式命名、參數與錯誤訊息的實戰準則
客戶抱怨「模型很笨、常鬼打牆」,我們把 trace 拉出來,發現問題幾乎都不在模型,而在工具介面。一個叫 getData 的函式、一句 Error 400,就足以讓 agent 瞎猜到底。這篇給出 tool schema、錯誤回傳與冪等性設計的可複用範本——因為 agent 從來不笨,它只是照著你給的爛介面老實辦事。
作者
Tenten AI 研究團隊
應用 AI
發佈日期
2026年2月12日
閱讀時間
7 分鐘

上個月我們接手一個 agentic 專案,客戶抱怨「模型很笨,常常鬼打牆」。我們把 trace 拉出來一看,問題根本不在模型。是工具。有一個查詢訂單的 function 叫 getData,吃三個沒有說明的參數,查不到就回傳一個空陣列。agent 收到空陣列,以為查詢成功但客戶沒有訂單,於是自信地回覆「您目前沒有任何訂單」。實際上是參數格式錯了。
換句話說,模型的每一個決策,都是根據工具給它的資訊做的。工具介面(tool interface)決定 agent 成敗,遠比你換哪個模型重要。
為什麼 agent tool 工具設計是成敗關鍵
人類工程師看到 getData 會去翻文件、試錯、問同事。agent 不會。它只有你塞進 context 的那段 schema,加上工具回傳的字串。這是它認識世界的全部。你的命名含糊,它就亂猜;你的錯誤訊息只寫 Error 400,它就只能瞎重試或直接放棄。
所以 agent tool 工具設計的核心心法只有一句:把工具當成寫給一個聰明但沒有背景知識的新人看,而且他只能讀不能問。
函式命名:動詞開頭,講清楚副作用
命名要讓 agent 光看名字就知道「這會做什麼、會不會改到東西」。用 動詞_名詞 結構:search_orders、create_refund、cancel_subscription。
最關鍵的是區分「讀」和「寫」。get_invoice 是唯讀,重試一百次都安全;send_invoice 有副作用,重試會寄一百封信。名字必須讓 agent 一眼看出這個差別。我們的準則是:任何有副作用的工具,名字裡要有明確的動作動詞(create、delete、send、charge),絕不用模糊的 process、handle、manage。
參數設計:少即是多,型別要嚴
每多一個參數,agent 就多一個猜錯的機會。能推導的別讓它填,能有預設值的給預設值。
參數一定要用 enum 收斂。與其開一個 status 字串讓 agent 自由發揮打出 pending、Pending、in-progress,不如直接限定 enum: ["open", "closed", "refunded"]。每個參數的 description 要寫清楚格式與範例,尤其是日期、金額、ID 這種容易錯的:
{
"order_id": {
"type": "string",
"description": "訂單編號,格式 ORD-XXXXXX,例如 ORD-018823。不是購物車 ID。"
},
"amount_twd": {
"type": "integer",
"description": "退款金額,新台幣整數(不含小數)。須小於等於原始訂單金額。"
}
}
錯誤訊息:寫給 agent 看,不是寫給 log
這是最多人踩的雷。錯誤訊息不是給工程師事後查 log 的,是給 agent 當場做下一步決策的。一則好的錯誤訊息要回答三件事:發生什麼、為什麼、agent 現在該怎麼辦。
| 情境 | 爛的回傳(agent 會亂重試) | 好的回傳(agent 知道下一步) |
|---|---|---|
| 參數格式錯 | Error 400: Bad Request | INVALID_PARAM: order_id 格式錯誤。應為 ORD-XXXXXX,你傳的是 '88231'。請先用 search_orders 取得正確編號。 |
| 查無資料 | [] | NOT_FOUND: 查無此訂單。這可能是編號錯誤,或訂單不屬於此客戶。不要假設客戶沒有訂單。 |
| 沒有權限 | Error 403 | FORBIDDEN: 此操作需要主管授權,agent 無法執行。請回覆使用者需由專人處理,不要重試。 |
| 暫時性失敗 | 500 Internal Error | RETRYABLE: 上游服務逾時,可於數秒後重試,最多три次。 |
差別在於:好的訊息用穩定的錯誤碼(machine-readable)加上一句人話指引,並且明確告訴 agent「該重試」還是「別重試」。這一句話,能省下你 log 裡一半的無限迴圈。
冪等性:讓重試變安全
agent 會重試。網路抖一下、context 被截斷、loop 判斷失誤,同一個 create_refund 可能被呼叫兩次。如果你的工具不冪等,客戶就被退款兩次。
解法是讓寫入類工具吃一個 idempotency_key:同一把 key 重複呼叫,回傳第一次的結果而不是再執行一次。agent 那邊,我們固定用「本輪任務 ID + 操作名稱」當 key。這樣即使 harness 重跑整個 loop,危險操作也只會真正發生一次。這是把「Demo 能跑」推進到「敢上生產線」之間,最不起眼卻最省事的一道保險。
把上面幾條收斂成一個可複用範本:命名用 動詞_名詞 且讀寫分明、參數少而嚴且用 enum 收斂、錯誤回傳「錯誤碼 + 人話指引 + 是否可重試」、所有寫入操作吃 idempotency_key。
在 Tenten 幫客戶落地 agentic 工作流時,我們通常不急著調 prompt,而是先把這層工具介面重寫一遍。多數「模型很笨」的抱怨,改完工具就消失了一大半——因為 agent 從來不是笨,它只是照著你給的爛介面老實辦事。
