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、适配器、控制策略与生产验证。
Decision brief决策摘要
TL;DR
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.
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 schema mode improves argument shape. Your server must still validate values, authorize the caller, control side effects, and treat tool output as untrusted.
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,并在可信后端执行工具。
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 单独保存,适配器才能重建正确的回传消息。
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 协议对比
| Concern | OpenAI | Anthropic | Google Gemini |
|---|---|---|---|
| Tool definition工具声明 | type: function + function schema | name, description, input_schema | type: function + parameters in Interactions |
| Call output调用输出 | function_call | tool_use content block | function_call step |
| Correlation key关联键 | call_id | tool_use_id | call_id; preserve signature/state where required |
| Return result结果回传 | function_call_output | tool_result in the next user message | function_result |
| Strict schema严格 Schema | strict: true; strict object requirements | strict: true supported | Supported schema subset varies by API/model |
| Parallel calls并行调用 | Supported; can disable | Multiple tool_use blocks; can disable | Parallel and compositional calling supported |
| Stateful continuation有状态续接 | Use response/conversation state or send prior items | Send the next user message with result blocks | previous_interaction_id in Interactions |
| 关注点 | OpenAI | Anthropic | Google Gemini |
|---|---|---|---|
| 工具声明 | type: function 加函数 Schema | name、description 与 input_schema | type: function 加 Interactions 中的 parameters |
| 调用输出 | function_call | tool_use 内容块 | function_call 步骤 |
| 关联键 | call_id | tool_use_id | call_id;必要时保留签名与状态 |
| 结果回传 | function_call_output | 下一条用户消息中的 tool_result | function_result |
| 严格 Schema | strict: 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 术语,以及旧版 generateContent 的 functionCall/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,不要默认强制调用。
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 标记。
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 中,函数调用是包含 id、name、arguments 的 step;回传引用该调用 ID 的 function_result。有状态模式使用 previous_interaction_id,无状态模式则必须完整重放历史 step,包括所需的思考签名元数据。
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.
每个适配器只负责四件事:序列化工具定义、提取调用、序列化结果、保留供应商状态。校验、授权、执行、重试和证据应位于共享基础设施。
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: falseand 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生产注意 |
|---|---|---|
| Auto | The model may answer or call tools.模型可以直接回答或调用工具。 | Best default for mixed conversations.适合作为混合对话默认值。 |
| Required / forced | A workflow step must obtain structured data.流程必须取得结构化数据。 | Do not force irreversible actions.不要强制执行不可逆动作。 |
| Strict | You need dependable argument shape.需要更稳定的参数形状。 | Still enforce business rules server-side.业务规则仍必须在服务端执行。 |
| Parallel | Calls 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安全、成本与延迟控制
Schema validation answers “is this shaped correctly?” Authorization answers “may this identity perform this action on this resource?” Both are required.
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.
Persist a deterministic idempotency key before side effects. Retries must return the previous outcome instead of repeating an order, message, payment, or mutation.
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 Injection | Minimize, 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 得出一个笼统“准确率”。应对每家供应商运行同一份版本化测试集,并按失败类型分别报告。
Migration checklist between providers跨供应商迁移清单
- Freeze a canonical tool registry and version every schema.
- Map definition fields, tool-choice controls, call IDs, result envelopes, and conversation state.
- Remove unsupported schema features before translation.
- Replay production traces in shadow mode without side effects.
- Compare call selection, argument validity, recovery, latency, and cost.
- Canary read-only tools first; enable write tools only after idempotency and authorization tests pass.
- 冻结统一工具注册表,并为每个 Schema 建立版本。
- 映射工具字段、选择控制、调用 ID、结果信封和会话状态。
- 翻译前移除目标接口不支持的 Schema 特性。
- 以无副作用影子模式回放生产链路。
- 比较工具选择、参数有效性、恢复、延迟和成本。
- 先灰度只读工具;幂等与授权测试通过后再开放写工具。
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 所要求的协议。
Find the capability and inspect its contract before a prompt exposes it.
Route validated arguments to the selected provider or data source.
Return provenance, retrieval time, units, and validation status with the result.
在 Prompt 暴露工具前,先找到能力并检查契约。
把已校验参数路由到选定服务商或数据源。
随结果返回来源、检索时间、单位和校验状态。
FAQ
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.
There is no universal winner. Test your models and workloads for schema compliance, streaming, parallel behavior, recovery, observability, cost, and migration effort.
No. The model proposes a call. Your application validates, authorizes, executes, and returns the result.
Use it where supported, but still validate server-side. Strict mode does not grant permission or guarantee business correctness.
Collect all calls, run only independent work concurrently, and correlate each result by its original call identifier.
Persist an idempotency key derived from the turn, call ID, tool name, and normalized arguments before execution.
No. MCP standardizes client-to-tool-server interaction; provider APIs still define the model-facing call-and-result messages.
QVeris adds discovery, inspection, routing, and evidence for real-world capabilities while the adapter manages provider-native messages.
通常是。名称不同,但应用循环等价:描述工具、接收结构化调用、在模型外执行,再回传带关联标识的结果。
没有通用答案。应针对实际模型与负载测试 Schema、流式处理、并行行为、恢复、可观测性、成本和迁移难度。
不会。模型只提出调用,应用负责校验、授权、执行和回传。
支持时可以开启,但服务端仍需校验。严格模式不会授予权限,也不保证业务语义正确。
先收集全部调用,只并发彼此独立的任务,并按原始调用 ID 关联每个结果。
执行前根据会话、调用 ID、工具名和标准化参数生成并持久化幂等键。
不会。MCP 标准化客户端与工具服务器交互,供应商 API 仍规定模型侧调用与结果消息。
QVeris 为真实世界能力补充发现、检查、路由和证据,适配器则管理供应商原生消息。
