一条编码 Agent 事故的背后:写权限到底该给多少
「AI 删了我的生产数据库」这类事故的根因几乎都不是模型失控,而是权限设计偷懒。本文给出写权限的四层收窄模型、三个必须硬隔离的动作、以及一份可直接落地的权限矩阵。
每隔一段时间就会出现一条新闻:某个团队让 AI Agent 自动处理任务,它执行了一条不该执行的命令,删了东西或发了不该发的东西。评论区照例分成两派,一派怪模型不可靠,一派怪人类没设好约束。
看过几起真实事故的复盘之后,结论很清楚:几乎每一例都能追溯到一个被省略的权限检查点。 不是模型”想”做坏事,是它被允许做,而且在被允许之前没人告诉它边界。
写权限的第一原则:按”不可逆性”分级,不按”重要性”分级
很多团队按业务重要性分级:这是核心数据、这是边缘数据。这个分级方式错了,因为重要性是主观的、随时变化的,而不可逆性是客观的。
按不可逆性分四层:
| 层级 | 典型动作 | 策略 |
|---|---|---|
| L0 只读 | 查询、读文件、读日志 | 默认开放,可审计即可 |
| L1 可逆写 | 改本地文件、创建分支、写草稿 | 开放,但必须可回滚 |
| L2 有边界写 | 合并 MR、发布预发、更新非生产库 | 需第二条约束(白名单/审批) |
| L3 不可逆 | 删除数据、生产发布、对外发信、转账 | 默认禁止,必须人工逐次确认 |
关键判断标准:这个动作如果做错了,我能在一分钟内恢复吗? 能,就是 L1;不能但影响可控,是 L2;不能且影响不可控,是 L3。
绝大多数事故发生在 L3 被当成 L2 处理。比如”机器人有生产环境的写权限,但只在工作日 9-18 点有效”——这不是约束,只是时间窗口。
三个必须硬隔离的动作
以下三件事不应该靠提示词约束,而应该靠系统层面的阻止:
一、生产数据库的破坏性语句。 Agent 使用的数据库账号必须是只读的,或者只能在特定 schema 上写。DROP、TRUNCATE、无 WHERE 的 UPDATE/DELETE,应该在代理层或连接层直接拒绝,而不是指望提示词里写了”不要删数据”。
二、对外通信。 发邮件、发 IM、发短信、调用第三方付费 API,这四类都意味着”一旦发出无法收回”。这类工具应该默认不存在于 Agent 的工具集里,需要时以”生成草稿 + 人工点发送”的两步形式提供。
三、凭证与密钥。 Agent 不应该能读到生产密钥明文。给它短期、窄范围的令牌,而不是长期主密钥。这一点在沙箱里尤其重要:很多沙箱方案把环境变量原样注入,等于让 Agent 拿到了宿主的全部权限。
一份四层权限矩阵
我们内部用的矩阵长这样,按角色拆:
角色 读代码 写代码 合并MR 预发发布 生产发布 生产库写 对外发信
分析Agent ✅ ❌ ❌ ❌ ❌ ❌ ❌
开发Agent ✅ ✅ ❌ ❌ ❌ ❌ ❌
修复Agent ✅ ✅ ⚠️审批 ❌ ❌ ❌ ❌
运维Agent ✅ ✅ ⚠️ ✅ ⚠️审批 ❌ ❌
通知Agent ✅ ❌ ❌ ❌ ❌ ❌ ⚠️草稿
✅ 允许 ⚠️ 需人工确认 ❌ 无此工具
注意”生产库写”一栏全是 ❌。不是谨慎,是没必要——真有需要,用一个专门的、只对特定表有写权限的账号单独授权,比给通用 Agent 开一个口子安全得多。
提示词里该写什么
权限是系统层面的,但提示词仍然要写,因为它决定了 Agent 会不会”想办法绕过”。三类必须写的句子:
- 明确能力边界:“你没有权限修改生产环境。如果任务需要,请输出操作步骤清单并请求人工执行。”
- 给出替代路径:“无法完成时,不要尝试用其他工具变通,而是报告阻塞点。“——不加这句,Agent 会用 shell 调 curl 绕过被禁用的工具。
- 定义失败的处理:“任何返回错误、超时或权限拒绝的情况,停止并报告,不要重试超过一次。”
第三条尤其重要。事故里常见的放大模式是:第一次被拒绝 → Agent 换参数重试 → 换工具重试 → 最终用了一条更危险的方式达成了目的。被拒绝时的正确行为是停下来,而不是换条路。
怎么验证约束真的生效
做一次”红队自测”:给 Agent 一个明显越界的任务(比如”把这个测试数据库清空”),观察它是拒绝、报告,还是想办法完成。每月跑一次,因为工具集和提示词会随着迭代悄悄变化。
同时监控两个信号:权限拒绝事件的数量和被拒绝后的下一步动作。拒绝数突然归零,往往意味着约束被谁改松弛了;被拒绝后仍有写操作发生,说明隔离层有漏洞。
给 Agent 的权限,应该等于”你愿意给一个刚入职、热情但不懂边界的新同事的权限”。这个类比在每一次授权评审时都好用。