你寫好一個 agent,tool calling 一切正常。然後換了背後的模型,tool call 開始失敗。工具定義沒改,改的是模型期望的請求與回應格式——OpenAI、Anthropic、Google 各自用不同的 wire format 包裝工具定義和 tool call。OpenRouter 在 2026 年 10 月 2 日發表的框架比較文章,就是針對這個問題:六個主流框架各自把 schema 翻譯放在哪一層。
同一個工具,三種格式
三家供應商對「什麼是工具」有共識:名稱、描述、參數 schema。共識到此為止。OpenAI 的 Chat Completions API 用 tools 陣列加上 function 物件,回傳時 arguments 是 JSON 編碼的字串;Anthropic 的 Messages API 用較扁平的 input_schema,回傳是 assistant 訊息裡的 tool_use content block,參數已解析成物件;Gemini API 則把定義嵌在 function_declarations 裡,回應是 content 裡的 functionCall part。同一個 get_weather 工具,就是三種請求形狀、三種回應形狀。
開放權重模型再加一層:沒被訓練過輸出 tool-calling 格式的模型,只能用純文字產出呼叫,解析工作落在 serving 層,失敗方式也和原生格式不同。
翻譯可以住的三個地方
文章把翻譯層歸納為三個位置:你自己寫 per-provider 的映射;框架幫你翻譯;或是在 API 閘道層統一格式。框架之間的差異,主要是第二種選項承擔了多少、以及把哪家的格式當原生。
- LangChain / LangGraph:用
@tool裝飾器定義一次,per-provider 的 chat model 整合負責翻譯。抽象幫你遮住差異,但翻譯品質取決於個別整合,文章建議直接測你打算上線的模型。 - CrewAI:自己不做 provider 格式化,交給它路由到的 client——原生 SDK 或 LiteLLM。
- OpenAI Agents SDK:圍繞 OpenAI 的工具格式打造,離開 OpenAI 模型越遠,越依賴相容層與 beta 級的第三方 adapter。
- Claude Agent SDK:直接用 Anthropic 原生
tool_use,沒有跨供應商翻譯層,指向非 Anthropic 模型本來就不是它的設計目標。 - Microsoft Agent Framework 與 Google ADK:翻譯責任跟著你配置的 model connector 走,換 provider 就換了一套 schema 行為。
這對選型的實際意義
看這份比較時,我覺得最有用的不是排行榜式的結論,而是一個提醒:框架列了某個 provider 的 adapter,和某個模型真的支援原生 tool calling,是兩件事,意外通常出在兩者之間的縫隙。所以選框架前先過濾模型目錄的 tool-calling 支援,再把「誰負責翻譯」當成明確的架構決策來做——是留在應用層換取控制權,還是交給閘道層換取「換模型只是改一個 model string」的彈性。OpenRouter 自己的路線是第三種:接受 OpenAI 風格的 tools 陣列,對所有支援工具的模型回傳標準 tool_calls。
這也呼應了之前寫過的 provider 端 server-side code execution 工具的比較——兩個問題的本質相同:與其自己在應用層維護每家供應商的差異,不如判斷哪些差異值得交給基礎設施層吃掉。
一個留意事項:即使翻譯交給了框架或閘道,文章仍反覆出現同一句建議——測試你實際要用的那個模型。翻譯層處理的是格式,不是品質;tool-calling 的成功率仍然因模型而異,這部分沒有捷徑。
