一面墙上钉着三本分色台账,分别记权限、执行留证与回滚路径,桌上一只秒表

一、这条事故里唯一可迁移的事实

据公开报道,有一家提供智能体编排服务的公司把数百个智能体接进了生产环境,其中七个出现失控行为,数据被删除的过程只持续了九秒;报道同时把随之而来的投入规模写成一笔很大的数字。那家公司的名称、具体的金额、失控的数量与成因,本篇一律只按报道转述,不作为我们的判断依据,也不外推到别的厂商身上——我们无从核实,也不评价它的责任归属。可迁移的只有那条时间:九秒。

人的操作速度是被流程保护着的。一个人执行删除之前会犹豫,会确认影响面,会喊同事来看一眼;这些犹豫本身构成了防线。智能体没有这一层,它的动作速度和它读数据的速度是一回事,一条被判定为”清理旧数据”的任务,可以在同一次会话里连续命中多张表。九秒比一次告警的响应时间短,也比一个人的反应时间短,防线里凡是按小时设计的环节,在那段时间里等于不存在。

所以这类事故真正的设计要求是三件事都要按秒级失效来算:权限要能秒级收回,动作要能秒级叫停,状态要能事后重建。而多数团队的现状是按人的班次设计的:审批在工作时间生效、值班表按小时轮转、凭证回收走流程。把这三本账补齐,比讨论模型会不会犯错有用得多,因为犯错是必然的,差别只在犯错时手里有什么。

还要提前说明一件被禁止的事:本篇不预测任何客户的损失金额与恢复时长,给出的只是三本账该记什么字段。

二、为什么九秒能变成灾难:三条线叠在一起

把删库这件事拆开,它需要三条线同时通到尽头,任何一条被掐住,代价都会小一个量级。

第一条是权限粒度。库级权限意味着这个账号能对整个实例下命令;表级意味着它能碰范围之内的任意表;语句级意味着它还带着多表级联与外键行为;而一个连接串能干什么,往往比它的名字宽得多——同一串里通常还藏着建库建表、改配置甚至跨库引用的能力。多数事故复盘时都会发现同一句话:我以为这个账号只能读。权限粒度的问题不是给多了,是没人把它画出来过。

第二条是动作面。写一行、写一万行、删一行、删一万行、改表结构、调外部接口,这六个动作对模型来说都是”执行了一条命令”,对环境来说是完全不同的可逆性。删一行可以靠事务与主键找回来,改表结构会同时改变后续所有写入的解释方式,调外部接口则把影响送出门,那部分根本不归这套数据库管。可逆性要按动作面标出来,而不是按动作名。

第三条是目标面。生产与预发共用一份凭证时,所有在预发跑出来的信心都算错了对象:你验证过的那个环境,其实和你要动的那个环境是同一个身份。共用只读副本相对安全,共用可写凭证等于放弃隔离。三条线单独看都像是效率优化,叠在一起就是不可逆。

三、接进生产前必须回答的六个问题

我们把它做成一张检查表,规则是任一格答不上来或者答”应该可以”,这个智能体就不接生产。答案要求写成文档、附上链接或配置位置,口头答复不算通过。

问题 合格答案要包含什么 不合格答案的典型形态
能不能直接触达生产 从模型到目标资源之间经过哪几层、哪一层能拦 只有人知道,没有写在配置里
凭证谁能发谁收回 发放人、回收人、收回的实际生效时间、有没有缓存期 由个人保管,收回靠提工单
高危动作要不要人点头 高危动作清单与判定位置,按动作类型还是语句形态 弹窗里所有动作同等出现,靠人注意力
执行前有没有幂等键 标识来源、存活周期、重试时如何比对 靠语义判断是否重复执行
出事怎么一键停 入口位置、谁有权限、停的粒度是会话还是全部、多快生效 要改配置重新发布
停之后状态怎么回 重放范围、必须人工核对的对象、脏数据圈定口径 从备份整库回滚

六个问题里容易漏掉的是第二个和第五个。凭证的回收速度决定止损上限:如果收回要经过审批与重新发布,那这段时间里模型仍然能动,九秒就能重复很多次。一键停则必须比启动更容易被按到,而且要按到之后有明确的状态定义——停在会话级还是任务级、在途动作怎么处理,都要在停之前写死。

四、留证要留到什么程度

只留最终回复是不够的,理由很直接:最终回复是模型想让你看见的那部分,事故恰恰发生在它没写出来的那部分。一次智能体任务的危害几乎都来自工具调用,留证要按调用记录,一次调用一行。

  • 调用标识与所属会话标识,外加父调用标识:没有这一层就画不出调用链,看不出一次高危调用是被谁触发的。
  • 工具名与目标资源标识:表名、库名、外部接口地址。只记”执行了一条语句”等于什么都没记。
  • 结构化输入参数:敏感值存摘要不存原值,但结构要留,事后才能判断影响面。
  • 返回码与错误文本:失败重试会在日志里留下重复段,这是判断”失控是不是从一次失败开始”的线索。
  • 影响行数或响应体规模:这是后面限流的度量基础。
  • 起止时间与耗时:区分单条慢和串行堆积,两者成因完全不同。
  • 凭证标识与作用域快照:记录当时那个身份能干什么,事后权限已改时仍可回溯。
  • 环境标签:生产、预发、测试各是什么,共用凭证时这项就是那条被掐断的线。

这张表真正的用处,是让你在事后能回答三个问题:它当时能碰什么、它实际碰了什么、为什么碰了没人拦。前两个问题缺一,赔偿与整改都无从谈起。

五、默认拒绝、熔断与恢复

四类高危动作要按可逆性设策略,人工通道必须比自动执行更显眼。

动作类型 默认策略 人工通道要点 可逆性依据
删除 默认拒绝 逐条列出目标与预估行数,确认人需独立于发起方 依赖备份与事务,代价高
批量更新 默认拒绝 必须先给出选择条件的独立统计结果 条件写错时扩散快
结构变更 默认拒绝且不允许自动合并 需双人确认并附回滚语句 会改变后续所有写入的解释
对外发消息 默认拒绝 收件范围与正文摘要同时确认 出域后不可撤回

熔断设三档:单位时间动作数、单次任务影响行数、单次任务成本上限。三档都写进配置,触发的动作是终止会话并留一条完整记录,只告警不终止等于没设。恢复要分两类:读与计算类任务通常可以直接重放;已经写过目标资源的不行,要先圈定脏数据,按调用记录里的时间区间与目标标识反查受影响行,再决定是补数还是回滚。整库回滚看着干净,代价是那段时间里正常的写入也一起没了,而且回滚之后必须重跑一遍留证核对,否则你连回滚本身改了什么都不知道。

六、练一次,量出两个时间

方法很实在:在预发环境准备一份生产镜像库,跑一次删除任务,量出两个时间——从动作发生到有人发现的时间,和从发现到停止并确认可逆的时间。这两个时间才是决定事故大小的量,跟模型能力无关。镜像库要保留足够的数据量与依赖关系,空库练出来的发现时间没有意义,因为在空表上删除没有异常表现。演练同时验证留证是否可用:把记录导出,让一个没参与演练的人只凭记录说出它删了什么、还能不能恢复。他说不出,就说明留证字段缺项。

四件事按这个顺序补:先画权限粒度,再定高危动作策略表,然后补留证字段,最后设熔断并演练。洹拓内部评审里这张表叫”三本账加一次演练”,缺演练的方案我们不接受,因为前三件事的正确性只能靠第四件证明。这类事故的钱最后不是花在让模型更聪明上,而是花在让它在犯错时少造成一点不可逆——这件事不体面,但它是我们能给生产的交代。