QVeris
运行任务
Function Calling API Comparison函数调用 API 对比指南

Function Calling APIs
Provider Comparison
函数调用 API
供应商对比

A production guide to tool schemas, call IDs, result messages, strict mode, parallel calls, streaming, adapters, and validation.

从工具 Schema、调用 ID、结果回传,到严格模式、并行调用、流式处理、统一适配和生产验证。

Compare provider schemas, call IDs, adapters, controls, and production validation.

对比三家 Schema、调用 ID、适配器、控制策略与生产验证。

OpenAI, Anthropic, and Google function calling APIs normalized into one canonical tool contract and validation pipeline OpenAI、Anthropic 与 Google Function Calling API 统一为工具契约及验证流程

Decision brief决策摘要

TL;DR

Same loop, different wire formats

All three APIs describe tools, emit structured calls, wait for your application to execute them, and consume correlated results. The field names and conversation rules differ.

Normalize at your boundary

Keep one internal tool contract and translate provider requests and responses in thin adapters. Do not let provider message shapes leak into business logic.

Strict is not safe

Strict schema mode improves argument shape. Your server must still validate values, authorize the caller, control side effects, and treat tool output as untrusted.

Test the loop, not one happy call

Evaluate malformed arguments, multiple calls, partial streams, timeouts, retries, duplicate side effects, result ordering, and model recovery.

循环相同,线格式不同

三家都会声明工具、返回结构化调用、等待应用执行,再消费带关联标识的结果;差异在字段名与消息编排规则。

在系统边界统一

内部只保留一份工具契约,用轻量适配器翻译三家格式,不让供应商消息结构进入业务逻辑。

严格模式不等于安全

严格 Schema 只能改善参数形状。服务端仍需校验值、鉴权、控制副作用,并把工具输出视为不可信输入。

测试完整循环

不要只测一次成功调用,还要覆盖畸形参数、多工具、流式分片、超时、重试、重复副作用、结果顺序和模型恢复。

Who this comparison is for这份对比适合谁

Use this guide if you are selecting a provider, migrating an existing agent, or building one orchestration layer across multiple models. It assumes you can make API requests, define JSON Schema, and execute tools in a trusted backend.

如果你正在选择模型供应商、迁移现有 Agent,或建设跨模型编排层,这份指南适合你。默认你已经能够调用 API、定义 JSON Schema,并在可信后端执行工具。

Prerequisite: server-side tool executor
Prerequisite: JSON Schema validation
Prerequisite: secrets outside prompts
Prerequisite: structured logs and traces
前置:服务端工具执行器
前置:JSON Schema 校验
前置:密钥不进入 Prompt
前置:结构化日志与链路追踪

Start with one canonical tool contract先定义一份统一工具契约

The durable unit is not a provider payload. It is a provider-neutral definition, a normalized call, and a normalized result. Store the provider call ID separately so the adapter can reconstruct the required reply.

真正稳定的单元不是某家 Payload,而是供应商无关的工具定义、标准化调用与标准化结果。供应商调用 ID 单独保存,适配器才能重建正确的回传消息。

TypeScript · internal contractTypeScript · 内部契约
type ToolDefinition = {
  name: string;
  description: string;
  inputSchema: JsonSchema;
  sideEffect: "read" | "write";
};

type ToolCall = {
  provider: "openai" | "anthropic" | "google";
  providerCallId: string;
  name: string;
  arguments: unknown;
  raw: unknown;
};

type ToolResult = {
  providerCallId: string;
  ok: boolean;
  content: unknown;
  evidence?: { source: string; retrievedAt: string }[];
};

OpenAI vs Anthropic vs Google: protocol comparisonOpenAI、Anthropic 与 Google 协议对比

ConcernOpenAIAnthropicGoogle Gemini
Tool definition工具声明type: function + function schemaname, description, input_schematype: function + parameters in Interactions
Call output调用输出function_calltool_use content blockfunction_call step
Correlation key关联键call_idtool_use_idcall_id; preserve signature/state where required
Return result结果回传function_call_outputtool_result in the next user messagefunction_result
Strict schema严格 Schemastrict: true; strict object requirementsstrict: true supportedSupported schema subset varies by API/model
Parallel calls并行调用Supported; can disableMultiple tool_use blocks; can disableParallel and compositional calling supported
Stateful continuation有状态续接Use response/conversation state or send prior itemsSend the next user message with result blocksprevious_interaction_id in Interactions
关注点OpenAIAnthropicGoogle Gemini
工具声明type: function 加函数 Schemanamedescriptioninput_schematype: function 加 Interactions 中的 parameters
调用输出function_calltool_use 内容块function_call 步骤
关联键call_idtool_use_idcall_id;必要时保留签名与状态
结果回传function_call_output下一条用户消息中的 tool_resultfunction_result
严格 Schemastrict: true;要求严格对象结构支持 strict: true支持的 Schema 子集随 API 与模型而异
并行调用支持,也可禁用支持多个 tool_use 块,也可禁用支持并行调用与组合调用
有状态续接使用响应/会话状态,或发送先前消息项在下一条用户消息中发送结果块在 Interactions 中使用 previous_interaction_id

Version boundary: Google has both the newer Interactions API vocabulary and the legacy generateContent vocabulary (functionCall/functionResponse). Pick one surface per adapter and document it.

版本边界:Google 同时存在较新的 Interactions API 术语,以及旧版 generateContentfunctionCall/functionResponse。每个适配器只选择一个接口面,并明确记录。

OpenAI implementation: correlate with call_idOpenAI 实现:用 call_id 关联结果

Send function tools with the request. When the model emits a function_call, parse its arguments, execute the approved tool, then append a function_call_output carrying the same call_id. Use tool_choice deliberately instead of forcing tools by default.

请求中发送函数工具。模型输出 function_call 后,解析参数、执行已授权工具,再用相同 call_id 回传 function_call_output。应有意识地配置 tool_choice,不要默认强制调用。

OpenAI Responses API · abbreviatedOpenAI Responses API · 简化示例
const first = await client.responses.create({
  model, input: userInput,
  tools: [{ type: "function", name: "get_quote", description,
    parameters: quoteSchema, strict: true }]
});

const call = first.output.find(x => x.type === "function_call");
const result = await executeSafely(call.name, JSON.parse(call.arguments));

const final = await client.responses.create({
  model, previous_response_id: first.id,
  input: [{ type: "function_call_output", call_id: call.call_id,
    output: JSON.stringify(result) }]
});

Anthropic implementation: preserve tool_use orderingAnthropic 实现:保持 tool_use 消息顺序

Claude returns one or more tool_use blocks, commonly with stop_reason: tool_use. The next user message must contain corresponding tool_result blocks. Put result blocks before any additional user text and mark execution failures with is_error: true.

Claude 会返回一个或多个 tool_use 块,通常伴随 stop_reason: tool_use。下一条 user 消息必须包含对应的 tool_result;结果块放在其他用户文字之前,执行失败用 is_error: true 标记。

Anthropic Messages API · abbreviatedAnthropic Messages API · 简化示例
const calls = response.content.filter(x => x.type === "tool_use");
const toolResults = await Promise.all(calls.map(async call => ({
  type: "tool_result",
  tool_use_id: call.id,
  content: JSON.stringify(await executeSafely(call.name, call.input))
})));

messages.push({ role: "assistant", content: response.content });
messages.push({ role: "user", content: toolResults });

Google implementation: preserve state and signaturesGoogle 实现:保留状态与签名

In the Interactions API, a function call is a step with id, name, and arguments; return a function_result referencing its call ID. Stateful continuation uses previous_interaction_id. In stateless flows, replay prior steps exactly, including required thought/signature metadata.

在 Interactions API 中,函数调用是包含 idnamearguments 的 step;回传引用该调用 ID 的 function_result。有状态模式使用 previous_interaction_id,无状态模式则必须完整重放历史 step,包括所需的思考签名元数据。

Google Interactions API · abbreviatedGoogle Interactions API · 简化示例
const call = interaction.outputs.find(x => x.type === "function_call");
const result = await executeSafely(call.name, call.arguments);

const next = await client.interactions.create({
  model,
  previous_interaction_id: interaction.id,
  input: [{ type: "function_result", call_id: call.id,
    result }]
});

Build a thin provider adapter构建轻量供应商适配器

Each adapter should do four things only: serialize definitions, extract calls, serialize results, and preserve provider state. Validation, authorization, execution, retries, and evidence belong to shared infrastructure.

每个适配器只负责四件事:序列化工具定义、提取调用、序列化结果、保留供应商状态。校验、授权、执行、重试和证据应位于共享基础设施。

VALIDATE校验
AUTHORIZE授权
EXECUTE执行
CORRELATE RESULT关联结果
ANSWER回答
Provider-neutral loop供应商无关循环
const turn = await adapter.ask({ messages, tools: canonicalTools });
const calls = adapter.extractCalls(turn);

const results = [];
for (const call of calls) {
  const args = validate(call.name, call.arguments);
  await authorize(identity, call.name, args);
  results.push(await executeIdempotently(call, args));
}

const answer = await adapter.continue({
  state: turn.state,
  toolResults: results
});

Schema design that survives all three APIs能跨三家工作的 Schema 设计

  • Use small objects with explicit properties and predictable primitive types.
  • Keep enums short and explain units, formats, time zones, and defaults in descriptions.
  • Avoid deeply recursive schemas, ambiguous unions, and provider-specific extensions in the canonical layer.
  • For OpenAI strict mode, objects need additionalProperties: false and required fields; represent optional values explicitly where needed.
  • Validate again after decoding. Schema compliance does not prove a ticker exists, a date range is allowed, or a transfer is authorized.
  • 优先使用小型对象、明确属性和可预测的基础类型。
  • 枚举保持简短,并在描述里写清单位、格式、时区和默认值。
  • 统一层避免深度递归 Schema、模糊 union 与供应商私有扩展。
  • OpenAI 严格模式下,对象需要 additionalProperties: false 与 required 字段;可选值按需显式表达。
  • 解码后再次校验。符合 Schema 不代表股票代码存在、日期范围被允许,或转账已经授权。

Tool choice, strict mode, and parallel calls工具选择、严格模式与并行调用

Control控制项Use it when适用场景Production caution生产注意
AutoThe model may answer or call tools.模型可以直接回答或调用工具。Best default for mixed conversations.适合作为混合对话默认值。
Required / forcedA workflow step must obtain structured data.流程必须取得结构化数据。Do not force irreversible actions.不要强制执行不可逆动作。
StrictYou need dependable argument shape.需要更稳定的参数形状。Still enforce business rules server-side.业务规则仍必须在服务端执行。
ParallelCalls are independent and read-only.调用彼此独立且只读。Serialize dependent or side-effecting calls.依赖调用或有副作用调用要串行。

Streaming and multi-turn state流式处理与多轮状态

Never execute a tool from an incomplete argument fragment. Buffer deltas until the provider marks the call complete, decode once, validate once, and persist the provider call ID before execution. For stateless continuation, retain every provider-required message item and opaque signature exactly.

绝不能从未完成的参数分片直接执行工具。先缓存 delta,等待供应商确认调用结束,再统一解码、校验,并在执行前持久化调用 ID。无状态续接时,所有供应商要求的消息项与不透明签名都要原样保留。

Rule: parse only complete JSON; execute only persisted calls; return exactly one result for every accepted call.

规则:只解析完整 JSON;只执行已持久化调用;每个已接受调用必须恰好返回一个结果。

Security, cost, and latency controls安全、成本与延迟控制

Validate and authorize separately

Schema validation answers “is this shaped correctly?” Authorization answers “may this identity perform this action on this resource?” Both are required.

Treat tool output as untrusted

Fetched pages, documents, and API text can contain indirect prompt injection. Preserve provenance, limit returned fields, and keep results inside the provider's designated tool-result structure.

Make writes idempotent

Persist a deterministic idempotency key before side effects. Retries must return the previous outcome instead of repeating an order, message, payment, or mutation.

Budget every stage

Set deadlines, maximum calls per turn, concurrency, result-size limits, and token budgets. Cancel downstream work when the user request is abandoned.

校验与授权分开

Schema 校验回答“形状是否正确”,授权回答“这个身份能否对这个资源执行该动作”,两者缺一不可。

工具输出默认不可信

网页、文档和 API 文本可能包含间接 Prompt Injection。保留来源、限制返回字段,并把结果放在供应商指定的 tool-result 结构中。

写操作必须幂等

副作用前持久化确定性幂等键;重试应返回上次结果,而不是重复下单、发信、支付或写入。

为每一层设置预算

限制截止时间、单轮最大调用数、并发数、结果大小和 token;用户请求取消时同步终止下游工作。

Common failure modes and fixes常见失败模式与修复

Symptom现象Likely cause常见原因Fix修复
Provider rejects the next turn供应商拒绝下一轮消息Missing, reordered, or wrong result ID结果 ID 缺失、错序或不匹配Persist raw calls and generate results through one adapter持久化原始调用,并统一由适配器生成结果消息
Tool runs twice工具执行两次Network retry without idempotency网络重试但没有幂等控制Deduplicate before execution and cache outcome执行前去重并缓存结果
Arguments fail randomly参数偶发解析失败Parsing streamed fragments or vague schema解析未完成流片段或 Schema 含糊Aggregate to completion; simplify and tighten schema聚合完成后再解析,并简化、收紧 Schema
Parallel results are mismatched并行结果对应错误Matching by array position按数组位置匹配Match only by provider call identifier只按供应商调用 ID 匹配
Model follows text inside a result模型执行了结果中的恶意文本Indirect prompt injection间接 Prompt InjectionMinimize, label, sanitize, and policy-check untrusted content最小化、标记、净化并策略检查不可信内容

A provider-neutral validation benchmark供应商无关的验证基准

Do not publish a single “accuracy” score from a handful of prompts. Run the same versioned corpus against every provider and report success by failure class.

不要用少量 Prompt 得出一个笼统“准确率”。应对每家供应商运行同一份版本化测试集,并按失败类型分别报告。

Selection: correct tool vs no tool
Arguments: schema and semantic validity
Correlation: every call gets the right result
Recovery: timeout, error, empty result, retry
Safety: unauthorized and injected requests blocked
Operations: p50/p95 latency, cost, call count
选择:该调用时调用,不该调用时不调用
参数:Schema 与语义都有效
关联:每个调用拿到正确结果
恢复:超时、报错、空结果与重试
安全:未授权与注入请求被阻止
运维:p50/p95 延迟、成本、调用次数

Migration checklist between providers跨供应商迁移清单

  1. Freeze a canonical tool registry and version every schema.
  2. Map definition fields, tool-choice controls, call IDs, result envelopes, and conversation state.
  3. Remove unsupported schema features before translation.
  4. Replay production traces in shadow mode without side effects.
  5. Compare call selection, argument validity, recovery, latency, and cost.
  6. Canary read-only tools first; enable write tools only after idempotency and authorization tests pass.
  1. 冻结统一工具注册表,并为每个 Schema 建立版本。
  2. 映射工具字段、选择控制、调用 ID、结果信封和会话状态。
  3. 翻译前移除目标接口不支持的 Schema 特性。
  4. 以无副作用影子模式回放生产链路。
  5. 比较工具选择、参数有效性、恢复、延迟和成本。
  6. 先灰度只读工具;幂等与授权测试通过后再开放写工具。

QVeris implementation patternQVeris 实现模式

Provider-native function calling controls the model-facing message loop. MCP can standardize how a client discovers and invokes tool servers. QVeris sits at the capability layer: it helps an agent discover, inspect, route, call, and audit real-world tools and data, while your provider adapter preserves the required OpenAI, Anthropic, or Google protocol.

供应商原生 Function Calling 管理模型侧消息循环;MCP 可以标准化客户端发现和调用工具服务器的方式;QVeris 位于能力层,帮助 Agent 发现、检查、路由、调用并审计真实世界工具与数据,而供应商适配器继续保持 OpenAI、Anthropic 或 Google 所要求的协议。

Discover

Find the capability and inspect its contract before a prompt exposes it.

Call

Route validated arguments to the selected provider or data source.

Evidence

Return provenance, retrieval time, units, and validation status with the result.

发现

在 Prompt 暴露工具前,先找到能力并检查契约。

调用

把已校验参数路由到选定服务商或数据源。

证据

随结果返回来源、检索时间、单位和校验状态。

FAQ

Is function calling the same as tool use?

Usually. The names differ, but the application loop is equivalent: describe tools, receive a structured call, execute outside the model, and return a correlated result.

Which provider has the best function calling API?

There is no universal winner. Test your models and workloads for schema compliance, streaming, parallel behavior, recovery, observability, cost, and migration effort.

Does function calling execute code?

No. The model proposes a call. Your application validates, authorizes, executes, and returns the result.

Should strict mode always be enabled?

Use it where supported, but still validate server-side. Strict mode does not grant permission or guarantee business correctness.

How should parallel calls be handled?

Collect all calls, run only independent work concurrently, and correlate each result by its original call identifier.

How do I prevent duplicate side effects?

Persist an idempotency key derived from the turn, call ID, tool name, and normalized arguments before execution.

Does MCP replace provider function calling?

No. MCP standardizes client-to-tool-server interaction; provider APIs still define the model-facing call-and-result messages.

What does QVeris add?

QVeris adds discovery, inspection, routing, and evidence for real-world capabilities while the adapter manages provider-native messages.

函数调用和工具调用是一回事吗?

通常是。名称不同,但应用循环等价:描述工具、接收结构化调用、在模型外执行,再回传带关联标识的结果。

哪家函数调用 API 最好?

没有通用答案。应针对实际模型与负载测试 Schema、流式处理、并行行为、恢复、可观测性、成本和迁移难度。

函数调用会直接执行代码吗?

不会。模型只提出调用,应用负责校验、授权、执行和回传。

严格模式应该一直开启吗?

支持时可以开启,但服务端仍需校验。严格模式不会授予权限,也不保证业务语义正确。

并行工具调用怎么处理?

先收集全部调用,只并发彼此独立的任务,并按原始调用 ID 关联每个结果。

如何避免重复副作用?

执行前根据会话、调用 ID、工具名和标准化参数生成并持久化幂等键。

MCP 会替代供应商函数调用吗?

不会。MCP 标准化客户端与工具服务器交互,供应商 API 仍规定模型侧调用与结果消息。

QVeris 增加了什么?

QVeris 为真实世界能力补充发现、检查、路由和证据,适配器则管理供应商原生消息。

Official sources官方资料

函数调用 API:供应商对比 | QVeris Guides