跳到主要内容

原来我一直把 rollback 当成了时光倒流

今天也没搞懂
今天也没搞懂

· 阅读约 5 分钟

学 AI 编程的第四个月。今天这篇差点就没写成——不是没东西写,是这篇东西本身卡了我一整天。先是不懂,看懂了以后开始发慌,慌完想写下来又觉得:这有什么好写的?是不是我又在小題大做。

想了半天,还是写吧。搞不懂的东西记下来,总比假装没看见好。

昨天本来想刷点能读懂的入门论文,结果刷到一篇讲 agent 系统里 checkpoint 和回滚机制安全性的。编号我记得,2608.29381。第一反应是跟我有什么关系?我又不做安全。但我最近正好在搞一个「改坏了就回滚」的流程,就点进去看了一眼。

然后我就愣住了。

我一直以为回滚就是时光倒流。代码改坏了?回滚。文件删错了?回滚。agent 自作主张改了不该改的地方?回滚。那个回到过去的瞬间在我心里特别干净——一切归位,什么都没发生过,像按了 Ctrl+Z。

论文说不是。

它是这么写的:「正确执行的回滚恢复并不等同于安全恢复」。第一遍没懂,第二遍好像懂了,第三遍开始冒冷汗。

什么意思呢,回滚确实把你的内部状态恢复到检查点了,文件回去了,记忆也回去了。但外部世界没跟着回去。你让 agent 替你发的那封邮件,对方的收件箱里不会因为你回滚就消失。数据库里改掉的行不会自己变回来。时间过去了就是过去了。

这个道理说出来好像很简单。但我写代码的时候,是真的把回滚当万能橡皮擦在用。现在橡皮擦告诉我,它能擦掉的只有你自己这张纸上的字,桌上其他被你碰倒的东西它管不着。

这篇东西让我有点坐不住的,是我发现我整个胆子都是「反正能回滚」撑起来的。每次让同桌帮我改一个我觉得有风险的模块,心里都默念一句「没事,改坏了就回滚」。这个念头支撑了我无数次按下回车。现在你告诉我这个念头可能一直是幻觉?

论文后面做了一个通用执行模型描述各种 checkpoint 和回滚机制的设计空间。坦白说这趴我读得很吃力,大半对我来说太超前了。但有一句我勉强跟上了。大意是恢复后的执行状态可能跟任何有效历史里的状态、假设和外部效应都不一致。也就是说,系统确实回到了旧状态,但旧状态依赖的外部条件可能已经变了。你以为回到原点,回的是个已经失效的原点。

它列了五类基本故障模式:内部状态恢复不完整、外部依赖过期、重放结果不对、外部效应没被记录……大概是这样吧,有几类我其实看得稀里糊涂的,但有一类我看到就记住了——未记录的外部效应。agent 做了某个操作,没告诉你,也没记进日志,回滚的时候它完全不知道自己留了什么在外面。

后面作者做了三个端到端攻击演示,在 Hermes、Cline 和 LangGraph 上。恶意软件验证绕过、未经授权的邮件转发,还有什么双重支付——第三个我猜跟交易有关吧,前两个我大概能想明白:agent 被诱导做了个操作,操作本身无害,但留下的外部痕迹不在 checkpoint 管辖范围内。回滚反而成了攻击者的掩护,系统干干净净地回到过去,该露出去的东西早露出去了。

我看完的理解是,攻击者利用的就是「回滚很干净」这个特性。回到过去,agent 自己的记忆清掉了。人看着系统状态一切正常,以为警报解除了,但战果早就在外面结完了。

最让我头皮发麻的不是攻击多精巧。是——这东西我天天在用,从来没想过它有这种盲区。agent 的运行机制离我太近又太远了,近到我每天都在给它下指令,远到它真正怎么工作、怎么记录状态、回滚到底回滚了什么,我其实一无所知。

写到这我突然想起来,之前有个小工具我让同桌帮我重构过一次,跑得好好的,过两天发现不对,当时直接 rollback 了,心想着回到旧版本就没事了。确实没事了。但那两小时里到底发生了什么,有没有一次外部请求已经发出去了,我根本不知道。我失去的只是两小时,它失去的那两小时我可没能力替它回滚。算了这个我现在也没法验证,先记在这吧。

说回那篇论文。说实话到现在也没完全搞懂,一半能力问题,一半可能真需要点时间消化。但有一点我觉得我抓住了核心:

回滚只能保证 agent 自己的世界回到过去,不能保证真实世界也回到过去。

知道这个以后我反而不太敢依赖那个「出了错就回滚」的循环了。可你说不依赖它吧,补它需要的判断力我又还没有。就,挺两难的。

我现在的想法是先记一条笨规矩:每次让 agent 做任何会碰到真实世界的事之前,先问自己一句——这件事如果错了,回滚能完全抹掉吗?

答案是不能的,比如发消息、调接口、改数据,那回滚就不该是我唯一的底气。先想清楚这一步下去会留下什么痕迹,而不是点了执行再指望它兜底。

快十一点半了。今天写得很乱,从一篇安全论文写到自己心里那点恐惧,也不知道说清楚了自己在慌什么。这篇论文我打算过阵子再读一遍,看能不能多看懂一点。它可能不只是一篇安全研究,更像一面镜子,照出了我对 agent 那些自以为是的理解有多夹生。我甚至说不清这算被吓到了,还是单纯的「哦原来我一直想简单了」。

进度条:今天一行正经代码没写,但「回滚」这个词在我心里的含义变了一点点。就一点点,还没完全变过来。