跳到主要内容

Queues、Retry、Backoff 与 Dead Letter

只要 Agent 系统开始走长链路、外部依赖和异步任务,队列问题很快就会出现。

系统会开始碰到这些情况:

  • tool 调用超时
  • provider 抖动
  • 外部 API 暂时不可用
  • approval 长时间没人处理
  • background run 卡住
  • 某一类任务不断失败

这时候如果没有队列和重试策略,失败很容易直接扩散。

这篇文档讨论的就是这一层。

1. 先把 4 个词分开

1.1 Queue

queue 负责把任务先排起来。

它主要解决:

  • 不要所有任务同时打到下游
  • 让任务可以异步消费
  • 给重试、延迟执行和失败隔离留空间

1.2 Retry

retry 负责在可恢复失败时再试一次。

它解决的是临时故障,不是逻辑错误。

1.3 Backoff

backoff 负责控制重试间隔。

它解决的是:

  • 不要瞬间连续重打
  • 给下游恢复时间
  • 避免雪崩式放大

1.4 Dead Letter

dead letter 负责接住反复失败、不能继续重试的任务。

它不是丢弃,而是隔离。

2. 哪些 Agent 任务特别需要队列层

最典型的是:

  • 长时间 research task
  • 大量并发 tool call
  • 发邮件、写库、外部通知
  • browser / computer use 执行链
  • background mode 长任务
  • 需要人工审批的异步任务

这些任务的共同点是:

  • 不是立即完成
  • 容易受外部系统影响
  • 失败后不能简单丢掉

3. 什么错误该 retry,什么不该

这是最关键的一层判断。

可以考虑 retry 的错误

  • 网络抖动
  • provider 临时超时
  • 速率限制
  • 短暂的 5xx
  • 暂时不可用的外部依赖

不该直接 retry 的错误

  • 参数错误
  • tool schema 错误
  • 权限错误
  • 审批被拒绝
  • 明显的业务规则冲突

也就是说:

  • retry 面向暂时失败
  • fix 面向确定性错误

4. 为什么 backoff 很重要

如果没有 backoff,重试通常会做两件坏事:

  • 在下游最脆弱的时候继续施压
  • 把一个局部故障放大成系统级抖动

所以即使第一版很简单,也应该有:

  • 固定延迟
  • 指数退避
  • 最大重试次数

5. 一个最小重试链路

这里最重要的是两件事:

  • retryable 判断
  • retry budget 控制

6. retry budget 最少该包括什么

至少建议有:

  • 当前第几次重试
  • 最大重试次数
  • 每次重试时间
  • 最后一次错误类型
  • 是否已进入 dead letter

如果还要再稳一点,可以再加:

  • 不同错误类型的不同重试上限
  • 不同工具的不同 backoff
  • 租约 / 锁超时信息

7. dead letter 到底拿来做什么

它不是“失败垃圾桶”。

它更像:

  • 隔离区
  • 人工处理队列
  • 失败样本来源
  • 回归样本来源

进入 dead letter 的任务,后面通常会进入这些动作之一:

  • 人工重放
  • 参数修正后重试
  • 转人工接管
  • 标成永久失败
  • 沉淀到 failure triage 和 regression 集

8. 最常见的 4 个坏模式

8.1 所有错误一律 retry

这会让系统不停重打本来就不会成功的任务。

8.2 retry 没有 backoff

结果通常是错误放大。

8.3 没有 dead letter

失败任务最后不是悄悄丢失,就是堆在主队列里反复打转。

8.4 retry 不带状态上下文

如果重试时丢掉:

  • run id
  • tool args
  • specialist 上下文
  • 上一次错误信息

排查会非常困难。

9. approval 和 queue 的关系

approval 任务经常适合进入队列,因为它们天然是异步等待型任务。

例如:

  • 触发 interrupt 后写入待审批队列
  • 审批通过后再投回执行队列
  • 审批超时后转失败队列或人工队列

这一层和 Tool Approval、Interrupt 与 Resume 是直接衔接的。

10. retry 和 failure triage 的关系

retry 不是为了掩盖问题,而是为了处理临时问题。

如果同一类任务不断进入 retry 或 dead letter,就要回到:

去看是不是:

  • route 有问题
  • tool schema 有问题
  • 某个 provider 在抖
  • 某类任务压根不该自动执行

11. 第一版怎么落地比较稳

比较稳的顺序通常是:

  1. 先给异步任务加 queue
  2. 再区分 retryable / non-retryable
  3. 再加 backoff
  4. 最后加 dead letter 和人工重放

这个顺序的好处是,每一层都能单独验证。

12. 和现有专题里的关系

最适合一起看的文档有:

13. 小结

队列层真正要解决的,不只是“异步执行”,而是把失败控制住:

  • 先排队
  • 再判断是否可重试
  • 重试时做 backoff
  • 最后把反复失败的任务隔离到 dead letter

这一层一旦补清楚,Agent 系统在面对外部依赖时会稳很多。