欢迎光临
我们一直在努力

AI Agent 长任务总在中断后跑偏?一份 workflow-state.md 把它变成可恢复流程

AI Agent 长任务总在中断后跑偏?一份 workflow-state.md 把它变成可恢复流程

做 AI Agent 长任务时,最浪费时间的场景往往不是某一步做错,而是:资料查完、脚本写到一半、部分结果已经出来;会话一中断,下一轮又从头搜索,甚至把已验证的步骤重做一遍。

这通常不是模型“记忆力不好”。真正的问题是,任务事实散落在对话、终端输出和临时文件里,没有一份能让下一轮直接接手的状态。

本文给出一个不依赖框架的办法:用一份 workflow-state.md,把长任务从“靠上下文续命”变成“按状态恢复”。它适合 Codex、Claude Code、Cursor,也适合你自己写的自动化脚本。

1. 哪些信息必须留下来

不要把整段对话复制进状态文件。真正有用的只有四类事实:

类别要记录什么示例
目标 最终要交付什么 一份可运行的导入脚本和校验报告
已验证项 已通过、无需重做的步骤 100 条源数据已完成格式校验
当前卡点 精确停在何处、为什么停 import-003 超时,结果未知
下一动作 恢复时的第一件事 先检查目标表是否已有 import-003

其中最重要的是“结果未知”。网络超时、页面断开、模型生成超时,都不等于失败。没确认前立刻重试,最容易造成重复写入、重复扣费或覆盖已有成果。

2. 一份可以直接复制的状态文件

在项目根目录新建 workflow-state.md:

# 任务状态

## 目标
– 将 `source/` 中的 CSV 导入本地 SQLite,并输出 `reports/check.md`。

## 不可违反的约束
– 不修改源 CSV。
– 已成功导入的批次不得重复写入。
– 只在校验通过后生成最终报告。

## 已完成
– [x] `source/` 文件清单已固定:12 个 CSV。
– [x] `import-001`、`import-002` 已校验通过。

## 当前状态
– `import-003`:请求超时;结果未知。
– 已知输出位置:`data/app.db`。

## 恢复步骤
1. 查询 `data/app.db` 是否已有 `import-003` 的批次记录。
2. 有记录则执行行数和哈希校验;无记录才重试导入。
3. 通过后更新“已完成”,再处理 `import-004`。

这份文件的标准不是漂亮,而是一个没参与前文的人能否在 30 秒内知道接下来该做什么。

3. 恢复前,先做一次只读核对

长任务恢复时,最危险的动作不是“继续”,而是“盲目继续”。先检查日志、落盘文件和目标系统,再决定是否重试:

#mermaid-svg-Ol4FhyrlxtoDeTIc{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ol4FhyrlxtoDeTIc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ol4FhyrlxtoDeTIc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ol4FhyrlxtoDeTIc .error-icon{fill:#552222;}#mermaid-svg-Ol4FhyrlxtoDeTIc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ol4FhyrlxtoDeTIc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ol4FhyrlxtoDeTIc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ol4FhyrlxtoDeTIc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ol4FhyrlxtoDeTIc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ol4FhyrlxtoDeTIc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ol4FhyrlxtoDeTIc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ol4FhyrlxtoDeTIc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ol4FhyrlxtoDeTIc .marker.cross{stroke:#333333;}#mermaid-svg-Ol4FhyrlxtoDeTIc svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ol4FhyrlxtoDeTIc p{margin:0;}#mermaid-svg-Ol4FhyrlxtoDeTIc .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Ol4FhyrlxtoDeTIc .cluster-label text{fill:#333;}#mermaid-svg-Ol4FhyrlxtoDeTIc .cluster-label span{color:#333;}#mermaid-svg-Ol4FhyrlxtoDeTIc .cluster-label span p{background-color:transparent;}#mermaid-svg-Ol4FhyrlxtoDeTIc .label text,#mermaid-svg-Ol4FhyrlxtoDeTIc span{fill:#333;color:#333;}#mermaid-svg-Ol4FhyrlxtoDeTIc .node rect,#mermaid-svg-Ol4FhyrlxtoDeTIc .node circle,#mermaid-svg-Ol4FhyrlxtoDeTIc .node ellipse,#mermaid-svg-Ol4FhyrlxtoDeTIc .node polygon,#mermaid-svg-Ol4FhyrlxtoDeTIc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ol4FhyrlxtoDeTIc .rough-node .label text,#mermaid-svg-Ol4FhyrlxtoDeTIc .node .label text,#mermaid-svg-Ol4FhyrlxtoDeTIc .image-shape .label,#mermaid-svg-Ol4FhyrlxtoDeTIc .icon-shape .label{text-anchor:middle;}#mermaid-svg-Ol4FhyrlxtoDeTIc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Ol4FhyrlxtoDeTIc .rough-node .label,#mermaid-svg-Ol4FhyrlxtoDeTIc .node .label,#mermaid-svg-Ol4FhyrlxtoDeTIc .image-shape .label,#mermaid-svg-Ol4FhyrlxtoDeTIc .icon-shape .label{text-align:center;}#mermaid-svg-Ol4FhyrlxtoDeTIc .node.clickable{cursor:pointer;}#mermaid-svg-Ol4FhyrlxtoDeTIc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Ol4FhyrlxtoDeTIc .arrowheadPath{fill:#333333;}#mermaid-svg-Ol4FhyrlxtoDeTIc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Ol4FhyrlxtoDeTIc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Ol4FhyrlxtoDeTIc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ol4FhyrlxtoDeTIc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Ol4FhyrlxtoDeTIc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ol4FhyrlxtoDeTIc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Ol4FhyrlxtoDeTIc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ol4FhyrlxtoDeTIc .cluster text{fill:#333;}#mermaid-svg-Ol4FhyrlxtoDeTIc .cluster span{color:#333;}#mermaid-svg-Ol4FhyrlxtoDeTIc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Ol4FhyrlxtoDeTIc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ol4FhyrlxtoDeTIc rect.text{fill:none;stroke-width:0;}#mermaid-svg-Ol4FhyrlxtoDeTIc .icon-shape,#mermaid-svg-Ol4FhyrlxtoDeTIc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ol4FhyrlxtoDeTIc .icon-shape p,#mermaid-svg-Ol4FhyrlxtoDeTIc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Ol4FhyrlxtoDeTIc .icon-shape .label rect,#mermaid-svg-Ol4FhyrlxtoDeTIc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ol4FhyrlxtoDeTIc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ol4FhyrlxtoDeTIc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ol4FhyrlxtoDeTIc :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

存在

不存在

不确定

状态为 generating 或 timeout

检查日志、落盘文件和目标系统

结果是否存在?

校验后标记 passed

标记 failed,再决定是否重试

停止写入,继续定位

这一步尤其适合外部 API、批量图片生成、数据导入和线上发布。它把“我觉得应该失败了”改成“我已经确认没有结果,可以安全重试”。

4. 给每个昂贵步骤一个稳定 ID

“再跑一次第 3 批”不够可靠。更好的做法是为任务分配稳定 ID:

research-001
import-003
render-012
review-012

ID 一旦创建就不改。日志、输出文件、状态文件都引用同一个 ID。这样无论是人工接手、Agent 恢复,还是隔天回查,都不需要猜“第 3 批”具体是哪一次。

5. 从一个小任务开始

第一次不必给整个项目建状态系统。选一个会跨两轮完成的任务:写清目标和三条约束,为批次分配稳定 ID,每完成一批更新“已完成 / 当前 / 下一步”,再主动中断一次,只靠状态文件恢复。

如果能顺利恢复,说明你得到的不是一份日报,而是一套可复用的任务记忆。

结语

上下文窗口适合思考,不适合承担项目记忆。把可验证的事实写进状态文件,Agent 才能在会话中断、模型切换或人工接手后继续向前,而不是反复从起点出发。

你在长任务中最常丢失的是进度、文件位置,还是“为什么当时没有继续做”?欢迎留言,我会把高频问题整理成下一篇的恢复检查清单。

赞(0)
未经允许不得转载:171主机测评 » AI Agent 长任务总在中断后跑偏?一份 workflow-state.md 把它变成可恢复流程
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址