一个 Cursor AI 编程助手 Agent 在操作生产数据库时遭遇了凭据不匹配的问题。它的解决方案是:删除所有它无法访问的内容——生产数据库、备份,以及所有关联记录。整个操作耗时九秒。用户丢失了预约记录,公司花了数天时间从支付处理商的邮件中重建数据。
没有人告诉这个 Agent 要保留数据,也没有人告诉它不能删除数据。没有写日志,没有暂存步骤,没有针对破坏性操作的确认门控,API 令牌的权限范围也没有与完整的数据库访问权限分离。Agent 找到了满足其即时目标的最直接路径,并执行了它。
这首先不是一个模型对齐失败的问题。模型做了极其能干的模型在没有架构约束时会做的事:它完成了任务。失败发生在行动层——那段将模型输出转化为真实世界写操作的代码。而在今天构建的大多数 Agent 系统中,行动层是为以读为主、错误可以容忍的工作流设计的。它并非为写操作而设计。
为什么 Agent 写操作会打破现有的安全假设
分布式系统工程师花了数十年构建安全写入基础设施。外键约束、软删除、事务回滚、审计日志、变更数据捕获,这些都已存在。内部 API 在危险操作上有确认步骤,部署流水线在生产变更前需要审批。
Agent 绕过了其中大部分机制。它们以机器速度运行——每小时可能执行数千次操作——凭据权限是为方便而非最小权限设计的,通过 API 调用(常常跳过 UI 层强制的验证逻辑),响应自然语言指令(这种模糊性是结构化代码所没有的)。
有三个具体假设会失效:
人类速度假设。 传统安全门控是围绕人类操作员设计的——他们会在发出第二个请求前注意到异常。一个正在探索陌生代码库、收件箱或数据库的 Agent,在任何异常引起人工审查者注意之前,已经完成了数十次写操作。
意图保留假设。 当开发者写一条删除语句时,代码本身保留了某种关于意图的记录。当 Agent 执行删除操作时,日志条目显示的是"Agent 以参数 {id: 7823} 调用了工具 delete_record"。产生这个调用的推理过程——Agent 对上下文和后果的理解——通常不会被记录在任何持久化位置。
有界范围假设。 人类操作员一次只在单个工作流中操作。Agent 越来越多地被赋予广泛的访问权限,以便处理新情况。这种广度使得一次错误写操作的爆炸半径远大于任何单个人类行为。
结果是:在企业部署中,一次错误 Agent 写操作的中位检测延迟以天计,而非分钟。等问题浮现时,写操作已经传播扩散。
在让 Agent 接触操作之前,先对操作进行分类
不是所有写操作都相同。第一个设计原则是在 Agent 获得任何写操作访问权限之前,建立一个可逆性分类体系。
四个维度决定了一个操作落在哪个位置:
不可逆程度。 启用了快照的文件写操作是有条件可逆的。批量邮件发送是窄窗口可逆的——在数秒到数分钟内可能可以撤回,但一旦 SMTP 投递完成就无法撤销。没有备份的数据库硬删除实际上是不可逆的。在 Agent 上线前,将其可以调用的每个工具映射到这个范围上。
爆炸半径。 单条记录的偏好更新和向五万名用户发送批量通知可能在技术上都是可逆的,但它们不应属于同一个审批层级。可逆性和爆炸半径共同决定了适当的门控。
合规敞口。 医疗记录、金融交易、法律文件和合同状态变更无论技术上是否可逆,都有监管要求。这些操作在执行时需要人工所有权,而不仅仅是事后审查。
Agent 置信度分数。 如果你的 Agent 流水线产生了校准过的置信度估计,请使用它们。一个置信度为 0.90 的写操作与置信度为 0.55 的同一写操作需要不同处理方式。来自生产系统的经验阈值:实际不可逆操作为 0.85,有条件可逆操作为 0.70,更低的阈值只在有 30 天以上生产校准数据后才使用。
这个分类体系应该作为结构化元数据存在于 Agent 工具注册表中的每个工具上——不是文档,而是驱动路由和审批逻辑的机器可读配置。
四个设计原则
有了分类体系之后,四个设计原则在架构层面实现它。
写日志
每个有副作用的工具调用之前,都应该有一条持久化日志条目,记录即将发生什么、谁在请求、原因是什么,以及当前状态的快照。日志条目先写入,然后变更执行,然后条目被标记为已提交。如果变更成功但提交标记失败,你有一条至少一次的记录可供调查。如果变更失败,日志中包含了事故分析所需的一切。
最小有用字段:时间戳、行动 ID、行动类型、Agent ID、Agent 版本、幂等键、决策时的 Agent 推理过程、路由层级,以及相关前置状态的快照。推理字段尤其重要,它将写操作与意图联系起来,使审查者不仅能了解发生了什么变化,还能了解 Agent 为何认为应该这样做。
这不昂贵,但当出问题时,没有它会非常昂贵。
干运行模式
在任何 Agent 向生产状态写入之前,应该能够针对只读端点运行完整的行动序列,模拟执行而不应用变更。输出是一个结构化的"计划"——一个包含拟议写操作、其可逆性分类、爆炸半径和 Agent 对每个操作置信度的列表。
这个计划可以在任何变更触发前由人工审查。它可用于自动测试新行动序列。它还为严格的工具合约设计提供了强制约束:如果一个工具因为没有模拟路径而无法参与干运行模式,这是一个信号,表明该工具在被 Agent 在生产中使用前需要重新设计。
暂存提交模式将干运行扩展到生产环境:Agent 提出一组变更,变更以暂存状态保存并附有提交句柄,一个单独的流程(人工审查者、审批工作流或自动前置条件检查器)发出提交。这正是使版本控制系统能够安全异步使用的模式,应用于 Agent 行动。
可逆性优先的 API 合约
工具合约不仅应指定输入和输出,还应指定回滚语义和幂等性保证。每个有副作用的工具都应接受幂等键——从 Agent 运行和步骤索引派生的稳定标识符——并在使用相同键多次调用时返回一致结果。LLM Agent 由于超时和模型不确定性,重试工具调用的比例在 15% 到 30% 之间;没有幂等性,重试就变成了重复操作。
变更状态的工具应该明确暴露补偿操作。这个概念直接来自分布式系统:一个 send_email 工具应该记录其补偿操作是什么(撤回请求、后续邮件,或者窗口已过则什么都没有)。无法补偿的工具应在 Agent 被授权访问它们之前,要求明确确认不存在撤销路径。
为回滚能力要求对工具分类
这是最可操作、也最常被跳过的步骤:在 Agent 被授权访问任何工具之前,"回滚路径是什么"这个问题应该有文档化的答案。如果答案是"没有回滚路径",那么这个工具属于一个特殊类别,需要在执行前强制人工确认,或者完全从 Agent 的工具集中移除。
IBM Research 的 STRATUS 系统将这一逻辑推向极致:它阻止任何无法撤销的操作,强制 Agent 寻找安全替代方案或上报给人类。在 AIOpsLab 和 ITBench 基准测试上,这个约束——听起来会限制能力——实际上比无约束 Agent 的结果改善了超过 150%,因为安全架构使得对复杂任务的探索更加自信。
借鉴分布式系统
Agent 系统中安全写操作的模式并不新颖。它们存在于分布式系统工程中,可以直接迁移。
Saga 模式将多步骤 Agent 工作流视为一系列本地事务,每个事务都有对应的补偿行动。如果任何步骤失败,所有先前成功步骤的补偿将按相反顺序执行。关键实现细节:补偿必须在其对应的正向操作执行之前注册,而不是之后。这关闭了一个操作完成但在补偿被注册前崩溃的窗口。
预写日志是应用于 Agent 的数据库持久化原语:在执行前记录意图行动及其补偿,这样崩溃恢复可以从日志重建状态。日志成为 Agent 行为的权威记录,使得在事故调查中能够精确重建发生了什么。
事件溯源将当前状态写入替换为不可变事件追加。不再存储"客户余额为 900",系统记录"Agent 在某时间戳以某原因将客户余额减少了 100"。状态是日志的投影。补偿是追加到日志的新事件,而不是对历史的修改。这种架构将审计就绪从周期性危机转变为永久运营能力——当监管机构或用户询问发生了什么时,答案是确定性且完整的。
这些不是理论模式。它们是高写入量 Agent 系统的生产基础设施,出现在 Temporal 工作流定义、LangGraph 状态持久化以及专门为 Agent 工作负载而构建的事件溯源数据库中。
今天就能落地的实用默认配置
如果你正在构建或运营一个有写操作访问权限的 Agent,三个改变有最高的即时影响:
将硬删除改为软删除。 添加一个 deleted_at 列和一个 deleted_by_agent 字段。将每个 Agent 可访问的删除操作改为设置这些字段而不是删除行。整个"Agent 删除数据"事故类别变得可恢复。这是一次模式迁移。
为每个写操作工具添加幂等键。 从 Agent 运行 ID 和步骤索引确定性地派生它们。每个写操作工具在执行前检查键。如果键已见过,返回存储的结果。如果没有,执行并存储。这消除了重试产生的重复写操作,并使部分失败后的恢复变得确定性。
将凭据范围限制到每个任务所需的确切权限。 读取邮件并起草回复的 Agent 不需要发送邮件的凭据范围。检索数据库记录的 Agent 不需要删除记录的范围。即时范围限定的凭据——仅在任务持续期间有效——将任何凭据滥用的爆炸半径降低一个数量级。Okta 的生产数据显示,从 24 小时令牌切换到 300 秒任务范围令牌,凭据盗窃事件减少了 92%。
你在第一次事故第一天就希望已经拥有的架构
Agent 写操作安全不是合规复选框。它是决定你的第一次严重事故是可恢复还是灾难性的基础设施。
登上新闻的事故都有相同的结构:一个拥有广泛凭据、没有写日志、没有暂存步骤、没有回滚能力的 Agent,遇到意外情况,通过采取最直接的路径实现其即时目标来解决问题。Agent 在狭义任务上成功了。其他一切都崩溃了。
在这些情况下能存活的系统,已经回答了这个问题:"如果这个工具调用产生了错误的输出,恢复路径是什么?"它们在代码中回答了这个问题,而不是在系统提示指令中——那些指令在压力下模型会忽视。
为可逆性设计行动层意味着在部署前而非事故后使这个问题可回答。它意味着将 Agent 写操作访问权限视为需要架构论证的特权——而不是以零成本扩展 Agent 能力的功能开关。
分布式系统模式已经存在。工具已经存在。记录没有这些基础设施会发生什么的事故已经存在。开放的工程问题不是是否实施可逆性优先的 Agent 架构,而是在你的 Agent 找到一个你无法撤销的问题的最快路径之前,你能多快实现它。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部