第 14 章:Long-running Agent

本章导读

  • 核心问题:如何让 Agent 任务跨阶段、跨窗口、可暂停和可恢复。
  • 关键词:Long-running Agent、Task State、Checkpoint、Resume、阶段化
  • 学习产出:把复杂 CI 排障拆成可恢复的阶段化任务。

1. 本章要解决什么问题

上一章讨论了 Harness。

这一章进一步讨论一个更难的问题:

Agent 如何连续运行几十分钟、几小时,甚至跨多个上下文窗口完成复杂软件工程任务?

这类 Agent 可以称为 Long-running Agent。

Long-running Agent 面临的问题和普通 Agent 不同。

普通 Agent 可能只需要几轮工具调用。

Long-running Agent 需要处理:

  • 任务拆分;
  • 多阶段执行;
  • 上下文耗尽;
  • 中断恢复;
  • 状态持久化;
  • 半完成代码;
  • 长期验证;
  • 多次失败修复;
  • 任务优先级;
  • 人工接管;
  • 成本和资源控制。

本章核心观点是:

Long-running Agent 的关键不是更长上下文,而是可恢复的任务状态机、检查点、验证机制和运行时调度。

本章回答:

  • 为什么长上下文不能单独解决长任务;
  • Long-running Agent 常见失败模式;
  • 如何把任务拆成阶段;
  • Checkpoint 应保存什么;
  • Resume 如何恢复;
  • 如何用 Java / Spring Boot 实现长任务 Agent。

2. 对应 Anthropic 文章

本章主要对应:

  • Harness Design for Long-running Application Development

文章讨论了长时间应用开发任务中的 Harness 设计。

其中一个重要经验是:

模型能力提升后,系统瓶颈越来越多地转移到 Harness 设计、验证和任务组织上。

如果只给 Agent 一个高层目标,例如:

构建一个完整 Web 应用。

Agent 容易出现:

  • 一次做太多;
  • 半途上下文耗尽;
  • 下一个会话无法接续;
  • 基础功能还坏着就继续加新功能;
  • 没有系统性 QA;
  • 最后产物看似完成但核心交互不可用。

这些问题不是一句 Prompt 能解决的。

3. Long-running Agent 的失败模式

3.1 一次做太多

Agent 常见错误是试图一口气完成大任务。

例如:

实现登录、聊天、文件上传、权限、搜索、设置页。

结果是:

  • 上下文被快速填满;
  • 多个功能半完成;
  • 测试难以定位;
  • 下一个会话不知道哪些完成了;
  • 系统处于不稳定状态。

解决方式:

把任务拆成可验证的小阶段。

3.2 状态只存在上下文中

如果任务状态只存在模型对话里,一旦 compaction 或会话重启,就容易丢失关键细节。

例如:

刚刚修改了 A 文件,但还没运行测试。
B 方案被用户否定。
C bug 是已知问题,不要重复修。

这些必须写入外部状态。

3.3 没有阶段性验证

长任务如果只在最后验证,风险很高。

正确方式是每个阶段都验证。

例如:

完成登录页面 → 运行登录 E2E
完成聊天发送 → 运行发送消息 E2E
完成文件上传 → 运行上传测试

3.4 恢复时上下文重建失败

恢复任务时,Agent 不需要看到全部历史。

它需要看到:

目标
当前阶段
已完成事项
未完成事项
关键决策
当前代码状态
最近验证结果
下一步

如果 Checkpoint 没有这些信息,恢复就会失败。

3.5 后期只做表面修补

长任务后期,Agent 可能陷入“修一个报错,引入另一个报错”的循环。

这通常是因为缺少全局验证和阶段边界。

Harness 应定期要求:

  • 运行端到端验证;
  • 检查核心功能;
  • 更新任务状态;
  • 必要时回滚或重规划。

4. 长任务的基本设计原则

4.1 任务必须阶段化

长任务应拆成阶段:

Discovery
Planning
Implementation
Verification
Stabilization
Summary

或者针对应用开发:

Scaffold
Core Flow
Feature 1
Feature 2
QA
Polish

每个阶段都要有:

  • 输入;
  • 输出;
  • 完成条件;
  • 验证方式;
  • 失败处理。

4.2 每个阶段必须可验证

阶段完成不能只靠模型判断。

例如:

阶段:实现登录
完成条件:用户可以输入账号密码并进入首页
验证:E2E 测试 login.spec.ts 通过

4.3 状态必须外部化

不能把状态只放在上下文中。

需要持久化:

  • 数据库;
  • 文件;
  • CheckpointStore;
  • 任务状态机;
  • Git commit;
  • Progress file。

4.4 恢复时重建最小上下文

恢复时应加载:

任务目标
最新 Checkpoint
当前阶段
最近 Git Diff
最近验证结果
未完成 Todo
相关项目知识

而不是重放完整历史。

4.5 定期健康检查

长任务开始前和阶段切换前,应运行健康检查。

例如:

pwd
读取进度文件
git status
运行基础测试
启动应用
执行 smoke test

如果系统已经坏了,应该先修复基础状态,再继续新功能。

5. Long-running Agent 状态机

一个典型状态机:

CREATED
  ↓
INITIALIZING
  ↓
PLANNING
  ↓
EXECUTING
  ↓
VERIFYING
  ↓
CHECKPOINTING
  ↓
COMPLETED

异常路径:

BLOCKED
FAILED
PAUSED
RESUMING
ESCALATED
CANCELLED

状态机比自由循环更适合长任务,因为它让任务可观察、可恢复、可调度。

6. Checkpoint 应保存什么

一个有效 Checkpoint 至少包含:

taskId
sessionId
phase
objective
currentPlan
completedSteps
pendingSteps
changedFiles
toolResultSummaries
verificationResults
decisions
openQuestions
risks
nextAction
createdAt

Checkpoint 不是聊天摘要。

它是任务恢复协议。

7. Resume 流程

恢复不是简单把历史对话塞回模型。

推荐流程:

加载最新 Checkpoint
  ↓
检查工作区状态
  ↓
读取 Git Diff
  ↓
运行基础验证
  ↓
重建 Context Window
  ↓
让 Agent 确认当前阶段
  ↓
继续执行下一步

如果工作区状态和 Checkpoint 不一致,应先进入 Recovery。

8. 架构图 / 流程图

Long-running Agent 状态机
图 14-1 Long-running Agent 状态机 这张图展示长任务从创建、执行、验证、恢复、暂停到完成或失败的状态迁移。 Mermaid 源文件

8.1 长任务状态机

长任务状态机
图 14-2 长任务状态机 Mermaid 源文件

8.2 Resume 流程

Resume 流程
图 14-3 Resume 流程 Mermaid 源文件

8.3 阶段化应用开发

阶段化应用开发
图 14-4 阶段化应用开发 Mermaid 源文件

9. Java / Spring Boot 落地方案

9.1 TaskState

public enum TaskState {
    CREATED,
    INITIALIZING,
    PLANNING,
    EXECUTING,
    VERIFYING,
    CHECKPOINTING,
    PAUSED,
    RESUMING,
    BLOCKED,
    ESCALATED,
    COMPLETED,
    FAILED,
    CANCELLED
}

9.2 LongRunningTask

public record LongRunningTask(
    String taskId,
    String objective,
    TaskState state,
    String currentPhase,
    Instant createdAt,
    Instant updatedAt,
    TaskBudget budget
) {}

9.3 Checkpoint

public record Checkpoint(
    String checkpointId,
    String taskId,
    String sessionId,
    String phase,
    AgentPlan currentPlan,
    List<String> completedSteps,
    List<String> pendingSteps,
    List<String> changedFiles,
    List<VerificationResult> verificationResults,
    List<String> decisions,
    List<String> openQuestions,
    List<String> risks,
    String nextAction,
    Instant createdAt
) {}

9.4 ResumeManager

public interface ResumeManager {
    AgentSession resume(String taskId);
}

实现逻辑:

public class DefaultResumeManager implements ResumeManager {

    public AgentSession resume(String taskId) {
        Checkpoint checkpoint = checkpointStore.latest(taskId)
            .orElseThrow(() -> new NoCheckpointException(taskId));

        WorkspaceState workspace = workspaceInspector.inspect(checkpoint);
        VerificationResult smoke = verificationRunner.runSmokeTest(workspace);

        if (!workspace.isConsistentWith(checkpoint)) {
            recoveryService.reconcile(checkpoint, workspace, smoke);
        }

        ContextWindow context = contextManager.buildForResume(checkpoint, workspace, smoke);
        return AgentSession.resumed(taskId, checkpoint, context);
    }
}

9.5 TaskScheduler

Long-running Agent 通常需要后台调度:

public interface LongRunningTaskScheduler {
    void submit(LongRunningTask task);
    void pause(String taskId);
    void resume(String taskId);
    void cancel(String taskId);
}

10. 企业案例:实现一个新功能

任务:

为订单服务增加 PENDING_REVIEW 状态。

阶段拆分:

阶段 输出 验证
Discovery 找到状态相关代码和测试 列出相关文件
Planning 修改计划 用户或规则确认
Implementation 修改枚举和状态机 编译通过
Testing 新增/修改测试 OrderServiceTest 通过
Regression 运行相关测试套件 mvn test 部分通过
Summary 输出 diff 和风险 包含证据

Checkpoint 示例:

phase: Testing
completed: OrderStatus 已新增 PENDING_REVIEW;OrderStateMachine 已更新
pending: 补充 OrderServiceTest 异常路径
verification: 编译通过;测试尚未运行
nextAction: 编写测试并运行 ./mvnw -Dtest=OrderServiceTest test

这个 Checkpoint 足以让下一个 Agent 恢复。

11. 常见误区

11.1 依赖超长上下文解决长任务

长上下文有帮助,但不能替代状态管理。

11.2 Checkpoint 只是对话摘要

Checkpoint 应是结构化恢复协议。

11.3 没有阶段边界

没有阶段边界,Agent 容易一次做太多。

11.4 不做恢复前健康检查

恢复时必须检查工作区是否与 Checkpoint 一致。

11.5 没有人工接管机制

长任务必须允许暂停、恢复、取消和人工升级。

12. 贯穿案例:CI 失败分析 Agent

第一版 CI 失败分析通常是短任务,但在复杂项目中也可能变成 Long-running Agent 任务。

例如一次 CI 失败可能涉及多个模块、多个失败测试、多个最近提交和多个服务依赖。此时任务需要阶段化:

Discovery:收集失败摘要和影响模块
Classification:判断失败类型
Investigation:逐个分析失败测试和相关代码
Verification:验证根因假设是否有证据
Reporting:输出报告和风险

每个阶段都应保存 Checkpoint。

例如:

phase: Investigation
completed: 已确认失败测试为 OrderServiceTest.shouldApprovePendingReviewOrder
pending: 读取 OrderStateMachine.allowedTransitions
hypothesis: PENDING_REVIEW 状态未配置合法流转
nextAction: read_file_range(OrderStateMachine.java)

如果任务中断,ResumeManager 不需要重放所有日志和对话,只需要读取最新 Checkpoint、当前 Git Diff、关键工具结果摘要和下一步动作。

13. 本章小结

本章讨论 Long-running Agent。

核心结论:

  1. 长任务不能只靠更长上下文,需要状态机和 Checkpoint。
  2. 任务必须拆成可验证阶段。
  3. 状态必须外部化,不能只存在模型上下文中。
  4. Resume 应重建最小有效上下文,而不是重放全部历史。
  5. 长任务需要调度、预算、暂停、恢复和人工接管。

一句话总结:

Long-running Agent 的本质,是把模型的连续行动组织成一个可恢复、可验证、可治理的工程流程。

14. 实践任务

任务 1:设计任务状态机

为“实现新功能”设计状态机,包含正常路径和异常路径。

任务 2:实现 Checkpoint 数据结构

用 Java 定义 Checkpoint,并写入数据库或 JSON 文件。

任务 3:设计 Resume 流程

说明恢复时需要加载哪些信息,哪些历史不需要加载。

任务 4:阶段化拆分

把一个真实开发任务拆成 5 个阶段,每个阶段写出:

  • 输入;
  • 输出;
  • 验证方式;
  • 失败处理;
  • Checkpoint 内容。

results matching ""

    No results matching ""