
规则写好了,AI 为什么仍可能做出另一种选择?
如果一份权限文件写着“允许写入的目录:空”,你会怎样理解?
很自然的答案是:哪里都不能写。我们研究的一个技能工具,其文档示例也是这样解释的。但将这份配置交给原始加载器,再询问原权限检查器,得到的结果却是:允许。
它不是偷偷执行了写入。这次实验根本没有写业务文件。值得注意的是更早的一步:人读到的约束与程序算出的决定,已经不同了。
三种研究,让我们开始追查规则的去向
Maurits Kaptein 等人的 Runtime Governance 强调执行路径:读过什么,会改变下一步能否发送。Haoyu Wang 等人的 AgentSpec 将条件与执行约束连接起来。Mansura Habiba 合著的 AGENTSAFE,则把能力、限制、监督和保证证据放入共同框架。
我们感兴趣的不是再增加一份原则清单,而是验证:这些原则落实到工程时,哪一段需要额外证据?因此,我们分别运行了公开策略引擎、规则触发模块和技能权限检查器。
这里有一个必须保持的来源区别:AGENTSAFE 尚未找到官方代码;受测的 Bulbasaur Skill CLI 是 Mansura 的另一个相关项目,不能拿它的表现替 AGENTSAFE 做验证。
空列表的两种解释
在技能工具里,我们让真实 YAML 加载器读取配置,再让权限检查器判断路径字符串。
| 配置与输入 | 原检查器的返回 |
|---|---|
| 没写文件写入规则 | 允许 |
明确写 write_paths: [] | 允许 |
允许 /workspace/output/**,访问其内文件 | 允许 |
| 同样规则,访问其他目录 | 拒绝 |
同样规则,输入 /workspace/output/../other.txt | 允许 |
空列表被当成了“没有规则”,不是“没有任何允许项”。最后一项则说明,受测方法按照字符串通配模式比较路径;它本身没有先消解 ..。
这还不足以证明真实运行环境可以越界写文件。调用者可能规范化路径,也可能另有隔离层。本轮证明的是加载器与判断器的行为,以及它和文档示例之间的差别。
更有意思的是,原项目的 29 条权限测试全部通过,其中一条就明确要求“没有规则时允许”。测试并没有失效;它验证了实现选择。真正需要澄清的是:这个选择是否与对用户公开的含义一致?
同一个发送动作,为什么会得到相反决定
Kyvvu 的公开外泄策略提供了另一组清楚的对照。我们用真实引擎与同一个发送动作,只改变输入历史。
公共数据读取后,附带审查记录,结果是允许。改成敏感数据读取,即使仍有审查记录,结果也变成阻止。再加一条审查记录,依然阻止。这项策略把敏感读取视为持续约束,不会被随后的一次审查自动清除。
接着我们做了一个刻意的控制实验:新建引擎,保持相同 Agent 和任务编号,只提供审查记录,不恢复敏感读取历史。它允许了发送;把历史补回来,又恢复阻止。
图 1:改变提供给引擎的历史,发送决定随之改变。来源:kyvvu-paths.json 中 tainted、fresh_engine_same_ids、restored_history 三个本地对照;仅计算决定,没有实际发送,也不证明托管平台恢复失败。
这不是某个平台恢复失败的事故报告。我们主动拿掉了政策所需的信息。实验说明的是:编号相同不能代替历史实际到场。 若系统要在恢复或跨 Agent 交接后继续执行,就需要说明哪些治理历史被恢复、由谁提供,以及缺少时如何处理。
原项目选定的 8 条外泄轨迹测试也全部通过。本轮共做 6 个历史对照,没有真正发消息或外传数据。
规则存在,仍要先被正确触发
AgentSpec 让我们把视线移到更靠前的地方。
我们使用原解析器建立一条 PythonREPL 规则,然后直接调用其触发判断。工具名称精确匹配时,规则触发;名称改成另一个拼写时,同样的文本参数不触发。其他工具的输入若以 PythonREPL 开头,也能触发。
输入类型也有影响:精确匹配的工具名配字典参数能够返回 true;不匹配的工具名配字典参数,会在后续字符串处理处抛出 AttributeError。结束动作配 None 也出现同类错误。
我们没有运行完整 AgentExecutor,因此不能将这个局部结果写成所有 AgentSpec 应用都会失败。它提出的是一个可检查的问题:动作适配层承诺传字符串、字典,还是允许空值?工具改名或封装之后,这份约定还成立吗?
安全条件写得再细,如果触发入口接收的是另一种对象,条件就可能没有机会按预期工作。
从“有规则”走到“规则实际生效”
这几组实验指向不同位置:配置的解释、动作的识别、历史的提供,以及决策最终怎样约束工具。它们需要分别验证,不能压成一个“治理已开启”的绿勾。
可以从三组小问题开始:
- 配置缺失、显式空值、拒绝全部是否有不同表示?文档和测试是否一致?
- 规则能否识别真实工具名与实际参数类型?适配层改变了什么?
- 恢复与交接后,政策所需的历史是否真实存在?引擎拒绝后,工具是否确实没有执行?
最后一问需要真实动作边界实验,本轮的判断器对照不能替它回答。
对专业读者,我们尤其想追问:跨 Agent 交接应该传递完整轨迹,还是一份能够验证且足够保守的治理状态?对使用者,则可以从最简单的反馈开始:界面写“未授权任何目录”时,你是否预期所有写入都被禁止?这种预期应该成为契约测试的起点。
好的治理需要明确约束,也需要证明约束没有在实现途中变成另一种意思。
研究日期:2026-09-17。固定源码版本、kyvvu-engine 0.11.0、全部对照及限制见 实验报告。这些局部实验不证明完整论文效果、真实业务越权或 CodeFlowMu 的产品缺陷。