副作用不变量任何重试前先回答“上一次是否可能已经成功”;任何补偿前先回答“现实世界能否真正回到原状”。两个答案都不明确时,必须进入 unknown 与人工处置,而不是继续猜。

先按可逆性和外部影响分类

只读但可能泄露或产生费用

读取不会改变业务对象,也可能泄露个人数据、消耗付费配额、触发审计或被第三方记录。只读工具仍需最小权限、数据域限制和速率预算。

可逆写入

存在可靠的反向操作,并且在明确时限内可恢复相同业务语义。例如尚未发布的草稿更新。但“有删除 API”不等于可逆:通知、索引、审计和下游消费可能已经发生。

可补偿

无法抹去历史,只能用新的业务动作抵消,例如退款抵消付款、取消预订抵消占位。最终状态是“发生后已补偿”,不是“从未发生”,费用、时效和合规后果可能保留。

不可逆

公开发送、永久删除、法律承诺、密钥泄露或不可撤销结算等。模型可以生成候选和预览,但提交应由确定性策略、参数绑定审批或受限人工执行。

分类决定默认自治与恢复策略
类别默认控制恢复
只读权限、数据范围、费用与速率停止后续传播、审计泄露范围
可逆版本写、幂等、短期撤销执行反向操作并验证
可补偿Saga、回执、补偿预算业务抵消与最终一致
不可逆预览、职责分离、强审批止损、人工和事故流程

高风险动作采用准备—确认—提交

Prepare 阶段解析目标对象、读取当前版本、计算差异和影响,生成规范化 Action Preview。策略引擎检查主体、金额、租户和敏感数据;需要审批时,审批记录绑定 preview hash、对象版本、审批人和有效期。

Commit 时重新读取对象并做条件写入,确认参数、权限、政策和审批仍有效,再携带业务幂等键提交。用户看到的自然语言预览不能成为唯一绑定对象,因为同义改写无法阻止底层参数被替换。

高风险动作的提交门:批准的是具体动作,不是模糊意图
Prepare规范参数、对象版本、Diff 与影响。
Policy/Approval绑定 action hash、权限与有效期。
Revalidate提交前复核版本、权限和预算。
Commit & Receipt幂等提交并记录外部业务回执。

超时后先确认结果,不立即重放

请求超时只能说明调用方没有在期限内收到确定答复。外部系统可能未收到、正在处理、已经成功但响应丢失,或已经失败。若直接重试,会把不确定性变成重复副作用。

  1. 用幂等键、业务流水号或客户端请求 ID 查询;
  2. 检查回执、事件流和权威业务状态,而非只查本地日志;
  3. 确认未发生后才允许重试;已发生则补记完成事件;
  4. 仍无法确认时标记 unknown,阻止依赖步骤并升级。

外部系统既不支持幂等,也不支持查询或对账时,自动化自治等级必须降低。Prompt 无法补齐接口缺失的事务能力。

跨系统一致性使用显式 Saga

Saga 把跨系统操作拆成各自本地提交的步骤,并为可补偿步骤定义业务反向动作。Microsoft 的补偿事务模式强调:补偿可能不按严格逆序,也可能失败,并且不能简单恢复旧值覆盖其他并发修改。

每步记录 forward command、外部回执、补偿条件和状态。Pivot 是越过后不能再靠补偿回到先前业务语义的点;它之前应完成关键校验,之后的步骤应尽量可重试并保证最终向前完成。

interface SagaStep {
  id: string;
  forward: BoundCommand;
  compensate?: BoundCommand;
  class: 'compensable' | 'pivot' | 'retryable';
}

type SagaState =
  | 'forward_running'
  | 'completed'
  | 'compensating'
  | 'compensated'
  | 'manual_intervention';

补偿本身需要幂等、重试、进度历史和人工升级。最终状态要区分 completed、compensated 和 unresolved,不能都折叠成 failed。

外部状态会在计划和提交间变化

审批不是锁,模型计划也不是保留。等待期间其他用户或 Agent 可能修改对象。提交使用版本号、ETag、条件更新或业务状态机;冲突后重新读取并重规划,禁止 last-write-wins 覆盖新状态。

Saga 缺少跨服务隔离,可能出现脏读、丢失更新和不可重复读。缓解手段包括语义锁、交换律更新、重新读取、版本文件与按风险串行化。选择哪种机制取决于业务不变量,不应让模型临场发明并发策略。

证明每个副作用发生了什么

一条完整 Attempt 时间线关联用户意图、规范参数、对象版本、策略决定、审批、幂等键、请求 ID、外部回执、重试与补偿。敏感值可以脱敏,但关联 ID、内容哈希和时间不能丢失。

对账任务比较内部账本与外部权威状态,发现孤儿、重复、长期 unknown 和补偿不完整。告警应带可执行上下文;“Tool error”不足以指导值班人员判断是重试、补记、补偿还是冻结。

围绕提交窗口做故障演练

必须演练的故障窗口与验收
注入点预期行为证据
请求发送前崩溃安全重试,不生成重复意图同一 command/幂等键
外部成功、响应丢失查询确认并补记,不盲重放外部回执与账本对齐
补偿中途失败从未完成补偿继续或人工接管补偿进度与 unresolved 告警
审批后对象被修改条件写失败并重新确认版本冲突事件,无覆盖写

跨团队 RFC 应列出每个 Tool Owner 对幂等、查询、回执、补偿和 SLO 的承诺,并明确哪个团队负责长期 unknown 与补偿失败。没有 Owner 的补偿设计只是架构图上的箭头。

主动提取:退款为什么不是付款的数据库回滚?
付款已经发生并可能被结算、通知和审计;退款是新的业务事务,只在经济效果上抵消,手续费、时间和法律记录仍存在。
故障判断:写入接口超时但没有查询 API,能靠换一个模型判断是否重试吗?
不能。缺失的是外部事实,不是推理能力。应停止依赖步骤并人工对账,长期方案是增加幂等与查询能力或降低该 Tool 的自治级别。

资料与事实边界

以下以官方文档、标准、论文和原始工程资料为主。厂商 API、价格、限额与模型能力会变化,落地时仍需按目标版本做能力探测和回归。

  1. Microsoft Azure Architecture Center:Compensating Transaction Pattern — 补偿并非简单回滚、补偿可失败及人工介入的官方模式说明
  2. Microsoft Azure Architecture Center:Saga distributed transactions pattern — Saga、Pivot、Retryable step 与数据异常边界
  3. Temporal:Activities — Activity 重试、幂等与完成事件的运行事实