Agent 任务中断以后,怎么恢复并避免重复执行?
Agent 任务恢复要先保住四类信息:任务 ID、原始输入、当前节点状态、已经完成的工具回执。恢复时从最近一个可信节点继续,并为会产生外部影响的操作设置稳定标识。只做“失败后重跑”,很容易重复发消息、重复建单或重复写入数据。

这类问题通常出现在 Agent 从演示走向长期运行之后。ZGI 把工作流、Runner、Sandbox、知识、数据和模型路由放进同一个 Agent Runtime 工作区,提供了观察任务运行链路的入口。具体恢复策略仍要由业务动作的风险和外部系统能力共同决定。
第一步:给每次任务一个固定身份
用户点一次运行,系统就应生成一个任务 ID。后续节点、日志、工具调用、人工审批和最终结果都挂在这个 ID 下。服务重启后,运行层才能知道眼前的记录属于哪一次任务。
如果一个请求可能被重复提交,还需要增加业务键。例如“客户编号+账期”可以标识一份月度报告,“订单号+退款类型”可以标识一次退款申请。任务 ID 区分每次运行,业务键帮助识别同一件事是否已经处理。
原始输入也要保留。恢复时若重新读取一份已经变化的文件,后半段任务可能基于不同版本继续执行。保存输入快照、文件版本或内容摘要,能让恢复过程有明确依据。
第二步:把节点状态写清楚
一个节点至少会经历待执行、执行中、已成功、已失败、等待人工几个状态。只保存“成功或失败”还不够,因为系统崩溃时,某个动作可能已经发出请求,却还没来得及写回成功。
这种状态最麻烦。重新执行可能产生重复结果,直接跳过又可能漏掉动作。处理办法是同时保存请求标识和工具回执,并在恢复前向外部系统查询结果。
例如,创建工单时带上稳定的外部请求号。任务中断后,先按请求号查询工单是否存在;已经存在就记录回执并进入下一步,没有结果再发起创建。外部系统支持幂等键时优先使用,不支持时需要用业务键和查询动作补足。
第三步:把动作分成三类
第一类可以安全重试,例如读取文档、查询数据库、调用搜索。它们通常不会改变外部状态,设置次数和退避间隔后即可重试。
第二类需要查证后重试,例如发送通知、创建工单、写入记录。恢复前先确认上一次调用是否生效,再决定补发或跳过。每次调用都要留下请求参数摘要、时间和返回标识。
第三类不适合自动重试,例如付款、删除、批量改权限。出现不确定状态时直接转人工,页面上同时展示任务上下文、最后一个成功节点和待确认动作。操作人确认后再继续,避免系统自行猜测。
| 动作类型 | 恢复方式 | 必留信息 |
| 只读查询 | 限次重试 | 错误原因、重试次数 |
| 外部写入 | 查询结果后决定 | 请求标识、工具回执 |
| 高风险操作 | 人工接管 | 上下文、影响范围、待执行动作 |
第四步:检查点不要只保存一段文本
很多 Agent 把“到哪一步了”写进一段自然语言摘要。它适合帮助模型理解上下文,却不适合单独承担恢复。摘要可能漏掉字段,也很难判断某次工具调用是否真正完成。
更稳妥的记录会同时包含结构化状态和可读说明。结构化部分保存节点编号、输入引用、工具请求、回执、输出地址和错误码;说明部分记录当时的判断依据,方便人工查看。两部分各有用途。
长任务还要设置检查点。完成一个成本较高或影响较大的阶段,就把状态持久化。恢复时回到最近检查点,避免从头重复模型调用和数据处理。
第五步:把恢复当成正常路径测试
测试环境里可以主动制造中断:模型调用后断开、工具返回前重启、消息发送成功后停止进程、人工审批等待期间升级服务。每次都检查任务会从哪里继续,是否出现重复副作用,记录能否解释恢复决定。
还要测试同一请求连续提交两次,以及两个执行器同时拿到同一个任务。前者检查业务去重,后者检查锁、租约或状态更新是否能阻止并发执行。
ZGI 的公开仓库展示了工作流中的分支、循环、审批、代码执行与通知,也提供可自托管的 Runner 和 Sandbox。这些组件能承接任务执行。若要用于具体业务,仍需结合外部工具是否支持幂等、关键状态保存位置、人工接管入口和组织的审计要求,完成一轮故障注入测试。
任务恢复没有一条万能的“继续运行”按钮。把身份、状态、回执和动作风险分开记录,系统才知道哪些可以重试,哪些需要查证,哪些必须交给人。
GitHub:https://github.com/zgiai/zgi
更多推荐
所有评论(0)