10.10概念更新于 2026年9月17日

长时间运行的任务

后台执行、断点续跑、异步通知与进度汇报。

10.10 · 课时讲解

长时间运行的任务

把任务从一次请求,升级为可暂停、可恢复、可观察的作业。

1 / 14

一句话理解:长任务的难点不在“多调几次模型”,而在于它必然会跨越进程重启、上下文上限和用户离开;Harness 要把任务从“一次请求”升级为“一个可暂停、可恢复、可观察的作业”。

一个 SEO 诊断 Agent 检查 5 个页面,两分钟就能跑完,用户盯着屏幕等结果就好。同一个 Agent 检查全站 3,000 个页面,要跑两三个小时。这时候会冒出一连串新问题:

  • 用户不可能一直开着页面,关掉之后任务还在跑吗?
  • 部署新版本会重启服务,跑到第 1,800 页的进度怎么办?
  • 上下文窗口不可能装下 3,000 页的检查结果,模型怎么记得前面发现了什么?
  • 跑到一半发现需要人确认某个判断,Agent 是干等着,还是先做别的?
  • 用户回来时,怎么一眼看懂“做了多少、发现了什么、还剩多少”?

这一课讲 Harness 需要为长任务提供的能力。长任务的交互设计见 异步任务体验,上下文压缩的细节见 长任务的上下文管理。

长任务会撞上的四堵墙

墙 表现 Harness 的对策
进程会死 部署、崩溃、机器回收导致任务中断 持久化执行:检查点 + 从中断处恢复
上下文会满 历史越来越长,成本上升、注意力下降,最终超限 压缩、清理旧工具结果、外置笔记、子任务隔离
人会离开 用户不在线,审批和问题无人回应 后台运行、异步通知、审批时暂停并保存状态
世界会变 两小时前查到的数据已经过期 关键动作前重新确认,状态带时间戳

Anthropic 工程团队在一篇关于长时间运行 Agent 的文章中总结过几种典型失败:Agent 想一次做完整个项目,结果上下文在实现中途耗尽;后续会话看到已有进展,就过早宣布完成;没有端到端测试就把功能标为完成。他们的对策是:先生成一份结构化的功能清单(初始全部标为未通过),每次只做一项,用 Git 提交记录进度,每次会话结束更新进度文件,并在标记完成前做端到端验证。这些做法不限于写代码,对任何长任务都适用。

架构:从“请求—响应”到“作业”

长任务的作业架构:任务 API 立即返回任务 ID,任务入队后由 Worker 运行 Harness 循环并写检查点、发进度、续心跳;Worker 崩溃后由其他 Worker 读检查点续跑 用户 / 定时器 / Webhook 任务 API 前端显示“已开始” 创建 立即返回任务 ID 任务队列 入队 关键设计 任务 ID 立即返回 每个业务步骤一个检查点 心跳与租约防重复接管 Worker · 运行 Harness 循环 每完成一个步骤: ① 写检查点(进度、产物引用) ② 发进度事件 ③ 心跳续约 任务状态存储 检查点 · 产物引用 事件流 / 通知 SSE · Webhook · IM Worker 崩溃 心跳超时 新 Worker 读检查点 从中断处续跑
图 1 · 从“请求—响应”到“作业”:检查点、进度事件和心跳让任务可暂停、可恢复、可观察

几个关键设计点:

  • 任务 ID 立即返回:创建任务的请求不等待完成。队列、Webhook、定时任务的基础知识见 异步、队列、Webhook 与定时任务。
  • 检查点粒度:太粗(整个任务一个检查点)等于没有;太细(每次模型调用都存完整历史)存储和性能开销大。常见做法是 每个业务步骤或每个有副作用的动作一个检查点。
  • 心跳与租约:Worker 定期声明“我还活着”,超时未续约的任务会被其他 Worker 接管。接管时要防止两个 Worker 同时执行同一个写操作,这又回到了 错误恢复与重试 中的幂等设计。

五个关键能力

1. 后台执行与断点续跑

需要区分两种“恢复”:

  • 对话恢复:把历史消息重新加载给模型,让它“记得刚才聊到哪”。
  • 任务恢复:知道哪些步骤已完成、产物在哪、下一步是什么。

只做对话恢复不够。对话历史可能已被压缩,模型也未必能从几百条消息里准确还原进度。长任务应该以 结构化的任务状态 为准,对话历史只是辅助。详见 任务状态与 Checkpoint。

以全站 SEO 诊断为例,一次崩溃加一次审批的完整时间线是这样的:

断点续跑时间线:Worker A 每步写检查点,第 1,800 页后崩溃,Worker B 心跳超时后接管并从 1,801 页续跑;审批等待期间主流程不阻塞 Worker A Worker B 审批人 逐页检查 1 → 1,800 崩溃 心跳超时,接管 读检查点,从 1,801 续跑 请求确认 等待审批(不阻塞,其余页面继续) 批准 时间 检查点
图 2 · 断点续跑:崩溃只丢失最后一个检查点之后的工作,审批也不会让整条作业停下

2. 上下文跨窗口

3,000 个页面的检查结果不可能全部留在上下文里。常用组合是:

  • 每检查完一批页面,把结论写入外部文件或数据库,上下文里只保留摘要;
  • 用子 Agent 处理单个页面,主 Agent 只接收精简结论(见 Subagent 与上下文隔离);
  • 开启自动压缩,并在项目说明中写明压缩时必须保留的信息(任务目标、已完成范围、关键发现)。Claude Agent SDK 的文档就建议把需要长期遵守的规则放在项目说明文件里,因为压缩可能丢失早期对话中的指令。

3. 暂停等待人工

长任务里的审批不能“阻塞式等待”:人可能几个小时后才回复。正确做法是 保存完整状态后暂停,人回复后再恢复。不同框架的实现方式:

框架 暂停与恢复机制
OpenAI Agents SDK 工具标记 needs_approval 后,运行结果中出现待审批项;把运行转为 RunState,可序列化为 JSON 保存,审批后再恢复运行
LangGraph 节点内调用 interrupt() 保存图状态并暂停,之后用 Command(resume=...) 恢复;需要配置 Checkpointer 和 thread_id
Claude Agent SDK PreToolUse Hook 返回 permissionDecision: "defer" 会结束本次运行,稍后恢复

审批期间,能并行推进的其他工作不必停下:例如 SEO Agent 等待“是否批量修改标题”的确认时,可以继续检查剩余页面。

4. 进度汇报

用户回来时需要回答三个问题:做到哪了?发现了什么?还要多久?这要求 Harness 维护一份“给人看”的进度,而不是让用户翻日志:

全站 SEO 诊断 · 运行中 1 小时 12 分
进度:1,840 / 3,000 页(61%)
发现:缺失 meta 描述 212 页 · 标题重复 37 组 · 404 链接 19 个
等待你确认:是否对 37 组重复标题生成改写建议?
预计剩余:约 45 分钟 · 已用预算:58%

计划与进度的呈现方式见 计划与进度。

5. 预算与超时

长任务更需要多重上限:总时长、总花费、单步超时、连续失败次数。触达上限时优先“保存进度并暂停”,而不是直接丢弃。Claude Agent SDK 在达到轮数或金额上限时返回带会话 ID 的结果,可以调高上限后恢复;托管平台 Claude Managed Agents 也支持在创建会话时设置花费上限,达到后会话暂停并进入空闲状态。

托管平台与持久化执行

如果不想自建队列、Worker 和状态存储,可以考虑现成方案:

  • 托管 Agent 平台:Claude Managed Agents(目前为 Beta)面向长时间运行和异步任务,会话在服务端保存对话历史与沙箱状态,通过事件流推送进度,可以中途发送消息引导或打断,还支持按 cron 表达式定时运行。需要注意,它因为有状态设计,目前不适用零数据保留(ZDR)安排。
  • 持久化执行引擎:OpenAI Agents SDK 的文档列出了与 Temporal、Restate、DBOS、Dapr 的集成,用于支持带故障恢复和人工介入的长时间运行 Agent。
  • 自带持久化的编排框架:LangGraph 通过 Checkpointer 持久化每个线程的图状态,用于对话延续、人工介入和容错。

选型的完整讨论见 框架与 SDK 选型。

常见误区

  • “把超时时间调到两小时就行。” 单个请求撑两小时,任何一次网络抖动或部署都会让全部进度归零。
  • “对话历史就是进度。” 历史会被压缩、会很长、很难被程序解析。进度必须是结构化状态。
  • “后台任务不用管体验。” 恰恰相反,看不见的任务最容易让用户焦虑,也最容易被重复提交。

设计要点

  • 创建任务立即返回任务 ID,并防止用户重复提交同一任务。
  • 每个业务步骤写检查点,每个写操作带幂等键。
  • 审批时保存状态并暂停,不阻塞等待;能并行的工作继续推进。
  • 维护一份面向用户的进度摘要:已完成、发现、待确认、预计剩余。
  • 恢复前重新确认关键业务状态;数据带上查询时间。
  • 设置总时长、总花费、单步超时与连续失败上限,触达后保存并暂停。

练习

把「全站 SEO 诊断 Agent」设计成长任务,用 60 分钟完成:

  1. 画出它的作业架构(参考本课的图),标出检查点写在哪几步。
  2. 设计一份任务状态 JSON,至少包含:总页数、已完成页数、每类问题的计数、待确认事项、已花费。
  3. 写出三个中断场景的恢复流程:Worker 在第 1,800 页崩溃;用户两小时后才审批;站点在诊断期间更新了 200 个页面。

延伸阅读

下一步

长任务往往没有人守在屏幕前。下一课「无人值守运行:SDK、CLI 与 CI」讲怎么把 Agent 放进 CI 和定时任务:用非交互模式运行、输出结构化结果、设好预算与权限上限。

试试:上下文、MCP、沙箱、Prompt 注入、外链