Agent-Friendly API:把你的服務做成 Agent 拿得起來的工具
前言
過去十年,我們為人類工程師設計 API:RESTful 命名、OpenAPI 文件、SDK 範例。但 2026 年,你的 API 多了一種呼叫者——AI Agent。它只讀三樣東西:工具名稱、描述文字、參數 schema,然後憑此決定要不要呼叫、怎麼呼叫。
結果是:同一支 API,人類工程師用得好好的,Agent 卻頻頻呼叫錯誤的工具、傳錯參數格式、被錯誤訊息困住。這不是模型不夠聰明,而是介面從來沒為它設計過。
Anthropic 在〈Building Effective Agents〉裡說過一句值得貼在牆上的話:"Tools are a new kind of software which reflects a contract between deterministic systems and non-deterministic agents."(工具是一種新軟體,體現的是確定性系統與非確定性 Agent 之間的契約。)他們的建議很直白:在 Agent-Computer Interface(ACI)上花的功夫,應該要跟 Human-Computer Interface(HCI)一樣多。
這篇文章從服務提供者的角度出發:如果你手上有一支 API 或一個後端服務,要怎麼把它包裝成 Agent 拿得起來、用不壞的工具?五個原則,一個可跑的 MCP 範例。
一、換個腦袋:Agent 是另一種使用者
人類工程師和 Agent 讀介面的方式完全不同(如圖一):
- 人類會先讀文件、看範例、試錯幾次後記住慣例。Agent 沒有「記住」的機會——每次呼叫都是一次全新的閱讀理解。
- 人類遇到模糊的錯誤訊息會去搜尋、問同事。Agent 只能靠錯誤訊息本身決定下一步;一句「Invalid request」對它來說等於死路。
- 人類能從 50 個端點中憑經驗挑出對的那個。Agent 靠的是工具描述的語義相似度——描述寫得含糊,它就選錯。
所以第一個心態轉換是:工具描述不是文件,是路由訊號。MCP 生態有句實務格言:description 是模型決定要不要呼叫這個工具的「主要路由訊號」。寫描述的時候,想像你在對一個聰明但毫無上下文的新人說話——他只看得到這段文字。
二、五個設計原則
原則一:描述寫「何時用」,不只寫「做什麼」
壞描述只講功能:「搜尋文件並回傳結果。」好描述講觸發條件:
在內部知識庫搜尋公司文件、政策與流程。當使用者詢問公司內部資訊、人資流程,或任何可能記載於內部文件的問題時使用。回傳最相關的三段摘錄並附來源。不處理一般網頁搜尋與即時資料。
好的工具描述回答四件事:是什麼、何時用、回傳什麼、不處理什麼。最後一點最常被忽略——明確寫出不處理什麼,比寫做什麼更能防止選錯工具。
實務上限:描述控制在 200 字以內。太長的描述會稀釋路由訊號,模型反而抓不到重點。
原則二:參數要防呆(poka-yoke)
Anthropic 在打造 SWE-bench agent 時發現,模型在使用相對路徑的工具時頻頻出錯;把工具改成「只接受絕對路徑」之後,錯誤直接歸零。他們把這個概念叫做 poka-yoke(防呆):與其指望模型不犯錯,不如讓錯誤的參數根本傳不進來。
落到 API 設計上:
- 日期一律 ISO-8601(
YYYY-MM-DD),不要讓模型猜10/15/2026是哪國格式。 - 有限集合用 enum:
status: [pending, paid, cancelled],不要用自由文字。 - 單位寫在參數名或描述裡:
timeout_ms比timeout好;預設值要合理(例如 5000)。 - 每個參數都要有型別與描述——永遠不要指望模型「猜」參數。
原則三:Chunky tools——一個工具做完一件事
人類工程師喜歡細粒度的 REST 端點:查訂單、查客戶、查物流,三支 API 各司其職。但對 Agent 來說,每多一次呼叫就多一次出錯機會、多一段 context 消耗。
The New Stack 在〈How To Prepare Your API for AI Agents〉中引述的實務建議是:提供 "chunky" 工具——把多個端點包裝成「完成一個商業結果」的單一工具。例如與其讓 Agent 先查客戶、再查訂單、再查物流,不如給它 get_order_status_with_tracking,一次回傳訂單加物流狀態。
判斷標準:一個工具應該對應一個使用者意圖,而不是一個資料表。
但注意另一端:也不要把 get_user 和 update_user 硬塞成一個帶 mode 參數的工具。單一職責仍然成立——chunky 是指「按意圖聚合」,不是「全部塞在一起」。
原則四:錯誤訊息是寫給 Agent 的說明書
當工具呼叫失敗,模型手上唯一的線索就是錯誤回傳。一句 400 Bad Request 或直接丟 stack trace,等於把 Agent 推下懸崖。
好的錯誤回傳有三個要素:
- 結構化:用固定 schema(例如
{"error_code": "ORDER_NOT_FOUND", "message": "...", "next_step": "..."}),不要純文字。 - 可行動:告訴 Agent 下一步能做什麼。「訂單不存在」之後加一句「請用 list_orders 確認訂單編號是否正確」。
- 不洩漏:永遠不要把 stack trace 或內部實作細節丟給模型——那是給人類除錯看的,不是給 Agent 看的。
MCP 的慣例是用 isError: true 標記錯誤內容,讓 harness 能區分「工具執行失敗」和「工具回傳了錯誤資訊」。
原則五:回傳要為 context 預算設計
Agent 的 context 視窗是預算,不是檔案櫃。你的 API 回傳直接吃掉這個預算,所以:
- 預設回傳精簡版(concise mode):關鍵欄位加
has_more旗標,需要時再要詳細版。 - 大列表一定要分頁或截斷(例如 25,000 token 上限),並在截斷時明確告知。
- 優先回傳人類可讀的識別(名稱而非 ID)、高訊號欄位;冗餘的 metadata 往後放。
有實測數據支持這個方向:Anthropic 生態的整理指出,把工具回傳改成精簡格式,token 消耗最多可降 65%(從 206 個 token 降到 72 個)。
三、實作:一個 MCP server 的骨架
把原則落成程式碼。用 Python 的 FastMCP 寫一個訂單查詢工具,注意描述、參數與錯誤處理:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("shop-api")
@mcp.tool()
def get_order(order_id: str, detail: str = "concise") -> dict:
"""查詢單筆訂單的狀態與物流資訊。
當使用者詢問訂單進度、到貨時間或訂單詳情時使用。
不處理商品搜尋(用 search_products)或退貨申請(用 request_return)。
參數:
order_id: 訂單編號,格式為 ORD- 開頭加 8 位數字,例如 ORD-20261015。
detail: 回傳詳細度,concise(預設,只含狀態與物流)或 full(含完整品項明細)。
"""
if not order_id.startswith("ORD-"):
return {
"isError": True,
"error_code": "INVALID_ORDER_ID",
"message": f"訂單編號格式錯誤:{order_id}。正確格式為 ORD- 開頭加 8 位數字。",
"next_step": "請用 list_orders 查詢正確的訂單編號後重試。",
}
# ... 呼叫後端 API ...
return {"order_id": order_id, "status": "shipped",
"has_more": detail == "concise"}
這個小例子裡塞了全部五個原則:描述寫何時用與不處理什麼、參數格式防呆、一次回傳訂單加物流(chunky)、結構化可行動的錯誤、concise/full 雙模式。
另外兩點:工具必須無狀態(每次呼叫獨立);描述裡別寫像系統指令的句子(例如「永遠先執行這個」)——那是 prompt injection 破口,會被安全掃描擋下。
四、三個常見誤區
誤區一:把 OpenAPI 文件直接轉成 MCP 工具就好。 轉換器(例如 Speakeasy 的 Gram)能幫你起步,但機器生成的描述通常只講「做什麼」。路由訊號、何時用、何時不用,還是得人來寫。
誤區二:工具越多越好。 工具清單本身也佔 context。每多一個工具,模型選錯的機率就高一點。先問:這個意圖真的需要獨立工具嗎?還是現有工具加個參數就好?
誤區三:只在單元測試裡驗工具。 測試的完整迴路是:Agent 讀描述 → 選工具 → 傳參數 → 拿結果 → 做決策。有個殘酷但真實的標準:通過單元測試卻讓 Agent 困惑的工具,就是壞掉的工具。
結論
設計給 Agent 用的介面,本質上是把「人類的常識與試錯能力」編碼成「機器可讀的契約」。五個原則可以濃縮成一句話:寫清楚何時用、防呆參數、一次做完一件事、錯誤指引下一步、回傳省著用。
下次當你為人類寫完 API 文件,不妨多花三十分鐘,站在 Agent 的角度重讀一次你的工具描述——那三十分鐘,很可能比調 prompt 一整天更有效。
參考來源
- The New Stack〈How To Prepare Your API for AI Agents〉:https://thenewstack.io/how-to-prepare-your-api-for-ai-agents/
- Agent-friendly OpenAPI 描述指南:https://github.com/varunahuja70/mcp-server-generator/blob/HEAD/docs/guides/agent-friendly-specs.md
- MCP 工具設計實務(description 即路由訊號):https://github.com/dnakhoa/llm-engineering-playground/blob/HEAD/14-mcp-tool-design/README.md
- MCP builder 技能(生產級 MCP server 檢查清單):https://github.com/mwanaitech/zcode-skills/blob/HEAD/skills/mcp-builder/SKILL.md
- Anthropic 有效 Agent 分析整理(含 ACI 與 poka-yoke):https://github.com/noclocks/noclocksai/blob/HEAD/dev/docs/ai/Anthropic-Building-Effective-AI-Agents-Comprehensive-Analysis.md
沒有留言:
張貼留言