失败重试
核对日期:2026-05-09。
1. 定义与边界
失败重试是对模型、工具、队列、网络、数据库和外部 API 的临时失败进行恢复的机制。它必须和超时、幂等、限流、熔断、降级、死信队列共同设计。重试不是“失败就再来一次”,错误重试会放大故障和成本。
2. 为什么重要
Agent 系统依赖多个外部组件。一次用户请求可能触发多个模型调用和工具调用,任一环节失败都会影响结果。没有策略的重试会造成雪崩:上游限流后,下游大量重试,队列堆积,成本暴涨。
3. 核心机制
错误分类:
| 类型 | 示例 | 策略 |
|---|---|---|
| 可重试临时错误 | 429、503、网络超时 | 指数退避 + jitter + 最大次数。 |
| 不可重试业务错误 | 参数非法、无权限 | 立即失败或请求用户修正。 |
| 不确定副作用 | 工具超时但可能已执行 | 查询幂等记录或补偿,不盲目重试。 |
| 安全拒绝 | 越权、注入、敏感数据 | 不重试,记录安全事件。 |
重试流程:
4. 架构模式
| 模式 | 适用场景 | 注意点 |
|---|---|---|
| 客户端重试 | 模型 API、外部 HTTP | 必须有超时和幂等。 |
| 队列重试 | 异步任务 | 设置最大次数和死信队列。 |
| 熔断 | 下游持续失败 | 半开探测,不要永久切断。 |
| 降级 | 非关键能力失败 | 明确用户可见行为。 |
| 补偿 | 副作用已部分成功 | 需要业务支持反向操作。 |
5. 工程实现
重试策略配置:
retry_policies:
model_call:
max_attempts: 3
timeout_ms: 30000
backoff: exponential
jitter: true
retry_on: [rate_limit, timeout, unavailable]
payment_tool:
max_attempts: 1
require_idempotency_key: true
on_unknown: manual_review
search_tool:
max_attempts: 2
fallback: cached_result
调用包装:
def call_with_retry(operation, policy, idempotency_key):
for attempt in range(1, policy.max_attempts + 1):
try:
return operation(idempotency_key=idempotency_key, timeout=policy.timeout)
except Exception as exc:
if not should_retry(exc, attempt, policy):
raise
sleep(backoff_with_jitter(attempt, policy))
6. 生产实践
- 所有外部调用设置连接超时和总超时。
- 对 429/限流遵守上游返回的 retry-after 或速率限制建议。
- 重试要携带同一个幂等键和 trace id。
- 队列重试和代码内重试不要叠加失控;要计算总最大尝试次数。
- 对长时间故障使用熔断和降级,保护核心链路。
7. 常见反模式
- 无限重试,或者多个层级各自重试导致指数放大。
- 对权限错误、schema 错误、prompt injection 也重试。
- 工具调用没有幂等键,却对超时进行重试。
- 没有 dead letter queue,失败任务静默丢失。
- 只记录最终失败,不记录每次尝试的错误和延迟。
8. 评测方法
- 故障注入:模拟 429、503、超时、半成功副作用。
- 重试预算:验证最大尝试次数和成本上限。
- 熔断测试:下游持续失败时核心链路仍可工作。
- 恢复测试:下游恢复后半开探测能逐步恢复流量。
9. 安全与治理
- 安全类失败不重试,避免攻击流量放大。
- 对高成本模型调用设置 retry budget。
- 不把错误响应完整写入用户可见回复,避免泄漏内部系统信息。
- 对重复失败的工具禁用或转人工,防止模型在错误路径中循环。
10. 权威资料
- OpenAI Error codes: https://developers.openai.com/api/docs/guides/error-codes
- OpenAI Rate limits: https://developers.openai.com/api/docs/guides/rate-limits
- AWS Builders Library - Timeouts, retries, and backoff with jitter: https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/
- Google SRE Book - Handling Overload: https://sre.google/sre-book/handling-overload/
- Celery retrying tasks: https://docs.celeryq.dev/en/stable/userguide/tasks.html#retrying
11. 二次精修:错误分类决定重试策略
重试不是统一再试一次,而是先判断错误是否可恢复、是否有副作用、是否需要人工介入。
| 错误类型 | 示例 | 是否重试 | 策略 |
|---|---|---|---|
| Transient | 429、网络抖动、临时 5xx | 是 | 指数退避 + jitter |
| Deterministic | schema 不合法、权限不足 | 否 | 快速失败,修复输入或权限 |
| Partial side effect | 下游超时但可能已创建工单 | 谨慎 | 查 ledger 或业务事实源 |
| Model quality | 输出不满足 schema | 可少量 | 约束化重试或降级模型 |
| Safety block | 命中越权或注入策略 | 否 | 记录并上报安全事件 |
| Human pending | 审批未完成 | 不算失败 | 等待、提醒、过期取消 |
12. 重试控制流
retry_policy:
transient:
max_attempts: 3
backoff: exponential
base_seconds: 2
max_seconds: 60
jitter: true
model_schema_error:
max_attempts: 2
repair_prompt: true
unsafe_action:
max_attempts: 0
alert: security
13. 验收与运维指标
| 指标 | 解读 |
|---|---|
| Retry Success Rate | 重试是否真正提高成功率 |
| Retry Amplification | 一次用户请求放大的模型/工具调用数 |
| Duplicate Side Effect Rate | 重试导致重复副作用,目标为 0 |
| DLQ Inflow | 超限失败任务数量 |
| Mean Attempts Per Success | 成功任务平均尝试次数 |
| Cost Per Recovered Task | 每个被重试救回任务的成本 |
安全治理:注入攻击、权限错误、审批拒绝不能被重试绕过;重试日志要记录原错误、决策原因、预算消耗;对外部 API 要遵守对方 rate limit 和退避建议。
14. 补充权威资料
- AWS Builders Library: Timeouts, retries, and backoff with jitter: https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/ (核对日期:2026-05-09)
- Google SRE Book: Handling overload: https://sre.google/sre-book/handling-overload/ (核对日期:2026-05-09)