审批回调看到“无需人工确认”,工具真正执行时却多了默认值,甚至把字符串转成了整数——这不是显示差异,而是权限判断和实际动作没有对齐。OpenAI Agents SDK 0.22.3 修的正是这条缝。
OpenAI 在 2026 年 9 月 17 日 22:19 UTC 发布 openai-agents 0.22.3。发行说明第一项是:让条件审批使用经过校验的工具参数。对应 PR #5066 解释得更具体:装饰器工具现在只准备一次参数;只要校验过程补了默认值、转换了类型,或无法安全判断前后是否一致,就转为人工审批。
这条变化很小,却直接影响有副作用的工具:发邮件、改工单、下单、删文件、调生产接口。审批策略如果只看原始 JSON,而函数执行前还会经过 Pydantic 校验,那么“批准的内容”和“实际动作”可能不是同一份参数。
工具调用通常经过两层语义。第一层是模型给出的 JSON,比如 {"limit":"10"};第二层是 Python 函数真正收到的对象。中间的参数模型会检查字段、补默认值、做类型转换,还可能运行 validator。业务写的条件策略如果只拿第一层做判断,就容易漏掉第二层产生的变化。
默认值尤其隐蔽。调用方没有传 region,审批策略自然也看不到它,但函数签名里的 region="cn" 会在执行时出现。类型转换更容易制造“看起来一样”的错觉:字符串 "10" 和整数 10 展示相近,却可能进入不同的额度分支。自定义 validator 还可能把相对路径展开、把用户名归一化,甚至依据其他字段生成目标资源。
0.22.3 没有尝试猜测这些变化是否安全。它只在能保守证明参数未变化时沿用条件策略;一旦默认值、转换或不可检查的校验参与,就要求显式批准。这是安全设计里常见的原则:无法证明等价,不要自动放行。

0.22.2 与 0.22.3 的参数审批差异
环境是 Windows、Python 3.13.14。执行时间为 2026 年 9 月 19 日。我分别建立两个隔离环境,固定安装:
python -m venv .venv-0222
.venv-0222/Scripts/python -m pip install openai-agents==0.22.2
python -m venv .venv-0223
.venv-0223/Scripts/python -m pip install openai-agents==0.22.3测试工具只有两个:一个会给 region 补默认值 cn,另一个把 limit 声明为整数。条件策略始终返回 False,含义是“无需人工审批”。核心定义如下:
async def policy(ctx, params, call_id):
print("policy sees:", params)
return False
@function_tool(needs_approval=policy, strict_mode=False)
async def ship_order(order_id: str, region: str = "cn") -> str:
return f"{order_id}:{region}"
@function_tool(needs_approval=policy, strict_mode=False)
async def set_limit(limit: int) -> str:
return f"{type(limit).__name__}:{limit}"完整脚本与原始输出保存在本篇本地证据目录。它不调用模型、不需要 API Key,也没有连接生产系统。
第一组输入只传 {"order_id":"A-1"}。
第二组输入传 {"limit":"10"}。
作为对照,当调用方明确传入 region:"cn",或原生传入整数 10,0.22.3 能证明参数未变化,仍会调用条件策略并自动放行。

0.22.3 的保守审批流程
这说明修复并不是“所有工具都弹确认框”,而是只在审批对象和执行对象可能不一致时 fail closed。官方 PR 还覆盖 Runner、流式运行和 Realtime;本机只复现了本地审批准备路径,没有声称验证远端模型或真实生产链路。
如果项目使用 needs_approval 回调,建议把下面四类输入放进合同测试:
升级命令可以很简单:
python -m pip install --upgrade "openai-agents==0.22.3"
python verify_approval_args.py但生产验收不能只看依赖安装成功。至少要断言三件事:参数不变时策略还能自动决策;参数发生变化时一定产生人工中断;拒绝后工具主体没有副作用。
还要注意版本回滚。若服务回退到 0.22.2,同一组合同测试应该立即暴露行为差异,而不是等线上出现一次误操作才发现。建议把 SDK 版本、输入 JSON、审批结果和工具是否执行写进测试报告;真实业务参数需要脱敏,只保留能解释分支的字段。

升级时要覆盖的四类参数变化
第一,0.22.3 解决的是条件审批与实际参数的错位,不等于审批界面一定展示了所有校验后细节。自己的审批 UI 仍应清楚呈现资源、动作、范围和风险。
第二,示例为了离线复现调用了 SDK 私有审批函数;它适合做诊断,不是建议业务代码依赖的公共 API。生产代码继续使用公开的 function_tool、Runner 和中断/恢复流程。
第三,日志里可能包含路径、客户编号或业务参数。为审计保存“为什么触发审批”和字段差异即可,不要把密码、Token、Cookie 或完整敏感正文写进日志。
这次修复挡住的是一类参数错位,不代表有审批就可以让工具直接碰生产。至少还需要三层约束。
第一层是工具定义本身。能用枚举就不要接任意字符串;金额、数量、路径和资源 ID 要有明确范围;高风险动作与只读查询不要塞进同一个函数。输入越模糊,审批者越难判断真实影响。
第二层是执行前的独立 guardrail。它不应该只重复审批策略,而要检查租户、资源所有权、允许的域名或目录、请求幂等键,以及当前环境是否真的允许写入。人工点了“同意”,也不能绕过这些硬限制。
第三层是副作用后的可核对证据。工具返回“成功”不够,要记录平台或服务端的资源 ID、状态和时间;涉及删除、发送或扣费时,应有可恢复或补偿路径。这样即使审批逻辑正确,执行层异常也不会被一句成功文案掩盖。
如果短期不能升级,最小缓解不是在回调里手工猜 Pydantic 会怎么转换,而是让高风险工具统一要求审批,并在执行前重新校验范围。手写一套平行转换逻辑很容易再次漂移;升级 SDK 加合同测试,才是可持续做法。
条件审批最危险的错觉,是“回调运行过,所以动作已经被检查过”。真正需要保证的是:审批时看到的语义,必须和执行时采用的语义一致。无法证明一致,就让人确认一次。这次 0.22.3 的价值,不是多一个弹窗,而是把不确定性留在副作用发生之前。
更新时间:2026-09-20
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight All Rights Reserved.
Powered By 61893.com 闽ICP备11008920号
闽公网安备35020302035593号