计划与任务系统:Agent 的行动蓝图
Agent Loop、工具系统、技能系统分别提供循环机制、执行能力和领域知识。计划与任务系统提供长步骤任务的拆解、排序、追踪和验证能力。

普通聊天的上下文是线性的,但现实任务可能是并行的、有依赖的、会回滚的。计划系统在这两者之间架桥。
为什么 Agent 需要计划
复杂任务包含多个有依赖关系的步骤。以升级 React 版本为例:
任务:将项目从 React 17 升级到 18
步骤 1:升级 package.json 中的 React 版本 ← 可做
步骤 2:修复被废弃的 API 调用 ← 依赖 1
步骤 3:更新依赖库到兼容版本 ← 依赖 1
步骤 4:替换 Concurrent Mode 相关代码 ← 依赖 2、3
步骤 5:全量回归测试 ← 依赖 4没有计划系统时,Agent 靠上下文记忆推进。上下文会被压缩、截断、干扰。 计划系统则把进度变成显式清单,解决四个问题:
| 没有计划 | 有计划 |
|---|---|
| 大目标模糊,易遗漏 | 拆解,每步都是可执行小任务 |
| 依赖隐式,易搞错顺序 | 排序,依赖显式,顺序清晰 |
| 需翻对话历史 | 追踪,任务看板实时反映进度 |
| 做完了但可能方向错了 | 验证,每步后对照原始目标检查 |
计划的制定:Plan Mode
面对复杂任务,Agent 先进入计划模式(Plan Mode),核心约束是只读不写:搜索代码、阅读文件、理解架构,但不执行修改。
用户提出复杂任务
│
▼
┌───────────────────┐
│ Plan Mode(只读) │
│ │
│ 搜索代码 │
│ 理解架构 │
│ 设计方案 │
│ 列出实现步骤 │
│ 标注依赖关系 │
└─────────┬─────────┘
│
▼
人类审查计划
┌───┴───┐
│ │
通过 修改
│ │
▼ │
┌──────────────────┐
│ 执行阶段 │
│ (读、写) │
└──────────────────┘Plan Mode 分离理解和行动,在零成本阶段确认方向,避免动手后才发现方向错误的代价。
计划的产出是一份任务列表——每个任务标注做什么、为什么做、有什么前置条件。
任务的载体:任务管理工具
计划不能悬浮在空中。任务管理工具在会话中提供四件事:
- 创建任务(将计划步骤变为显式条目)
- 追踪状态(记录每步当前进展)
- 管理依赖(声明谁先谁后)
- 提供进度可见性(实时反映整体完成情况)。
计划中的每个步骤创建为一张任务卡片:
- 做什么(subject):简短标题
- 为什么做(description):背景、要求
- 前置条件(blockedBy):必须先完成的任务
版本演进:v1 → v2
Claude Code 的会话内任务管理经历了两个版本:
| 特性 | v1: TodoWrite | v2: Task 工具集 |
|---|---|---|
| 写入工具 | TodoWrite | TaskCreate/TaskUpdate |
| 查询工具 | 无,只能等待系统推送 reminder 或靠自身记忆 | TaskList/TaskGet,可随时主动查询 |
| 存储 | 纯内存,session 结束后丢失 | 磁盘文件(~/.claude/tasks/),持久化 |
| 任务 ID | 无,靠数组索引 | 自增数字 ID |
| 任务依赖 | 不支持 | 支持 blocks / blockedBy |
| 多 Agent 协作 | 不支持 | 支持团队共享 task list |
| 并发安全 | 无锁 | 文件锁保护 |
| Hook 系统 | 无 | 支持 taskCreated / taskCompleted 钩子 |
| 恢复方式 | 从 transcript 解析最后一条调用 | 直接读取磁盘文件 |
切换逻辑:交互式会话(终端/IDE)默认启用 v2,非交互式会话(如 SDK 调用)默认走 v1。v2 启用时,TodoWrite 工具自动被禁用。两者不会同时存在。
本文后续内容默认以 v2(Task 工具集)为准。
任务看板
┌────┬───────────────────────┬─────────────┬──────────┐
│ ID │ 任务 │ 状态 │ 依赖 │
├────┼───────────────────────┼─────────────┼──────────┤
│ 1 │ 升级 React 版本 │ completed │ 无 │
│ 2 │ 修复被废弃的 API 调用 │ in_progress │ 依赖 1 │
│ 3 │ 更新依赖库到兼容版本 │ pending │ 依赖 1 │
│ 4 │ 替换相关代码 │ pending │ 依赖 2,3 │
│ 5 │ 全量回归测试 │ pending │ 依赖 4 │
└────┴───────────────────────┴─────────────┴──────────┘状态之间的流转关系:
pending ──→ in_progress ──→ completed
(未开始) (执行中) (完成并通过验证)
↑ │
│ 验证失败 │
└──────────────────────────────┘依赖管理
任务通过 blocks 和 blockedBy 显式声明依赖关系。依赖是执行时的硬性约束,未完成时不会执行后续任务。
进度看板
对人类是透明度,对 Agent 是防遗漏的安全网——上下文压缩时,任务列表保留进度信息。
从计划到执行:工作循环
┌──────────────────────────────────────────┐
│ 1 查看看板 还有哪些 pending 任务? │
│ │ 哪些依赖已解决? │
│ ▼ │
│ 2 领取任务 选择可做任务, │
│ │ 标记 in_progress │
│ ▼ │
│ 3 执行 调用工具完成 │
│ │ │
│ ▼ │
│ 4 标记完成 确认成果,标记 completed │
│ │ │
│ ▼ │
│ 5 回到 1 直到所有任务完成 │
└──────────────────────────────────────────┘关键设计
先创建任务再执行。 创建任务本身是一次显式思考,降低遗漏概率。
单 Agent 场景也需要。 任务列表提供进度锚点(上下文压缩后仍可恢复)和人类透明度。
任务完成 ≠ 目标达成。 所有任务完成后需回到原始目标验证。
验证
三层验证:
- 自动化验证:运行测试、类型检查、lint
- 功能性验证:启动应用,实际操作
- 目标对照:回到用户原始请求逐条核对
验证不通过时重新打开相关任务,标记 in_progress,修复后再验证:
执行 → 验证 → 发现问题 → 修复 → 再验证 → 通过