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
这会让系统不停重打本来就不会成功的任务。