2017 年 2 月 28 日上午 9 点 37 分(太平洋时间),亚马逊云服务的一位工程师坐下来处理一件小事。亚马逊的大型存储服务 S3,有一部分计费系统跑得慢。办法是下线几台服务器。
这位工程师有权限,也照着一份现成的操作手册在做。那条命令要填几个参数,其中一个输错了。
下线的服务器比预想的多得多。其中就有撑着 S3 索引的那批机器,索引记着每一个存储对象放在哪儿。没了它,北弗吉尼亚的 S3 读不了、列不了、存不了、也删不了任何东西。过了好几个小时才恢复正常,一长串网站和应用跟着出了问题。那天上午的完整经过,见案例。
亚马逊公开的事故总结没点那位工程师的名,点的是工具。「所用的工具允许过快地移除过多容量,」总结写道。亚马逊把工具改了:移除容量变慢了,凡是会让某个子系统低于运行所需最低容量的移除,一律拒绝。「这将防止一次错误的输入在将来引发类似事件。」它还开始排查其他运维工具有没有同样的漏洞。
失误和次品
在丰田生产方式里,这类修法有个名字:poka-yoke,通常译作「防错」。
新乡重夫讲过一个故事,新乡研究院的布鲁斯·汉密尔顿称之为「流传的说法」:这个词原本叫 baka-yoke,「防傻瓜」。新乡要松下的经理们别再这么叫,因为这等于骂工人是傻瓜。他认为,犯错是人之常情。「失误不可避免,」他说,「但由失误造成的次品是可以避免的。」
整套方法就建立在这个区分上。失误是手滑:数字输错了,零件装反了。次品,是手滑之后没东西拦住、一路变成的结果。有的防错装置让手滑根本发生不了,比如现在那个拒绝低于底线的 AWS 工具;有的允许手滑发生,但用汉密尔顿的话说,在它「流到下一道工序之前」就抓住。
2022 年,Atlassian 吃过这个亏。一个本该从客户站点里删掉某个应用的脚本,拿到的却是站点本身的 ID。Atlassian 事后写道,删除接口「既接受站点 ID 也接受应用 ID,并默认输入是对的」,也「没有任何警示来确认要删的是哪一种」。23 分钟里,它删掉了 775 个客户的 883 个站点,其中一些客户停了两个星期。Atlassian 在复盘里提出的修法,是让所有客户数据的删除都先走一道「软删除」:数据先留一段保留期,期间还能恢复。
为什么装置会被晾在一边
防错装置得有人用才管用,汉密尔顿列了几条人们不再用它的原因。装置多出一道工序,却没人给这道工序留时间,工人就会觉得被逼着在速度和质量之间二选一。装置其实不好使,用它的人最先知道。装置抓住了次品,却没人去追为什么会出,「那就不是防错,只是个挑废品的筛子」。干活的人要是没参与设计,也很少会认真用它。
一周药盒
设想一个人在照顾父亲吃药。五种药,有的早上吃,有的晚上吃,一个月里有两次不是漏吃就是多吃。没人粗心,只是药瓶长得太像,晚上又太忙。
后来他们换了一个一周药盒,每天早晚各一格,周日一次装好。装药时出错,它拦不住。可到了周三早上,周二晚上那格要是还满着,谁都看得见,说明那顿可能漏了。格子空了能说明的就少一些:药被取出来了,不等于真吃下去了。
给工具做防错
AI 智能体也会手滑,它们的工具也可以照这个思路设计。Anthropic 2024 年的智能体搭建指南写得很直接:「给你的工具做防错。改一改参数,让人更难犯错。」
团队举了做编程智能体时的一个例子。智能体一离开项目根目录,用相对路径的工具就容易出错。于是他们把工具改成必须用绝对路径,结果,按他们的说法,「模型用这个办法用得完美无缺」。
上面几次事故还能引出几条。给智能体分开两个工具,一个删记录、一个删账户,别用一个什么 ID 都收、默认输入正确的工具。让有破坏性的工具拒绝低于底线的操作,就像现在的 S3 工具那样。删除先进回收站。这些都抓不住谁也没料到的那种失误,但能让见过的那几种不那么容易原样重演。要验证,就拿以前真出过的错误输入去喂工具,看它拦不拦得住。