🛡️ 重试与容错策略

🎯 为什么 Agent 需要容错

Agent 的生产链路涉及LLM API、工具服务、数据库、外部 API 等多个依赖方,任何一个环节的失败都可能导致整个任务中断。与传统的微服务不同,Agent 的容错需要考虑 LLM 特有的失败模式(如 Rate Limit、Context Length Exceeded、Content Filter 等)。

🔑 幂等性设计

在构建 Agent 容错策略前,幂等性设计是前提。Agent 的工具调用可能因重试而被重复执行——如果操作不幂等(如重复扣款、重复发送邮件),容错机制反而会引入数据不一致风险。

  • 天然幂等操作:查询、读取、检查状态(GET 类操作)
  • 需要设计幂等:写入、删除、发送(使用幂等键 Idempotency Key)
  • 难以幂等:物理世界操作(打印、机器人动作),需要确认机制
  • 最佳实践:每个写操作的 API 接受幂等键,服务端通过幂等键去重

🔄 LLM 调用重试

LLM API 是最容易出错的环节之一。常见的失败模式包括:

失败类型典型原因HTTP 状态码重试策略
Rate Limit 超出 API 速率限制 429 指数退避 + 读取 Retry-After 头
Server Error API 服务端临时故障 500 / 502 / 503 指数退避重试
Timeout 请求超时(网络/模型推理慢) 超时异常 退避重试 / 模型降级
Context Length 上下文超出模型限制 400 不重试 · 截断/压缩上下文
Content Filter 内容被安全策略拦截 400 不重试 · 返回安全提示

指数退避 + 抖动 (Exponential Backoff with Jitter)

指数退避是分布式系统中最经典的重试策略:每次重试的等待时间指数级增长,避免对服务端造成雪崩式压力。在此基础上加入随机抖动 (Jitter),防止多个客户端同时重试造成"惊群效应"。

def retry_with_backoff(max_retries=5, base_delay=1, max_delay=60):
for attempt in range(max_retries):
try:
return call_llm_api()
except RetryableError as e:
delay = min(base_delay * (2 ** attempt), max_delay)
jitter = random.uniform(0, delay * 0.1) # 10% 抖动
time.sleep(delay + jitter)
raise MaxRetriesExceeded()
  • base_delay:初始等待时间(如 1 秒)
  • 最大延迟上限:避免等待时间无限增长(如 60 秒)
  • Jitter 范围:通常为延迟的 10%~25%

🔧 工具调用失败处理

Agent 的工具调用可能因参数错误、外部服务不可用、权限不足等原因失败。处理策略分为三个层次:

🔄 自我修复 (Self-Healing)

将错误信息返回给 LLM,让 Agent 根据错误信息调整策略——修正参数、选择替代工具、或调整执行计划。

  • 错误信息需结构化——错误码 + 可读的描述
  • 限制自我修复次数(防止无限循环)
  • 示例:"API 返回 404,尝试搜索替代数据源"

⬇️ 降级 (Fallback)

当主要工具不可用时,切换到备用工具或简化处理。如搜索 API 故障时回退到本地缓存。

  • 明确降级触发条件
  • 降级路径需事先定义(编码而非 LLM 决策)
  • 降级事件需告警——降级是"异常"状态

🛑 快速失败 (Fail-Fast)

对于不可恢复的错误(权限不足、参数非法),立即返回明确的错误信息,不浪费重试资源。

  • 区分可重试和不可重试的错误类型
  • 快速失败 + 精确的错误码 + 解决建议
  • 避免用户/Agent 陷入无效的重试循环

📉 降级策略

降级是容错体系中最重要但最容易被忽视的环节。一个好的降级策略可以让 Agent 在部分依赖不可用的情况下,仍然提供有价值的服务(即使不是最优的)。

降级层级策略示例用户体验影响
L1 · 功能降级 关闭非核心功能,保留核心能力 关闭实时翻译,保留文本问答
L2 · 模型降级 切换到更小/更便宜的模型 GPT-4 → GPT-4o-mini 中(质量下降)
L3 · 数据降级 使用缓存/静态数据替代实时数据 实时行情 → T-1 缓存数据 中(时效性下降)
L4 · 静态兜底 返回预定义的静态回复 返回"系统繁忙,请稍后再试"

🔌 熔断机制 (Circuit Breaker)

熔断器是一种自动保护机制:当某个外部依赖的失败率超过阈值时,自动"断开"对该依赖的调用,直接返回降级响应,防止级联故障蔓延。

🟢 关闭 (Closed)
正常调用 · 监控失败率
🟡 半开 (Half-Open)
试探性调用 · 评估恢复
🔴 断开 (Open)
拒绝调用 · 直接返回兜底

熔断器核心参数

参数说明推荐值
失败阈值 在时间窗口内失败多少次触发熔断 5~10 次
时间窗口 统计失败率的滑动窗口大小 30~60 秒
熔断时长 断开状态持续多久后进入半开 30~120 秒
半开试探数 半开状态下放行多少请求用于探测 1~3 个

📊 容错策略对比

策略保护对象恢复方式复杂度适用场景注意事项
重试 单次调用 透明重试,指数退避 偶发故障、网络抖动 需幂等;注意重试风暴
超时控制 调用链路 取消等待,触发降级 所有外部调用 超时时间需根据 P99 设定
熔断 下游服务 自动断开/恢复 高频调用、级联风险大 配置不当可能过于敏感
降级 业务功能 切换到备用路径 核心依赖不可用时 需提前设计降级路径
隔离 故障域 线程池/进程级隔离 多工具并发调用 增加资源开销
限流 系统整体 令牌桶/滑动窗口 保护 API 配额和预算 与业务优先级对齐
💡 容错设计原则
  • 假设所有依赖都会失败:每个外部调用都应有超时、重试和降级
  • 幂等性优先:重试的前提是操作可以安全重复
  • 渐进式降级:尽可能保留核心功能,而非全有或全无
  • 快速失败优于慢速失败:不可恢复的错误应立即返回,避免资源浪费
  • 可观测驱动:容错事件必须可追踪、可告警、可复盘