工具调用参数校验失败后怎样安全重试
来源:17golang原创
时间:2026-09-12 12:46:49 215浏览 收藏
工具调用参数校验失败时,最安全的处理不是把原请求整段重放,而是把“解析失败、业务不满足、工具已执行”分成三种状态。先在应用侧校验模型生成的 JSON,再把带有 tool_call_id 的错误结果交回模型,让它只修正参数;真正可能修改订单、发送消息或写入数据的工具,还要用幂等键和有限重试保护。
官方地址:https://platform.openai.com/docs/guides/function-calling
strict=true负责提高 Schema 遵循度,不能替代应用侧业务校验。- 校验失败要回传工具错误,不要在副作用工具前盲目重放。
- 每次修正都记录校验类型、调用 ID、幂等键和重试次数。
为什么一次参数校验失败不能直接重放工具
模型生成的参数有两类问题。第一类是 JSON 无法解析、字段缺失、类型不对或出现额外字段;第二类是 JSON 合法,但业务上不能执行,例如退款金额超过可退余额、收件人为空,或者同一个请求已经被处理。前一类适合让模型修正,后一类要把明确原因交给模型或转人工,不能靠多试几次碰运气。
尤其要注意“工具有没有真正执行”。如果服务端已经调用了扣款、发信或写库接口,再因为响应解析失败而重放整个 assistant 消息,就可能产生重复副作用。重试的对象应该是参数修正或查询型工具;写操作必须由幂等键决定是否允许再次落地。
先把校验放在副作用之前
工具定义可以启用严格 Schema。官方文档建议严格模式下对象设置 additionalProperties: false,并把字段列入 required;可选字段可以用包含 null 的类型表达。它能减少“字段名写错”这类错误,但库存、权限、金额和状态机仍然属于应用规则。
from json import JSONDecodeError
def validate_tool_call(tool_call, schema_validator):
# 只解析和校验参数,不在这个函数里执行真实工具。
try:
arguments = json.loads(tool_call.function.arguments)
except JSONDecodeError as exc:
return None, {"kind": "invalid_json", "message": str(exc)}
# Schema 校验拦截缺字段、类型错误和未声明字段。
errors = list(schema_validator.iter_errors(arguments))
if errors:
return None, {"kind": "schema_error", "message": errors[0].message}
# 业务校验只读数据;通过后才允许进入副作用工具。
if arguments["amount"]

这段代码的关键是返回结构化错误,而不是在校验函数里偷偷调用工具。生产实现还应给写操作生成请求级幂等键,例如由业务订单号和动作类型组成,并在真正写入前检查该键是否已经成功消费。
用工具错误结果让模型修正,而不是重放副作用
校验失败后,应用应该保留原 assistant 工具调用,并使用同一个调用 ID 发送工具角色消息。消息里说明错误类型、缺失字段和可修正范围,不要把数据库内部堆栈、密钥或完整隐私数据直接暴露给模型。模型收到反馈后可以生成新的工具调用;应用仍要重新解析、重新校验,不能因为“这是第二次”就跳过检查。
def tool_error_message(tool_call, error, attempt):
# 将错误限制在可修正信息,避免泄露内部实现细节。
payload = {
"ok": False,
"error_type": error["kind"],
"message": error["message"],
"retryable": error["kind"] in {"invalid_json", "schema_error"},
"attempt": attempt,
}
return {
"role": "tool",
"tool_call_id": tool_call.id, # 必须对应这一次工具调用。
"content": json.dumps(payload, ensure_ascii=False),
}
对“参数字段缺失”可以允许模型修正;对“权限不足、余额不足、资源不存在”通常只反馈一次并停止自动重试。若业务工具已经成功执行,后续模型回合只能读取执行凭证,不能再次提交同一写操作。

strict Schema 和业务校验怎么分工
| 层次 | 检查内容 | 失败后的动作 |
|---|---|---|
| 生成约束 | 字段名、类型、枚举、对象结构 | 让模型根据错误修正参数 |
| 应用校验 | 权限、库存、金额、资源状态 | 给出可理解原因,必要时停止 |
| 副作用保护 | 幂等键、执行凭证、重复提交 | 拒绝重复落地,转查询或人工 |
可以把 strict 看成输入形状的护栏,而不是安全授权。OpenAI 的工具调用流程仍要求应用接收调用、执行自己的代码,再把工具输出发回模型;因此,最终执行权必须留在服务端。
上线时的重试边界要写死
建议为一次用户请求设置很小的参数修正预算,例如最多两次。预算耗尽后记录原始参数和最后错误,让用户补充信息或进入人工队列。日志至少包含 request_id、tool_call_id、error_type、attempt、idempotency_key、validated_at 和 executed_at。只要看到同一幂等键出现两次成功执行,就应立即按业务预案止损,而不是继续增加重试次数。
常见问题
开启 strict 后还需要 JSON Schema 校验吗?
需要。strict 主要约束模型生成的参数形状,业务范围、权限和资源状态仍必须由应用检查。
校验失败要不要重新请求模型?
可以,但应把错误作为对应 tool_call_id 的工具结果回传,并限制次数;不要重放已经产生副作用的工具调用。
查询工具和写入工具的重试策略一样吗?
不一样。查询通常可在超时后有限重试,写入必须先确认幂等键、执行状态和服务端凭证。
-
485 收藏
-
278 收藏
-
483 收藏
-
291 收藏
-
493 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习