← 返回 2026-10-04 简报

对比智能体框架:工具调用模式的处理

Agent Frameworks Compared: Tool-Calling Schema Handling

摘要
事件:OpenRouter对比六款智能体框架的工具调用处理机制,指出各提供商格式不兼容导致模型切换需重写代码。 要点:OpenAI、Anthropic和Google各有不同请求响应形状;OpenRouter通过API层标准化工具调用,屏蔽底层差异。 影响:开发者无需维护多套翻译逻辑,即可无缝切换模型,降低集成复杂度并提升跨平台稳定性。

你构建了一个具备正常工作调用能力的智能体,随后更换了后端的模型,工具调用便开始失败。你的工具定义并未更改。然而,模型所期望的请求和响应格式发生了变化,因为每个提供商都使用其独有的形状来定义工具、工具调用响应、参数编码以及工具结果。如果你的技术栈中没有任何组件能在这些不同的形状之间进行转换,那么更换模型就意味着需要编写新的解析代码并面对新的故障模式。

本文比较了六种智能体框架如何定义工具模式并在不同提供商之间进行转换,以及每种情况下转换发生的位置。接着,它展示了我们如何在 API 层面对工具调用进行标准化处理,使得你的应用程序发送给每个支持工具的 OpenRouter 模型的形状保持一致。

简而言之

OpenAI、Anthropic 和 Google 各自以不同的网络格式定义工具并返回工具调用。为其中一个提供商编写的工具定义无法在不修改的情况下直接用于另一个提供商。

LangChain 和 LangGraph 针对每个提供商翻译一种工具定义。CrewAI 将翻译工作委托给其路由到的客户端。OpenAI Agents SDK、Claude Agent SDK 和 Google ADK 都是围绕单一提供商的格式构建的。Microsoft Agent Framework 则委托给配置的模型连接器处理。

OpenRouter 接受 OpenAI 风格的 tools 数组,并为每个支持工具调用的模型返回标准的 tool_calls 响应,因此切换模型只需更改模型字符串即可。

在包含工具的请求中,Auto Exacto 默认会根据吞吐量、工具调用成功率和基准数据对提供商进行重新排序,其背后的“工具调用错误率”指标在每个模型的 Performance(性能)选项卡上均可查看。

通过订阅,你同意接收 OpenRouter 通讯:包括模型使用数据、产品更新和研究报告,频率约为每周一次。您可以通过每封电子邮件中的链接随时退订。请参阅我们的隐私政策。

各提供商对“什么是工具”达成一致。工具具有名称、描述以及说明其接受哪些参数的参数模式。模型读取这三部分信息,决定是否调用工具,并生成相应的参数。

协议仅止于此。每个提供商将这些部分封装在其独有的请求和响应格式中,且这些格式互不兼容。

在 OpenAI 的 Chat Completions API 中,你传递一个 tools 数组,其中每个条目包含 type: "function" 和一个 function 对象,该对象持有名称、描述和 JSON Schema 参数。当模型希望调用工具时,助手消息会携带一个 tool_calls 数组,且每次调用的 arguments 字段均为 JSON 编码的字符串。

{
"tools" : [
{
"type" : "function" ,
"function" : {
"name" : "get_weather" ,
"description" : "获取城市的当前天气" ,
"parameters" : {
"type" : "object" ,
"properties" : { "city" : { "type" : "string" } },
"required" : [ "city" ]
}
}
}
]
}

Anthropic 的 Messages API 使用更扁平的定义,模式位于 input_schema 下。模型的请求以助手消息内的 tool_use 内容块形式返回,参数已解析为 input 对象,且回合以 stop_reason: "tool_use" 结束。

{
"tools" : [
{
"name" : "get_weather" ,
"description" : "获取城市的当前天气" ,
"input_schema" : {
"type" : "object" ,
"properties" : { "city" : { "type" : "string" } },
"required" : [ "city" ]
}
}
]
}

Google 的 Gemini API 在 generateContent 请求中将工具定义嵌套在 function_declarations 数组下,模型的请求以 response content 中的 functionCall 部分返回,而非作为单独的顶级字段。Google 较新的 Interactions API 又接受了不同的工具条目形状,在每个工具的顶层包含 type: "function"。

这是一个工具、三种请求格式和三种响应格式。开源模型增加了另一种情况。未经过训练以输出工具调用格式的模型只能以文本形式生成工具调用。此类模型的工具调用支持取决于服务层将工具定义放入提示词中,并将模型的输出解析回调用。这种解析不属于提供商的传输格式的一部分,其失败方式也与原生格式不同。

您的应用程序定义了一个工具,但它必须生成的确切请求格式取决于请求背后的模型。要么堆栈中的某些内容将该定义重写为每个模型的正确格式,要么您自己编写并维护该转换。

模式翻译可以位于何处

翻译可以在三个地方运行。

在您的应用程序中。您自己编写每个提供商的请求和响应映射,并在提供商更改时维护它。

在框架中。代理框架或它委托的提供商客户端接受一个工具定义,并为每个提供商生成格式。

在 API 层。在每个模型前面的网关接受一种格式,并在向每个提供商发送时进行翻译。我们的工具调用和结构化输出文档完整展示了标准化形状。

以下框架的主要区别在于它们承担第二种选项的程度以及将哪个提供商视为其原生格式。

这里的所有框架都支持工具调用。不同之处在于翻译位于何处以及框架拥有多少部分。

LangChain 和 LangGraph

您使用带有类型提示的 Python 函数定义一次工具,并使用 @tool 装饰器,类型提示定义了工具的输入模式。您通过 bind_tools() 将工具附加到模型,create_agent 运行工具调用循环。LangChain 的聊天模型集成将定义转换为每个提供商的格式,因此相同的代理代码可以通过 init_chat_model 在 OpenAI、Anthropic 和 Google 模型上运行。

这种抽象从您的代码中隐藏了传输格式的差异。任何给定翻译的质量取决于特定的提供商集成,因此请测试您计划发布的特定模型。LangChain 还在 langchain-openrouter 包中记录了 OpenRouter 聊天模型集成,因此您可以通过 init_chat_model 选择任何 OpenRouter 模型,并将每个提供商的翻译留给我们 API 处理。

对于 MCP,LangChain 记录了基于 FastMCP 构建的 MCPAdapter,它发现服务器的工具并将其适配为 LangChain 工具。langchain.mcp 命名空间需要 langchain[mcp]>=1.4.0,并记录为测试版。

CrewAI

CrewAI 围绕角色和任务组织。您将工具分配给代理,团队协调工作。CrewAI 本身不实现特定于提供商的工具格式。

CrewAI 的 LLM 文档描述了 OpenAI、Anthropic、Google 的 Gemini API、Azure、AWS Bedrock 和 Snowflake Cortex 的原生 SDK 集成,通过您配置的 provider/model-id 字符串进行选择。所有其他提供商都通过 LiteLLM 运行。在任何一种情况下,模式处理属于 CrewAI 路由到的客户端,而不是 CrewAI 本身。

对于 MCP,crewai-tools 包为 stdio、SSE 和可流式 HTTP 服务器提供了 MCPServerAdapter 和传输类。

OpenAI Agents SDK

OpenAI Agents SDK 围绕 OpenAI 的工具格式构建。您使用 @function_tool 装饰器定义函数工具,SDK 从函数签名和文档字符串生成参数的 JSON Schema。它在 OpenAI 模型上提供最完整的支持,包括在 OpenAI 端运行的托管工具。

这并不仅限于 OpenAI。该 SDK 的模型文档描述了通往其他提供商的三个内置路径。set_default_openai_client 通过设置 base_url 和 api_key 将 SDK 指向兼容 OpenAI 的端点,ModelProvider 对单次运行应用自定义提供商,而 Agent.model 则为单个智能体设置模型。Any-LLM 和 LiteLLM 被记录为尽最大努力的第三方适配器,用于覆盖内置路径未涵盖的情况。当你通过 Chat Completions 而非 Responses API 进行路由时,SDK 会丢弃仅适用于 Responses 的字段,且文档警告称某些提供商不支持 JSON Schema 结构化输出。你离 OpenAI 的模型越远,就越依赖于兼容性层而非官方支持。

MCP 支持是内置的,涵盖了通过 OpenAI 的 Responses API 托管的 MCP 服务器工具以及通过 stdio 和 HTTP 传输协议直接连接到 MCP 服务器的功能。

Claude Agent SDK

Claude Agent SDK 是 Claude Code 背后的智能体框架,打包为 Python 和 TypeScript 库。与 Anthropic Messages API 不同,它为你运行工具执行循环,内置了工具、上下文管理、权限、钩子和子智能体。你可以在 Python 中使用 @tool 装饰器或在 TypeScript 中使用 tool() 定义自定义工具,使用 create_sdk_mcp_server 将其包装为进程内 MCP 服务器,并将该服务器传递给查询。

它针对 Claude 模型,因此工具调用直接使用 Anthropic 的原生 tool_use 格式。不存在跨提供商的翻译层。将其指向非 Anthropic 模型并非其设计用途。

Microsoft Agent Framework

微软将 Agent Framework 描述为 AutoGen 和 Semantic Kernel 的直接继任者,结合了 AutoGen 的智能体抽象与 Semantic Kernel 的企业级功能,并添加了显式工作流。其概述列出了 Microsoft Foundry、Anthropic、Azure OpenAI、OpenAI 和 Ollama 作为支持的模型提供商,工具调用和 MCP 服务器通过智能体抽象进行处理。

工具作为类型化函数附加到智能体上,框架会将其转换为带有 JSON Schema 的函数工具。工具调用翻译属于你配置的任意模型连接器,因此更改提供商也会随之改变模式处理方式。微软发布了从 AutoGen 迁移的指南,供从旧框架转移的团队使用。

Google ADK

Google 的 Agent Development Kit 专为 Gemini 及其原生的 function_declarations 格式构建。当你将 Python 函数传递给智能体的工具列表时,ADK 会将其包装为 FunctionTool,并根据函数的签名和文档字符串生成模式。

对于 Gemini 之外的模型,ADK 记录了包括 LiteLLM 连接器在内的连接器页面。通过该路径,对 Claude 或 GPT 模型的调用将通过 LiteLLM 的翻译而非 ADK 的原生功能运行,因此这些模型的模式行为取决于该集成。请测试你计划使用的确切模型。

对于 MCP,ADK 提供了 McpToolset,它连接到 MCP 服务器并将其工具暴露给智能体。

框架比较

在选择框架之前,请先根据工具调用支持筛选我们的模型目录。列出提供商适配器的框架与支持原生工具调用的模型是两回事,它们之间的差距正是意外发生的地方。

框架 你如何定义工具 跨提供商翻译模式的组件 MCP 支持
LangChain 和 LangGraph 带有类型提示和 @tool 装饰器的 Python 函数 LangChain 的每个提供商聊天模型集成 langchain.mcp 命名空间中的 MCPAdapter,文档标记为 beta
CrewAI 按角色分配给智能体的工具 路由客户端,即原生提供商 SDK 或 LiteLLM crewai-tools 中的 MCPServerAdapter
OpenAI Agents SDK 带有生成 JSON Schema 的 @function_tool 无官方翻译。其他提供商通过兼容 OpenAI 的端点或 beta 版 Any-LLM 和 LiteLLM 适配器 内置,托管和直接 MCP 服务器

Claude Agent SDK @tool 在进程内 MCP 服务器中:无。单提供商设计,内置 MCP 客户端与进程内服务器

Microsoft Agent Framework 将类型化函数转换为函数工具:配置的模型连接器,通过代理抽象内置 MCP 服务器

Google ADK Python 函数包装为 FunctionTool:无原生跨提供商路径。通过 LiteLLM 等连接器支持非 Gemini 模型 McpToolset

将此表视为起点,在做出决定前请查阅最新文档。这些框架发布频繁,工具调用行为是其中变化较大的部分之一。

切换模型时会发生什么故障

故障呈现多种形态,上述框架均未消除这些问题。

一个提供商接受的 schema 可能被另一个更严格的提供商拒绝。深层嵌套的参数对象、不寻常的类型,或一个提供商忽略而另一个强制执行的约束,都足以在新模型上产生请求错误。

没有原生工具调用能力的模型会将调用返回为纯文本。管道中的任何组件都无法将其识别为 tool_call,因此没有可捕获的错误,只有不符合循环预期的响应。除非框架或你自己的代码添加了文本解析的回退机制,否则代理将停止推进,而不是抛出错误。

修复行为各不相同。某些代码路径在调用返回格式错误时会抛出可捕获的错误。其他情况则要求你自己负责检测和恢复。如果你的代理循环假设了某种行为,而框架提供了另一种,那么模型切换可能导致错误未被察觉。

一种更微妙的情况出现在未切换模型家族时。同一模型由不同提供商提供服务时,可能以不同的速率返回有效的工具调用。自 2025 年 8 月以来,我们对 OpenRouter 上的每次工具调用响应进行了评分,并在我们的 Auto Exacto 公告中指出,在受影响的提供商上,GLM-5 和 GLM-4.7 的工具调用错误率在我们开始将工具调用流量从较弱的端点路由走后,从约 8% 降至接近 1%。

我们将每个失败的工具调用分类为三类,同样的三项检查也适用于你自己的日志记录。InvalidJson 表示参数无法解析为 JSON。UnknownName 表示调用的函数名称不在请求的工具列表中。SchemaMismatch 表示参数未通过工具参数 schema 的验证。关于循环机制,包括重试、停止条件和逐轮控制,请参阅我们关于构建工具调用代理循环的指南。

翻译存在的第三个位置是 API 层,位于框架之下。我们在每个模型之前统一标准化工具调用,因此上层不会看到各提供商之间的差异。

你发送一个带有 tools 数组的 OpenAI 风格请求。我们将其转换为目标提供商的格式,运行它,并返回标准的 tool_calls 响应。对于所有支持工具调用的模型,你发送和接收的形状是相同的,因此切换模型只需更改模型字符串即可。

下面的示例以 OpenAI 格式定义一次工具,并根据运行请求的模型无关地从 message.tool_calls 读取结果。

import json
import os

from openai import OpenAI

client = OpenAI(
base_url = "https://openrouter.ai/api/v1" ,
api_key = os.environ[ "OPENROUTER_API_KEY" ],
)

def get_weather (city: str ) -> dict :
return { "city" : city, "forecast" : "sunny" , "temperature_c" : 24 }

tools = [{
"type" : "function" ,
"function" : {
"name" : "get_weather" ,
"description" : "Get the current weather for a city" ,
"parameters" : {
"type" : "object" ,
"properties" : { "city" : { "type" : "string" }},
"required" : [ "city" ],
},
},
}]

messages = [{ "role" : "user" , "content" : "What's the weather in Lisbon?" }]

将此字符串更改为 anthropic/claude-sonnet-4.6 或 google/gemini-3.5-flash

此文件中的其他内容无需更改。

response = client.chat.completions.create(
model = "openai/gpt-5.5" ,
messages = messages,
tools = tools,
)

choice = response.choices[ 0 ]
messages.append(choice.message)

来自每个具备工具调用能力的模型的 tool_calls 结构都相同。

for call in choice.message.tool_calls or []:
args = json.loads(call.function.arguments) # arguments 是一个 JSON 字符串
result = get_weather( ** args)
messages.append({
"role" : "tool" ,
"tool_call_id" : call.id,
"content" : json.dumps(result),
})
有两点在所有模型中保持一致。工具定义和你解析的响应保持不变。tool_calls 始终是一个数组,每个 arguments 的值是

本条评分 9.2 score-v1
  • 来源权威 8
    注册表 priority=8(OpenRouter)
  • 时效 1.225
    发布 46.5 小时前,衰减到 1.23/3.0
  • 多源印证 0
    只有 1 家在报(无旁证)
  • 社区信号 0
    无社区数据(本管线走 RSS,HN 的 hn_fetcher 未接入)
历史
刊期得分排名结果
2026-10-04 9.22 21 入选
2026-10-03 9.95 27 未入选
原文链接:https://openrouter.ai/blog/insights/agent-frameworks-compared-tool-calling-schema-handling/
来源:OpenRouter
以上内容由 AI 自动翻译,仅供参考。
← 返回简报