每个交付智能体系统的团队,最终都会问同一个问题,通常在第三个月左右:“我们需要 Temporal / Inngest / Restate 吗,还是加点 retries 就够了?”
答案几乎总是“你需要持久化编排器,但理由不是‘retries’。”
retries 实际上解决什么
retries 是在 发起调用的同一个进程 观察到瞬时失败时的正确工具。网络抖动、限流响应、抖动的下游——调用方手里握着失败的结果,知道自己在做什么,可以直接再试一次。
为此你需要:一个带指数退避的重试策略、一个最大尝试次数上限,以及接收方的幂等性。这是个库,不是个系统。p-retry、tenacity、tokio-retry——挑一个,继续干活。
持久化执行实际上解决什么
持久化执行,是在 进程本身 可能在两步之间挂掉时的正确工具。崩溃、部署、k8s 驱逐 pod、一次 30 分钟超出请求超时的 LLM 调用——问题不是“能否重试”,而是“断电时我们走到哪一步了,如何在不重做已经成功的部分的情况下继续?”
这是一个本质不同的问题。它需要:
- 持久化的步骤状态——一份记录,标明哪些步骤已完成及其结果。
- 可重放的历史——进程恢复时遍历该日志,跳过已完成的步骤,从第一个未完成的继续。
- 确定性的步骤边界——代码结构使编排器能在多次重放中无歧义地识别步骤。
你可以从零写出来。有人这么做。结果是花六个月调试竞态,然后才意识到自己造出了一个更差的 Temporal。
真正的决策
如果你的智能体系统具备:
- 单次耗时超过几秒的工具调用,
- 包含约 3 个以上顺序步骤的工作流,
- 中间某处存在交接或人在环节中,
- 无法容忍一次部署重启导致用户可见失败的 SLA,
……那你需要持久化编排器。不是“最好有一个锦上添花”。你需要它,而且事后再加比从一开始就用要昂贵得多。
如果你的系统短、同步、无状态(一个 prompt,一个响应,5 秒搞定),retries 就够了。别过度工程化。
我们交付什么
实践中,我们默认用 Temporal 或 Restate(取决于语言 stack),工作流代码组织成让每次 LLM 调用、工具调用和审批都成为独立的步骤。代价是一些学习曲线和一个需要运维的运行时。收益是“这个进程在工作流中途崩了会发生什么”不再是我们每个新功能都得回答的问题——编排器一次性回答了它。
retries 解决“这次调用失败了”。持久化执行解决“这个 工作流 需要在运行它的东西失败时仍然存活下来”。二者不是对立——大多数生产系统两者都需要,而被低估的是第二个。