
写了"始终审批",AI 为什么还是执行了?
给工具加审批时,正常的"执行"和"等待"都测了,你会不会漏掉"审批设置本身写错了"?我们把文字 "always" 放进配置,结果工具直接运行了一次。 给 AI 加一道"执行前先问我"的审批,通常是为了多一层把关。那么,如果这道审批本身设置错了,接下来应该发生什么?
直觉上,至少应该先停下来,告诉我们哪里需要修改。
我们做的一个实验却出现了相反结果:把审批设置填成文字"always",也就是"始终",工具直接运行了一次。换上候选修复后,同样的输入终于报错,工具没有运行。
值得研究的地方就在这里:一个本想收紧权限的设置错误,为什么反而变成了直接执行?
"意思很明确",不代表设置有效
这个反例来自 DeepanshuPal 提交给 OpenAI Agents Python 的修复提案。这是一个帮助开发者把 AI 与工具连接起来的程序库。
我们在做多 AI 助手协作系统,会格外留意执行前的审批。这个来源吸引我们,是因为它把一个大问题缩小成了可以验证的小问题:当审批设置无法识别时,程序会停下,还是继续?
这里先分清一件事:实验中的"always"填在程序配置里,不是用户在聊天窗口对 AI 说的话。问题发生在工具执行前的判断程序,也不是模型故意不听指令。
这项设置原本接受"需要审批"或"不需要审批"这样的明确选项,也允许交给一小段程序临时判断。文字"always"不属于它接受的格式。旧判断遇到这种错误,没有报错,而是落到了"不需要审批"。
人读懂了这个词,程序却没有把它当作有效设置;更糟的是,无效设置被当成了继续执行的理由。
我们让工具留下记录,看它究竟有没有动手
为了把"有没有执行"看清楚,我们使用一个本地工具:每运行一次,就在内存列表里留下一条记录。AI 服务由测试程序替代,审批判断和工具调用入口则使用项目的实际代码。
前后对照只替换审批判断方法,其他代码保持一致。这样,结果变化才能具体对应到这一个判断上。
| 我们交给程序的输入 | 原判断方法 | 候选修复 |
|---|---|---|
| 明确不需要审批 | 执行一次 | 执行一次 |
| 明确需要审批 | 不执行,等待审批 | 不执行,等待审批 |
| 不被接受的文字"always" | 执行一次 | 报错,不执行 |
| 数字 1、空值、空对象,分别测试 | 每种都执行一次 | 每种都报错,不执行 |
| 让一段程序回答:不需要 / 需要 | 分别执行 / 等待 | 分别执行 / 等待 |
| 负责判断的程序没有返回答案 | 执行一次 | 仍然执行一次 |
前四行说明,修复确实挡住了受测的四类无效设置。正常的执行和等待行为也保留了。
但最后一行,留下了另一个问题。
判断程序没给答案,也算"不需要审批"吗?
有些工具不能用一个固定选项决定是否需要审批。开发者可以提供一段判断程序,根据本次动作给出"需要"或"不需要"。
我们故意让这段程序没有返回答案。结果是:即使换上候选修复,工具仍然执行了一次。
原因在于,这次"提供了一段程序"本身符合设置格式;但程序算出的空结果,又被转换成了"不需要审批"。设置格式正确,并不保证它最后给出了有效答案。

图 1:两种错误经过不同的判断。来源:本轮审批实验记录 sdk.json;观察对象是本地工具调用。
我们没有把它直接称为新漏洞:这段判断程序原本就应该返回明确答案,实验故意违反了这个约定。它的价值,是帮助我们把下一步问得更准确:
如果负责决定是否审批的程序出错或忘了回答,执行前是否还应再检查一次,而不是把空结果当成允许?
其中,"忘了回答"已经做了对照;"抛出错误"等其他情况仍需补充实验。不能用这一行结果代替所有错误场景。
读完以后,可以检查什么?
检查审批功能时,除了"应该执行"和"应该等待",还可以加一个场景:设置本身坏了。然后同时查看错误提示和工具留下的记录,确认它真的停下了。
对于开发者,值得继续讨论的是:由谁检查判断程序的答案,哪些无效结果必须拒绝?对于使用者,如果审批出了问题,你是否希望明确看到"设置有误,这次动作没有执行",并能查到这次动作的记录?
这才是这次反例带来的收获:审批不仅需要一个正常答案,也需要一份明确的"答不出来时怎么办"的约定。
实验细节与复核入口
本轮使用候选提交 b6c2cef 的 RealtimeSession._handle_tool_call 入口;对照只换回 fbf59a4 的 _function_needs_approval 方法,属于单方法消融,不是两套完整发行版。记录工具只向 Python 列表追加数据,没有真实云端请求。
十种输入分别在两种模式运行。其中 needs_approval 的非法顶层值为字符串 "always"、整数 1、None 与空对象;负责判断的回调返回 None 是另一种、刻意不符合返回契约的输入。异步回调返回 false 的正常路径也保持执行。
原项目的 31 项审批测试:候选全部通过;换回前身方法后 30 项通过、非法设置一项失败。没有执行作者提到的全部实时会话测试,也未验证 CodeFlowMu 的对应路径。
你的审批检查程序没有给出有效答案时,工具会停下,还是继续?