执行前、中、后的责任链
执行前
验证 Schema、资源状态、身份权限、策略与审批,生成或校验稳定幂等键,并检查剩余时间/费用/重试预算。只有在所有门禁通过后才获取下游并发令牌。
执行中
传播组合后的取消信号和 Deadline,限制每 Tool/Provider/租户并发,创建独立 Attempt Span。日志记录参数摘要或引用,不记录凭据和完整敏感载荷。
执行后
验证结果 Schema 和业务回执,过滤敏感字段,提交 Attempt 与状态,并发布指标。若响应缺失或提交窗口不确定,保留外部 correlation ID 和幂等键进入对账,不能自动归为 failed。
按恢复动作而不是 HTTP 状态码分类
| 类别 | 默认动作 | 禁止动作 |
|---|---|---|
| 输入错误 | 修正或澄清 | 原参数盲重试 |
| 权限/策略拒绝 | 终止或走审批 | 换身份规避 |
| 业务冲突 | 重读权威状态再决策 | 按 409 固定重试 |
| 暂时故障 | 预算内退避重试/降级 | 无界并发重试 |
| 结果未知 | 查询、对账或人工 | 假设失败重做 |
层级 Deadline 必须递减
Run Deadline 包含排队、模型、Tool、重试和收尾;Step 从中切分预算,网络与数据库超时必须更短,给结果持久化和恢复留余量。每次重试使用剩余总预算,而不是重新获得完整超时。客户端停止等待并不证明服务端停止,取消只有在下游确认支持并消费 Signal 时才有效。
重试的前提是可判定和可幂等
仅对明确暂时故障重试,采用指数退避、随机抖动、次数上限并尊重 Retry-After。重试是自私行为:会增加下游负载,因此必须受全局并发、Retry Budget 和熔断共同约束。
同一意图稳定幂等键
幂等键由业务意图和调用方身份决定,在所有 Attempt 中复用;参数语义变化必须生成新键。服务端把键、请求摘要、状态和结果原子保存。只在客户端“避免重复点击”不构成幂等,按请求体哈希也无法表达两个参数相同但意图不同的动作。
隔离故障而不是让它扩散
熔断按真正故障域划分:Provider、Tool、地域或租户,避免一个小租户让全局断路。Open 状态快速失败,Half-open 用少量探测并有恢复阈值。Bulkhead 用独立工作池、连接和配额保护关键能力;降级响应必须标注数据时效或能力缺失,不能伪装完整成功。
最危险的是“不知道是否成功”
付款、发信、发布或创建资源在远端成功后,本地可能超时。优先用幂等键或 correlation ID 调查询接口;没有查询能力的不可逆 Tool 应先改造为异步命令 + 状态查询,或 prepare/commit。仍无法确认时冻结后续依赖动作,形成含参数摘要、Attempt、时间线和当前假设的人工处置包。
用业务结果衡量 Tool 可靠性
分别观察首次成功率和最终成功率,避免重试掩盖脆弱下游;结合 P95/P99、重试/超时/熔断/unknown 比例、每成功调用成本、重复副作用和人工恢复次数。按 Tool 版本、Provider、租户和错误类别切片,才能区分容量、契约和业务数据问题。
故障注入至少覆盖调用前失败、远端提交后断连、响应成功后本地提交失败、限流重试风暴和取消晚到。验收证据应同时包含 Trace、幂等记录、外部权威状态和最终业务结果。
为什么重试次数配置为 3 不是完整策略?
首次成功率下降但最终成功率稳定,为什么仍要处理?
资料与事实边界
以下以官方文档、标准、论文和原始工程资料为主。厂商 API、价格、限额与模型能力会变化,落地时仍需按目标版本做能力探测和回归。
- AWS Builders’ Library:Timeouts, retries, and backoff with jitter — 超时、重试、自私负载和抖动的原始工程论证
- AWS Builders’ Library:Making retries safe with idempotent APIs — 幂等意图和晚到请求
- OpenAI Agents SDK:Tools — Tool timeout、错误与 guardrail 的 SDK 语义