权限漏斗与人机审批:Agent 不敢乱来的原因

phenix-fledgling Lv5

Agent 能执行 shell、能写文件,安全体系不是可选项。三个开源实现的权限设计惊人一致,可以总结成一个漏斗

规则层:三元组 + findLast

每条规则是 (操作类型, 匹配模式, 动作),动作只有三种:allow 放行、ask 问人、deny 拒绝。求值规则是 findLast——后写的规则覆盖先写的(OpenCode 的做法),于是配置可以这样表达:

bash *          → ask     先默认都要问
bash rm *       → deny    删除直接拒,问都不问
bash git push*  → deny
read *          → allow   只读随便

默认值必须是 ask(fail-safe):没规则覆盖的新操作宁可打扰人,不可默认放行。

执行层:每个工具调用过闸

循环里每个 tool_call 派发前都过一次求值。allow 直接跑;deny 直接回填”权限被拒绝”(模型会收到并调整策略);ask 挂起,等人的答复。

再叠一层 doom loop 检测:同名同参的调用连续出现 3 次,说明模型卡死在重试里,强制升级为 ask。

审批层:把”问人”做成好体验

关键洞察来自 ACP 协议的 request_permission 语义:审批答复不是二选一,而是四选一——允许本次 / 总是允许 / 拒绝本次 / 总是拒绝。”总是允许”会沉淀成一条新规则(Codex 叫 amendment),下次同类操作不再打扰。审批系统于是有了学习能力:越用越安静。

我把这套语义落在了钉钉互动卡片上:Agent 要写文件时,钉钉弹一张卡片(操作、目标、风险等级 + 三个按钮),点击经回调唤醒挂起的审批协程,卡片就地更新成回执。超时 5 分钟自动拒绝。

一个真实教训

审批挂起期间我重启了进程,等待中的回合被杀,会话里留下孤儿 tool_call,第二天恢复会话直接被模型端拒收。修复:恢复时给所有无结果的 tool_call 补 [interrupted] 占位。安全体系的每个组件都会和会话持久化发生化学反应——这类跨模块的坑,只有真跑起来才能撞见。

没做的部分(诚实边界)

OS 级沙箱(Codex 的 Landlock/Seatbelt)和 AI 审 AI(Guardian)我都没做——个人档位靠”规则 + 人审 + 危险前缀”三道够用,但要对外服务,沙箱是下一个必须补的档位。

  • 标题: 权限漏斗与人机审批:Agent 不敢乱来的原因
  • 作者: phenix-fledgling
  • 创建于 : 2026-07-29 12:00:00
  • 更新于 : 2026-07-29 02:35:18
  • 链接: https://blog.xugua.xyz//post/权限漏斗与人机审批:Agent 不敢乱来的原因.html
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论