长时运行的 Agent 怎么做断点续跑?检查点、幂等与恢复策略
数据截至 2026-07,价格与限额以各官网为准。
断点续跑不是一个”加个 try-except 重试”就能解决的问题,它的本质是把 Agent 的执行进度从进程内存里搬出来,变成一份可以被外部读取、可以被重新装载的状态记录;只要进度还只活在内存里,进程一挂就什么都不剩。 想清楚这一点之后,剩下的工作其实是三件很具体的事:定义要存什么、保证工具调用重复执行不出事、定义从哪一步接着往下走。
一个常见的误解是”我用的框架自带 checkpoint,所以续跑这事框架已经帮我做完了”。框架帮你做的是状态的保存与装载这一层,它并不知道你的 Agent 在第 7 步调用的那个”创建订单”接口重复调一次会不会真的多出一张订单。真正会在生产上咬人的,恰恰是框架管不到的那一半。
一、先问一句:你真的需要断点续跑吗
不是所有 Agent 都值得为此付出复杂度。判断标准很朴素:单次任务的完整执行时间,是否明显超过你的运行环境愿意保证的连续存活时间。
- 一次问答式调用,几秒到几十秒返回,失败了整个重跑一遍成本很低——不需要检查点,加重试就够了。
- 一次跑十几分钟、要调二三十次工具的调研型任务——建议加,因为跑到第 25 步失败时全量重跑既慢又费 token。
- 跑几小时到几天、中间还要等人审批或等外部系统回调的流程——必须加,这类任务几乎不可能指望进程一直不挂。
顺带说一个容易被忽略的前置判断:如果你的场景只是单个 Agent 调用一两个工具,在 2026 年直接用 OpenAI Agents SDK 或 Anthropic Claude Agent SDK 这类更轻的路径,往往比先上一套多智能体框架更快,也不需要复杂的状态机——你可能根本没到需要”续跑”这个复杂度的位置。这个提醒值得放在任何选型讨论的最前面,免得过度设计。
二、断点续跑的本质:把”进度”从内存里挪出来
把一次 Agent 执行想象成一台状态机在往前走。每走一步,状态会变化:多了一条对话记录、多了一个工具返回值、某个计数器加一。只要每一步走完之后,你都能把当前完整状态写到进程之外的地方,崩溃就不再可怕。
这也解释了为什么”图”这种建模方式在长时任务上占便宜。以有向图为模型的框架——节点是函数或 LLM 调用,边定义控制流,状态以带类型的字典在节点之间传递——天然就有明确的”步与步之间”的切分点,检查点自然落在节点边界上。而以自由对话为模型的框架,几个 Agent 你一言我一语地聊,“一步”的边界在哪里其实是含糊的,要落检查点就得自己额外定义。
落到实现上,你需要一个存储层。最小可用的选择顺序大致是:本地文件(单机开发够用)→ 关系型数据库或 KV 存储(多进程、要查询历史)→ 带事务与租约的作业队列(多副本并发跑)。别一上来就上最重的那套,先看你的任务量。
三、检查点该存什么、不该存什么
这是最容易做错的一节。存少了恢复不出来,存多了每一步都在序列化一坨没用的东西,慢且贵。
建议存的:
- 进度游标:当前走到哪个节点/哪一步,下一步该去哪里。
- 累积的业务状态:这次任务已经产出的中间结果,比如已抓取的资料清单、已生成的段落。
- 消息历史或它的摘要:Agent 的短期记忆基本就是上下文窗口里的这堆消息,这部分丢了 Agent 就”失忆”了。历史很长时可以存摘要 + 最近 N 条,具体机制可以参考 AI Agent 的记忆是怎么实现的。
- 已完成工具调用的登记表:调用了什么、参数指纹是什么、返回了什么、有没有产生外部副作用。这张表是下一节做幂等的基础。
- 一个版本号或 schema 标记:将来你改了状态结构,旧检查点还能被识别出来做迁移或作废。
不建议存的:
- 密钥、令牌这类凭证:检查点很可能落在磁盘或数据库里,写进去等于多开一个泄露面。恢复时从环境变量重新读。
- 数据库连接、文件句柄、HTTP 客户端这类活对象:它们本来就不该被序列化,恢复时重建。
- 超大的原始产物:几十兆的 PDF 原文别塞进状态字典,存一个引用路径,正文放对象存储。
一个实用的经验:把状态设计成”可以被一个完全不知道前情的新进程读懂”的样子。写完之后自己做一次演练——杀掉进程,只拿这份 JSON,能不能推断出下一步该干什么。推断不出来,就是漏东西了。
{
"run_id": "task-20260728-0031",
"schema_version": 2,
"cursor": {"node": "verify_sources", "attempt": 1},
"state": {
"topic": "行业调研",
"collected": ["src-a", "src-b"],
"draft_sections": 3
},
"tool_log": [
{"call_key": "search:行业调研:p1", "status": "done", "side_effect": false},
{"call_key": "create_ticket:REQ-88", "status": "done", "side_effect": true}
],
"updated_at": "2026-07-28T10:31:00Z"
}
上面这段只是一个结构示意,字段名你自己定;重点是 cursor、state、tool_log 这三块信息缺一不可。
四、幂等:续跑最容易翻车的地方
这是全篇最该反复读的一节。恢复执行意味着某些步骤会被重复执行,如果这一步有外部副作用,重复就等于事故。
典型的翻车场景:Agent 跑到”给客户发确认邮件”这一步,邮件发出去了,但在写检查点之前进程崩了。恢复时它看到的最后状态是”还没发邮件”,于是又发一遍。客户收到两封。
处理办法按可靠性从高到低排:
- 让工具本身支持幂等键。调用方生成一个稳定的
call_key(比如任务 ID + 步骤 + 参数哈希),服务端见到重复的键就返回上次的结果而不是再执行一次。这是最干净的做法,但需要对方接口配合。 - 先登记、再执行、后确认。写入”意图执行”的记录 → 执行 → 写入”已完成”。恢复时看到”意图执行”但没有”已完成”的记录,说明这一步状态不明,交给下面的策略处理,而不是无脑重跑。
- 恢复时先查询再决定。执行前先调一次查询接口确认”这件事是不是已经做过了”。多一次调用,但对不支持幂等键的老系统往往是唯一可行的路子。
- 把有副作用的动作单独隔离出来,集中放在流程的少数几个节点上,并在这些节点前后强制落检查点。副作用点越少越集中,你要操心的地方就越少。
还有一条纪律:只读工具和写入工具要在代码层面区分标记。搜索、查询、读文件这类重复执行无所谓,可以放心重放;下单、发消息、转账、改配置这类必须走上面的保护。这个区分做在工具注册的地方,比事后靠人记要可靠得多。
五、恢复策略:重放、跳过还是回滚
进程重启后拿到检查点,接下来的动作不止一种,得按情况选。
- 重放(replay):从最后一个成功检查点原样往下跑。适合纯计算、纯查询的步骤,也是默认策略。
- 跳过(skip):确认某一步的副作用已经生效,直接标记完成,从下一步开始。需要幂等登记表来判断。
- 回滚(compensate):这一步做了一半、且做了一半比没做更糟(比如批量改了一半配置),需要执行一个补偿动作把它撤回去,再重来。补偿逻辑得你自己写,没有框架能替你想清楚业务上”撤回”意味着什么。
- 挂起等人(escalate):状态不明、自动判断有风险,就停下来把这次运行标记为待人工确认。听上去消极,但在失败代价高的场景里这往往是最负责任的选项。
另外记得给恢复本身设上限:同一个节点连续恢复失败超过 N 次就停,别让它无限重试。无限重试在长时任务里非常危险——它不只是浪费 token,还可能对下游系统持续发压。关于成本这块可以顺带看看 token 成本优化里的思路。
六、框架能帮到哪一步
先说明口径:下面的对比来自 2026 年的多篇第三方实战评测,不是各项目官方文档的逐条核实结果,具体能力和用法请以各项目官方文档当前版本为准。
LangGraph 在长时任务这条线上是目前被提到最多的。它以有向图为模型,对执行流的控制更精细,第三方评测口径称它支持持久化的长时运行工作流与 human-in-the-loop,包含 checkpointing、streaming、human-in-the-loop 这几类原语。在带反馈环的循环任务上,第三方对比里它胜出。同一份实测对比中还给了几个维度的排序:控制力最强、生产成熟度最成熟、token 效率最好、生态规模最大,代价是学习曲线最陡。
CrewAI 以”一队有明确角色的 agent”为模型(研究员→写手→审稿这种编排),串行并行都行,上手最快、学习曲线最平缓。它技术上也支持循环,但第三方评测的说法是调试起来比较痛苦。这里要纠正一个过时结论:CrewAI 在 2025 年加了 Flows,一种事件驱动的 pipeline 模式,面向更可预测的生产型负载,很多较老的对比文章没有涵盖这一点,所以”CrewAI 只能做原型”这句旧判断不宜再直接沿用。
AutoGen / AG2 走的是基于对话的路线,多个 agent 互相交谈,对话模式最丰富,在多方辩论、达成共识、代码生成与调研类任务上有它的长处;同一份对比中它的 token 开销是三者里最大的。但选型时必须知道一件事:微软已把重心转向更大的 Agent Framework,AutoGen 的主要新功能开发已经停止,进入维护模式,仍有 bug 修复和安全补丁,社区正在寻找替代。有实践者直言 2026 年不适合把它作为新项目的起点。这是就事论事的现状陈述——存量项目并不需要恐慌迁移,它还在被维护;但如果你现在要新起一个需要长期演进的长时任务系统,把这条信息纳入判断是合理的。
选型上不存在”唯一最好”:有循环、有分支逻辑、需要生产级可观测性、失败代价高,倾向 LangGraph;一天内要出可用原型、流程基本线性,CrewAI 门槛最低。更完整的横向比较可以看 主流 AI Agent 框架对比。
七、等人审批也是一种”长停顿”
很多长时 Agent 之所以长,不是因为算得慢,而是因为中间要等一个人点确认,或者等外部系统回调。这两种情况在工程上和”崩溃恢复”是同一个问题:进程不该在那儿干等着。
做法是把”等待”变成一次主动的挂起——写检查点、释放进程、留下一个可以被外部事件唤醒的运行 ID。审批通过时,外部系统带着这个 ID 回来,你从存储里装载状态继续往下走。这样一次跑三天的流程,实际占用的计算时间可能只有几分钟。
顺带提一句互操作:跨系统协作时会涉及协议层的选择,第三方资料提到 CrewAI 已加入 A2A 支持;另有 OpenAgents 声称自己是唯一原生同时支持 MCP 与 A2A 的框架(“声称”二字保留,未独立核实)。协议这块的背景可以看 MCP 协议是什么和 Agent 协议生态对比。
八、一套可落地的最小清单
如果你现在就要动手,按这个顺序做,投入产出比较高:
- 给每次运行分配一个稳定的
run_id,全链路日志都带上它。 - 定义状态结构,加上 schema 版本号,写一个”从状态推断下一步”的纯函数。
- 在每个节点边界后写检查点;有副作用的节点前后各写一次。
- 给所有工具打上”只读 / 有副作用”标记,有副作用的补幂等键或先查后写。
- 实现装载逻辑,并真的做一次演练:跑到一半
kill -9,然后从检查点恢复,比对最终结果。 - 加上单节点重试上限和整体超时,配一个”人工介入”的出口。
- 把检查点写入本身也做成可观测的——记录每次写入的耗时和体积,状态膨胀是长时任务的隐性杀手。
第 5 步是很多团队跳过的一步,但不做这次演练,你的恢复代码基本等于没测过。
九、诚实说局限
有几件事这套做法解决不了,得提前知道:
**LLM 的不确定性会让”重放”不完全等价。**同样的输入,模型两次输出未必逐字相同。如果你的流程依赖某一步的具体措辞,恢复后走出的路径可能和原来不一样。缓解办法是把关键决策的结果写进状态,恢复时读状态而不是重新问模型。
**状态会膨胀。**跑得越久,消息历史越长,检查点越大,序列化开销和上下文成本一起上涨。得配套做摘要或裁剪策略,这本身是另一个需要调的东西。
**外部世界会变。**任务暂停三天再恢复,中途引用的网页可能已经改了、库存数字已经不是原来那个。长停顿之后要不要重新校验关键前提,是业务判断,不是技术问题。
**框架能力在快速变化。**上面引用的能力对比来自 2026 年的第三方评测,不同版本之间差异可能很大,真正动手前请以各项目官方文档当前版本为准,别拿一篇文章的结论当规格书。
小结
断点续跑的核心是把执行进度外置成可装载的状态,而不是给代码加重试。检查点要存进度游标、业务状态、消息历史和工具调用登记表,不要存凭证和活对象。最容易出事的地方是有副作用的工具重复执行,解决靠幂等键、先登记后执行、或恢复前先查询。恢复不只有”重放”一种选择,跳过、补偿、挂起等人各有适用场景,并且一定要设重试上限。框架能帮你处理状态的保存与装载,业务上”重复做一次会怎样”这个判断,只能你自己下。