Claude Code 03:TodoWrite 规划与长任务防迷航

Claude Code 03:TodoWrite 规划与长任务防迷航
Asaakii在掌握了 Agent 核心循环与文件操作工具后,Agent 已经能够完成“读取文件 A 并修复某行报错”这类简单的单步任务。
但一旦进入真实软件工程场景——例如“为系统增加 JWT 鉴权功能”,任务通常涉及读取配置、编写鉴权中间件、修改登录路由、补充单测并更新文档。在多达十几轮的工具调用后,没有规划层的 Agent 会频繁出现令人沮丧的**“迷航现象”**:
- 重复劳动:反复读取同一个文件,甚至覆盖刚刚写好的逻辑;
- 遗漏子任务:改完中间件后就宣告任务完成,完全忘记了单测与文档;
- 目标漂移(Context Drift):被中间出现的某个调试小报错带偏,顺藤摸瓜去改无关库,彻底偏离了最初的核心需求。
人类工程师在面对复杂工程时,第一反应是列出 Checklist。大模型同样需要一张动态更新的任务清单。
本文将实现一个极简的 Todo 规划层,揭示为什么必须强制“同时只能有一个进行中任务”,并拆解 Claude Code 内部从 V1 内存 Todo 到 V2 磁盘 Task 系统的技术演进。
规划层核心设计:TodoManager
我们通过一个专用的 TodoManager 来维护当前会话的任务看板:
1 | from dataclasses import dataclass |
为什么强制“同时仅有一个进行中任务”?
模型在长上下文中缺乏人类的专注力分配机制。如果允许模型将 3 个任务同时标记为 in_progress,它在生成代码时就会在多个目标之间反复横跳,无法形成连贯的原子操作。
强制互斥机制(in_progress 唯一性)像一副思维轨道,迫使模型每次只能聚焦解决当前的单一最小闭环。
集成进 Agent 工具栈
将 Todo 操作作为独立工具暴露给模型:
1 | todo_mgr = TodoManager() |
在系统指令中明确约束:“面对涉及 2 步以上的任务,第一步必须调用 todo_write 拆解任务,并在完成每个步骤后立即更新状态”。
生产源码探秘:V1 内存 Todo 的局限与废弃
在早期版本的 Claude Code 源码中,TodoWriteTool 就是按照上述全量快照思路实现的:
1 | // src/tools/TodoWriteTool.ts(V1 历史源码逻辑) |
V1 方案的致命缺陷
随着 Claude Code 面向大规模复杂项目演进,V1 的全量快照模式暴露出了严重的物理瓶颈:
- 全量覆盖易丢数据:模型在更新第 5 个任务时,偶尔会漏传第 2 个任务,导致任务被意外删除;
- 无法跨会话持久化:所有的 Todo 都存留在 Node.js 进程内存(
appState)中,用户按Ctrl+C退出后,整个进度灰飞烟灭; - 不支持任务依赖:无法表达“必须等任务 A 的单测跑通后,才能开始任务 B”这种 DAG 依赖关系;
- 无法支持多智能体并发:当多个 Agent 协同工作时,内存快照的相互覆写会导致严重的竞态冲突。
因此,Claude Code 在新架构中已经将 TodoWriteTool 标记为 Deprecated(已弃用),全面转向了基于文件持久化的 Task 工具族(V2)。
架构演进:V1 Todo vs V2 磁盘 Task
flowchart TD
subgraph V1: 内存 Todo 快照
M1[appState.todos 内存对象]
M2[全量覆盖更新: 每次传入完整数组]
M3[无持久化: 进程退出即丢失]
end
subgraph V2: 磁盘持久化 Task DAG
D1["~/.claude/tasks/{taskId}.json 独立持久化"]
D2[原子 CRUD: TaskCreate / TaskUpdate / TaskGet]
D3["支持 blockedBy 前置依赖,构建执行 DAG"]
D4[多 Agent 共享与崩溃恢复]
end
V1 -.->|架构演进升级| V2
在 V2 架构下,每个任务对应磁盘上的一个持久化 JSON 文件,具备唯一的 UUID、状态时间戳以及 blockedBy: string[] 字段。任务变成了真正的独立实体,不再受限于单次模型上下文的存活周期。
总结
Todo 规划机制给 Agent 带来的改变是质的飞跃:
- 提供持续外部反馈:通过任务看板,模型始终清楚“我已经做了什么,我现在正在做什么,下一步要做什么”;
- 单进行中约束:严格限制同一时刻只能推进一个原子操作,消除多线程脑裂;
- 走向持久化:认识到全量内存快照的局限,为后续构建基于磁盘的持久化任务图埋下伏笔。
然而,规划层只解决了“不迷路”的问题。当某个子任务需要读取大量代码或执行数十次报错探索时,主 Agent 的上下文仍然会被这些无用的中间过程撑爆。
下一篇我们将探讨上下文防污染的核心利器:Subagent 子智能体与独立上下文隔离。











