一个智能体产品的好坏,由它出错之后发生的事来决定。
每个智能体都会在用户面前明显地失败。区别不只在失败率本身——而在失败是优雅、可恢复、能修复信任的,还是灾难性、不透明、摧毁信任的。本文涵盖安全地失败、把撤销与回滚作为首要安全网、用户真正可据以行动的错误提示,以及在用户亲眼目睹一次错误之后重建校准信任这件具体的工作。
用对待成功路径同样的心力去设计失败路径。
多数智能体体验的精力都投在顺利路径上;失败路径只是异常处理器碰巧做的那些事。这个比例反了——用户对一个智能体的持久判断,是在失败时形成的,而非成功时。一次优雅的失败有三个属性:它在叠加之前就停下(一个坏步骤,而不是十个建在它之上的步骤)、它让系统处于一个已知状态(而非半应用状态)、它准确告诉用户当下处境如何。大声且早失败,永远胜过无声且晚失败。
危险的失败不是那个可见的崩溃——而是那个悄悄产出一个看似合理却错误的结果并继续下去的智能体。要把检测的天平偏向"暴露不确定并停下",而非"硬闯过去"。
撤销是那张让其他一切都变得负担得起的安全网。
如果动作能被干净地撤销,犯错的全部代价会下降一个数量级——其他各处的摩擦也能随之下降(这就是 H2 中的可逆性杠杆,从失败一侧来看)。在投资更好的确认之前,先投资撤销:一个强大的撤销让你能安全地降低审批摩擦,从而减少疲劳,从而改善那个用来抓住失败的监督,而撤销随后再来清理这些失败。
# Make the action reversible; record how to reverse it op = effect.apply(action) journal.record(op.inverse) # compensating action, kept ready if user.undo(op) or monitor.detected_regression(op): await journal.compensate(op) # roll back to known-good state
- 宁可要真正的可逆性(补偿动作),也不要一个仅仅警告的确认。
- 在真正回滚不可能之处,在效果落地前插入一个带取消的延迟窗口。
- 让撤销在用户后悔的那一刻就触手可及,而不是埋在某个菜单里。
一条错误提示,是用户下一步行动的界面。
"出了点问题"没给用户任何能用的信息。一条可据以行动的失败提示要回答三个问题:我现在处于什么状态(有东西被应用了吗?它一致吗?)、我能做什么(重试 / 撤销 / 接管 / 上报)、我不该假设什么(例如"邮件并未发出")。把那些确凿的事实呈现出来——什么已完成、什么已回滚、什么待处理——并把用户最可能想要的恢复动作做成首要控件,就放在那里,而不是隔着三屏。
在后果上向关闭失败,在能力上向开放失败。
失败的方向是一个深思熟虑的选择。在后果轴上——金钱、数据、对外通信——向关闭失败:不确定或出错时,做得更少而非更多;一个没做的动作可恢复,一个错误的不可逆动作往往不可恢复。在能力轴上——某工具宕机、某来源不可达——向开放失败、走向诚实的降级:返回明确标注的部分结果,或在状态完好的前提下交还给人类,而不是为了显得能用而编造。最糟的失败模式把二者结合起来:一个自信、看起来完整、错误、且不可逆的结果。
可见错误之后的信任修复,是显式的工作,而非时间。
一次可见的错误不只赔上那个任务;它会重置用户对整个智能体的校准(H1),即便失败本是限定范围的,影响也常常是全局的。信任不会靠等待恢复——它靠刻意的修复恢复:平实地承认那个具体错误(不淡化、不上演拟人化的道歉表演)、说明那个能让重演变得更不可能的具体改动、以及最有力的一招——在那个恰好失败的范围内,主动提议暂时降低一级自主权(H5)。一次智能体自己提议的降级,读起来是在担责,比任何措辞的道歉都更快重建校准信任。
一次可见失败之后,为用户显式界定信任影响的范围:"这影响的是退款处理;工单打标签不受影响。"未界定范围的失败会悄悄毒化那些从未失败过的能力的信任。
什么时候不该自动重试。
如果这次失败可能已部分应用了一个非幂等的效果,就不要自动重试——在不确定的状态上悄悄重试,会把一次可恢复的失败变成一次重复的、不可逆的失败。