Async Tool Calling 适合“工具较慢,但模型还有独立内容可以继续处理”的 Responses API 工作流:在应用执行的 function 或 custom 工具上设置 async:true,应用立即登记并启动作业;完成后在后续请求中用原始 call_id 回传结果。它不会把作业交给 OpenAI 托管,也不是 Background mode。
OpenAI Async Tool Calling 怎么用?
先判断是否真的需要异步工具
普通函数调用在模型发出调用后会暂停当前回合,直到应用返回工具结果。异步工具允许模型先继续生成不依赖该结果的内容、调用其他合适工具,或在真正需要结果时再等待。若后续每一步都依赖工具结果,就没有可并行的工作,普通同步循环通常更简单。
| 任务形态 | 推荐方式 | 关键边界 |
|---|---|---|
| 单次快速查询,下一步立即依赖结果 | 普通 Function Calling | 减少登记与续接复杂度 |
| 慢查询可提前启动,期间有独立工作 | Async Tool Calling | 应用仍负责执行、状态和重试 |
| 整个模型响应需要脱离连接长时运行 | Background mode | 异步的是响应生成,不是你的工具作业 |
| 用 JavaScript 聚合多个已授权工具 | Programmatic Tool Calling | 不能把 async 工具配置给 PTC |
兼容范围先锁定
- 官方当前说明支持 GPT-6 Astra 及之后模型;上线前仍应读取模型页。
- 仅适用于应用自行执行的
function和custom工具。 - 不适用于 Web Search、File Search 等托管内置工具。
- 使用直接工具调用,不要为 Programmatic Tool Calling 配置异步工具。
- Multi-agent mode 中不要把 async 工具与 parallel tool calls 组合。
最小配置:在工具定义上设置 async:true
工具调用项目本身也会带有 async:true。下面同时加入全会话唯一的 task_handle,方便应用登记真实后台作业;不要把它误当成 OpenAI 自动生成的任务 ID。
const tools = [{
type: "function",
name: "lookup_price",
description: "Look up one product price.",
async: true,
strict: true,
parameters: {
type: "object",
properties: {
sku: { type: "string" },
task_handle: { type: "string" }
},
required: ["sku", "task_handle"],
additionalProperties: false
}
}];
const first = await client.responses.create({
model: "gpt-6-astra",
tools,
instructions:
"Start the lookup early. Continue independent work, " +
"but do not invent the pending result.",
input: "查询 SKU-123 的价格,同时先整理不依赖价格的检查项。"
});响应可能同时包含异步调用和一段可用回答。不要因为已经出现文本就把异步调用丢掉,也不要在工具结果回来前让模型猜测结果。
应用端必须维护任务登记表
收到完整调用项目后,先验证名称与参数,再把 task_handle、原始 call_id、实际作业 ID、状态、租户和截止时间绑定。句柄要在整个会话内唯一,包括已经完成的任务和重复查询。
| 字段 | 用途 | 常见错误 |
|---|---|---|
task_handle | 模型和应用识别业务任务 | 复用旧句柄导致结果串单 |
call_id | Responses API 关联原始工具调用 | 回传时新建 ID 或用错调用 |
| job_id / status | 应用队列、Worker 和重试状态 | 把 OpenAI 当成后台任务系统 |
| latest_response_id | 继续最新对话状态 | 期间续接后仍引用过期响应 |
工具完成后,用原始 call_id 回传
function 使用 function_call_output,custom 工具使用 custom_tool_call_output。如果作业期间发生其他对话轮次,previous_response_id 指向最新响应;但结果仍必须绑定最初调用的 call_id。
const call = first.output.find(
item => item.type === "function_call" &&
item.name === "lookup_price"
);
const job = runLookup(JSON.parse(call.arguments));
// 期间若有其他 Responses 续接,要持续更新这个值
let latestResponseId = first.id;
const result = await job;
const resumed = await client.responses.create({
model: "gpt-6-astra",
tools,
previous_response_id: latestResponseId,
input: [{
type: "function_call_output",
call_id: call.call_id,
output: JSON.stringify(result)
}]
});使用流式输出时,可在完整的调用项目到达后立即启动作业,同时继续消费响应事件。不要在参数仍是增量片段时提前执行。
什么时候需要自定义 wait 工具?
官方示例里的 wait_for_tasks 不是内置 Responses 工具,而是应用定义的普通同步函数。只有当模型下一步依赖尚未完成的结果时才等待;结果已经完成时,先把每个工具结果按原始 call_id 回传,再返回 wait 调用自己的状态。
- 异步工具参数包含唯一
task_handle。 - 应用登记每个 handle 对应的原始 call_id 与真实作业。
- 模型调用同步 wait 工具并传入非空、去重后的 handles。
- 应用只等待所请求的作业,不阻塞无关任务。
- 下一次请求先发送新完成的工具结果,再发送 wait 的状态输出。
设置服务端截止时间、可取消状态和明确的 pending / completed / failed 结果;失败要返回结构化错误,让模型决定重试、降级或向用户说明,而不是静默等待。
异步询问用户也遵循同一模式
需要用户补充偏好时,可以定义 async:true 的自有函数。应用展示问题、保存原始 call_id,并让模型继续处理独立工作;用户回答后再把答案作为该调用的输出回传。不要在展示问题时就用“已展示”完成工具调用。若用户关闭或超时,返回明确的无答案状态。
可靠性、安全与幂等
- 工具启动前校验租户、资源、权限与参数,不把模型生成的句柄当授权。
- 用稳定幂等键防止网络重试重复扣款、重复写入或重复发送。
- 为登记、执行、完成、回传和模型消费分别记录时间戳与错误。
- 结果回传前核对任务仍属于当前会话、用户和原始 call_id。
- 高影响写操作保留用户确认、应用审批和可撤销路径。
- 设定最大并发、超时、重试次数、结果大小和过期清理策略。
成本与性能怎么评测?
异步不是免费并行。它可能减少模型等待,但会增加队列、状态存储、续接和额外响应轮次。以普通 Function Calling 为基线,在同一批真实任务上比较:
- 首个可用回答时间、最终完成时间和 P95/P99 延迟。
- 输入、输出、缓存和总 Token,以及每次成功任务成本。
- 工具启动到完成时间、队列等待、重试和超时率。
- 串单、重复执行、遗失结果与错误降级率。
- 最终答案正确率、是否使用真实工具结果、是否提前猜测。
常见错误与排查顺序
- 模型仍然停住:确认所选模型支持,工具定义与返回调用项目确实有
async:true,并且提示中存在可独立完成的工作。 - 结果无法关联:检查是否保留原始
call_id,输出类型是否与 function/custom 匹配。 - 续接到旧对话:期间若产生新响应,更新
latest_response_id。 - wait 后仍无结果:先登记所有 launch,再处理依赖 wait;回传顺序先工具结果、后 wait 状态。
- 任务串单:检查 task_handle 是否全会话唯一,并验证租户与会话归属。
- 内置工具不异步:Hosted built-in 工具不在兼容范围。
- PTC 或 Multi-agent 冲突:改用直接调用;Multi-agent 下不要同时使用 parallel tool calls。
上线前检查清单
- 重新核对模型与工具兼容范围,不依赖旧示例。
- 同步路径和异步路径都能完成,并有相同权限校验。
- 完整保存 task_handle、call_id、job 状态和最新 response ID。
- 流式处理只在完整调用项目到达后启动任务。
- 实现超时、取消、失败、重试、幂等和结果过期。
- 用故障注入验证重复事件、乱序结果、断线和 Worker 重启。
- 监控端到端延迟、Token、单位成功成本与正确率。
常见问题
OpenAI Async Tool Calling 和普通 Function Calling 有什么区别?
普通 Function Calling 会在调用后暂停模型当前回合,等待应用返回结果;Async Tool Calling 在函数或 custom 工具定义中设置 async:true 后,模型可先继续处理不依赖该结果的内容。工具仍由你的应用执行,完成后用原始 call_id 回传。
Async Tool Calling 和 Background mode 是一回事吗?
不是。Background mode 让响应生成本身异步运行;Async Tool Calling 让模型在你的应用执行工具时继续工作。它不会把工具任务交给 OpenAI 托管,也不会替你创建、监控或重试后台作业。
哪些模型和工具支持 Async Tool Calling?
官方当前说明支持 GPT-6 Astra 及之后模型;适用于由应用执行的 function 和 custom 工具,不适用于托管内置工具。应使用直接工具调用,不能把 async 工具配置给 Programmatic Tool Calling。
异步工具完成后怎样把结果交回模型?
在后续 Responses 请求的 input 中发送 function_call_output 或 custom_tool_call_output,call_id 必须使用原始异步调用的 call_id。若期间有其他对话续接,previous_response_id 应指向最新响应,但工具结果仍绑定最初的 call_id。
wait_for_tasks 是 OpenAI 内置工具吗?
不是。官方示例中的 wait_for_tasks 是应用自己定义的普通同步函数。应用要为每个异步调用维护全会话唯一的 task_handle,将它映射到原始 call_id 和实际作业,并只在模型下一步依赖未完成结果时等待。
Async Tool Calling 能与 Multi-agent 的 parallel tool calls 一起用吗?
官方当前兼容说明要求在 Multi-agent mode 中不要把 async 工具与 parallel tool calls 组合。先按单一并发策略设计,并用真实任务验证顺序、结果归属和失败恢复。
Async Tool Calling 一定更快或更省钱吗?
不保证。它只在慢工具可以提前启动、且模型有独立工作可做时可能降低等待时间;任务登记、续接、重试和额外模型轮次也会增加复杂度与成本。应比较端到端延迟、Token、成功率、重试和单位成功成本。
官方资料
- OpenAI:Async tool calling
- OpenAI:Function calling
- OpenAI:Background mode
- OpenAI:Streaming API responses
- OpenAI:API deployment checklist
如果任务需要多语言命令、文件转换或自有运行环境,请参阅 OpenAI Shell 工具教程;先区分托管容器与本地执行,并按最小权限限制文件、网络和命令。
本文核对日期为 2026-11-01。模型支持、异步字段、工具类型、响应项目和兼容限制可能调整;生产上线前请重新读取 Async Tool Calling、Function Calling、Background mode、Streaming 与 Deployment checklist 官方页面。