不可逆操作
预演、二次确认、延迟执行与回滚设计。
一句话理解:对不可逆操作,要把“一步做完”拆成“先看效果、再确认、晚点生效、留好退路”——预演让人知道会发生什么,二次确认让人想清楚,延迟执行给人反悔的时间,回滚设计让做错也能补救。
有些动作做错了可以改回来:改错的订单状态再改一次,建错的工单关掉就好。但另一些动作做错了就是做错了:钱退出去了、邮件发给了三千个客户、生产数据库的表被删了、代码被强制推送覆盖了别人的提交。
Agent 的特点是执行快、执行多、偶尔犯错。人手工操作时,一个不可逆操作前往往会本能地停顿一下;Agent 没有这种本能。本课要做的,就是把“停顿一下”设计进系统里。
先识别:哪些操作是不可逆的
不可逆并不只是“删除”。判断时问三个问题:执行后能否撤回?撤回是否需要第三方配合?撤回之前是否已经产生了影响?
| 类型 | 例子 | 为什么不可逆 |
|---|---|---|
| 资金流出 | 退款、付款、转账、发放优惠券 | 钱到了对方账户,追回要靠对方配合 |
| 对外通信 | 给客户发邮件、短信、推送,公开发布内容 | 对方已经看到,无法“撤回”记忆 |
| 数据销毁 | 删除记录、清空表、覆盖文件、强制推送 | 没有备份就永久丢失 |
| 外部系统动作 | 在第三方平台提交商品下架、向税务系统提交申报 | 对方系统没有撤销接口 |
| 触发连锁反应 | 修改订单状态触发自动打款、合并代码触发部署 | 第一步可逆,但它引发的后续动作不可逆 |
| 基础设施变更 | 生产环境迁移、销毁云资源、修改 DNS 与权限 | 恢复成本极高,影响范围大 |
最后两类最容易被漏掉:动作本身看起来可逆,但它触发的下游不可逆。
Coding Agent 领域已经有相当具体的清单可以参考。Claude Code 的官方文档中,auto 模式默认拦截的动作就包括:生产环境部署与迁移、云存储大批量删除、强制推送、销毁基础设施资源(如 terraform destroy)、会丢弃未提交修改的 Git 命令、改写并非本次会话创建的提交等。这份清单本质上就是一份“不可逆操作目录”。
四种手段
四种手段分别落在执行前、执行时和执行后:
1. 预演(Dry Run):先看会发生什么
在真正执行之前,先生成一份“如果执行会发生什么”的预览:
Agent 提案:批量关闭 9 月份已超 30 天未更新的售后工单
【预演结果】
将关闭:312 单
其中: 含未完成退款的 4 单 ← 风险提示
属于 VIP 客户的 17 单 ← 风险提示
将触发:向 312 位客户发送“工单已关闭”通知
不可撤回的部分:客户通知
[ 全部执行 ] [ 排除风险单后执行 ] [ 取消 ]
预演的关键是 由程序计算影响范围,而不是让模型估算。基础设施领域的 terraform plan、数据库的事务预执行都是这种思路。
2. 二次确认:让人真的想清楚
对最高风险的动作,普通的“确认”按钮不够。常见的加强方式:
- 复述关键参数:要求确认人输入金额或数量,比如“请输入本次退款总额 18,420 以确认”。
- 双人复核:发起人与批准人不能是同一个人,资金类动作尤其如此。
- 展示不可逆提示:明确写出“此操作执行后无法撤回”,以及撤回需要付出的代价。
二次确认的代价是摩擦,所以只用在真正高风险的地方,否则就会变成 Human-in-the-loop 里讲过的审批疲劳。
3. 延迟执行:给反悔留一个窗口
不少邮件产品提供“撤销发送”:点击发送后先等几秒,期间可以撤回。这个思路可以推广到 Agent:
延迟窗口也是 熔断 的好位置:如果 10 分钟内 Agent 提交的退款总额突然达到平时的十倍,系统自动暂停整个队列,而不是逐笔放行。
4. 回滚设计:做错了怎么补救
真正的不可逆是少数,大多数操作都可以通过设计变得“可补救”:
| 手段 | 做法 | 例子 |
|---|---|---|
| 软删除 | 标记为已删除,保留一段时间后再真正清理 | 删除的工单进回收站,30 天内可恢复 |
| 执行前快照 | 修改前自动备份受影响的数据 | 批量改价前导出原价格表 |
| 补偿动作 | 为每个动作预先定义反向操作 | 错误发放的优惠券可以作废;错误通知可以发更正说明 |
| 分批执行 | 先执行一小批,验证无误再继续 | 先给 10 位客户发通知,检查内容和送达后再发剩余 |
| 幂等键 | 重复提交不会重复执行 | 网络重试不会导致退款两次 |
| 版本控制 | 所有变更可追溯、可回退 | 代码改动在分支上提交,通过评审再合并,而不是直接推主干 |
一个值得借鉴的原则:在 Agent 的权限设计上,优先给“可补救”版本的工具。给 archive_ticket 而不是 delete_ticket,给 create_pull_request 而不是 push_to_main,给 create_refund_request 而不是 execute_refund。
把四种手段组合起来
以「订单售后 Agent」批量退款为例,一个完整流程可能是:
不是每个动作都需要全部七步。根据 操作分级 决定强度:普通写入可能只要幂等和回读;资金和批量对外发送才需要全套。
常见误区
- “有人批准过就没问题了。” 审批人看到的是描述,预演让他看到的是后果;没有预演的审批往往是在盲批。
- “数据有备份,所以删除是可逆的。” 恢复备份可能需要几个小时,期间的新数据会丢失,而且不是每个人都知道怎么恢复。要把恢复路径演练过一次才算数。
- “只要单个动作可逆就安全。” 要沿着下游看:这个动作会不会触发打款、通知、部署等不可逆的后续?
产品经理检查清单
- Agent 的动作中,哪些本身不可逆?哪些会触发不可逆的下游?
- 不可逆动作是否都有预演?影响范围是由程序计算的吗?
- 最高风险动作是否要求复述关键参数或双人复核?
- 是否有延迟执行窗口和撤销入口?是否有基于总量异常的自动熔断?
- 能否用“可补救”版本的工具替换“不可逆”版本?
- 批量操作是否分批执行,每批之后是否验证?
- 回滚或补偿路径是否演练过?
练习
为「Coding Agent」或「SEO 诊断 Agent」设计不可逆操作的防护方案,用 45–60 分钟完成:
- 列出它可能执行的所有不可逆或触发不可逆下游的动作(例如合并到主分支、发布到线上、批量修改页面标题)。
- 为每个动作选择适用的手段:预演、二次确认、延迟执行、回滚设计,并写出具体做法。
- 挑出一个动作,把它的工具改写成“可补救”的版本。
延伸阅读
- Claude Code:Choose a permission mode——“What the classifier blocks by default”一节列出了 auto 模式默认拦截的高风险动作。
- OWASP:LLM06:2025 Excessive Agency
下一步
权限、安全与护栏模块到此结束。Agent 现在“不该做的做不成”,但“该做的有没有做对”还需要另一套机制——下一个模块「验证与错误恢复」从「为什么必须验证」开始。