TodoWrite — 没有计划的 Agent,做着做着就偏了

"没有计划的 agent 走哪算哪" — 先列步骤再动手,长任务更不容易漏项。

Github 原文:shareAI-lab/learn-claude-code

问题

给 Agent 一个复杂任务:“把所有 Python 文件改成 snake_case 命名,然后跑测试,修好失败。”

Agent 开始干活,改了 3 个文件,跑了个测试,发现 2 个失败,开始修。修着修着,它忘了最初是”改成 snake_case”,测试失败把注意力全吸走了。

对话越长越严重:工具结果不断填满上下文,系统提示的影响力被稀释。一个 10 步重构,做完 1-3 步就开始即兴发挥,因为 4-10 步已经被挤出注意力了。

解决方案

TodoWrite — 没有计划的 Agent,做着做着就偏了

保留上一章的最小 hook 结构,重点看新增的 todo_write 工具和 reminder 机制。todo_write 本身不做任何实际工作,不能读文件、不能跑命令,只是让 Agent 在动手之前先理清思路,此外,额外在循环里加了一个计数器:连续 3 轮没调 todo_write 就注入一条提醒,用AI 检查一下是否需要更新一下 Todo 或者重新看一遍 Todo。

工作原理

先说 tode_write ,这个东西通俗来说就是我们每次操作 Agent 的那个任务清单,例如你在使用 codex的时候,在做复杂任务的时候在右侧的列表会有个清单,一步一步的完成的那个东西。

其实光从这个东西的作用我们就可以推理出来,它其实就是一个带有状态的列表,保存在当前进程的内存中,用于显示进度。

TOOLS = [
    {"name": "bash",       ...},
    {"name": "read_file",  ...},
    {"name": "write_file", ...},
    {"name": "edit_file",  ...},
    {"name": "glob",       ...},
    # s05: 新增一条
    {"name": "todo_write", "description": "Create and manage a task list ...",
     "input_schema": {
         "type": "object",
         "properties": {
             "todos": {
                 "type": "array",
                 "items": {
                     "type": "object",
                     "properties": {
                         "content": {"type": "string"},
                         "status": {"type": "string", "enum": ["pending", "in_progress", "completed"]},
                     },
                 },
             },
         },
     },
    },
]

TOOL_HANDLERS["todo_write"] = run_todo_write

然后再说提醒 AI 的那个 nag reminder ,在教学中是很简单的,它的逻辑就是只要 Agent 的 loop 三轮没有调用 todo_write 就会触发,自动注入一条提醒让 Agent 去再去获取一下 todo 清单,如果要更新就去更新,就算不更新,也会重新加入到上下文防止 Agent 忘记。要注意的是,CC 并不是这么做的,他其实做得很复杂,这个后面我们会简单讲到,在后续的 Task system 的部分,再详细介绍。

总结,Agent 收到任务后的典型流程:

  1. 先调 todo_write 列出所有步骤(全 pending

  2. 做一个步骤,改成 in_progress

  3. 做完改成 completed

  4. 看下一个 pending

  5. 继续重复上面的步骤,如果连续 3 轮没有调用 todo_write 时,循环会在下一次 LLM 调用前追加一条 reminder。

TodoWrite — 没有计划的 Agent,做着做着就偏了

CC是如何做的

CC 中有两套任务系统并存(tasks.ts:133-139):

  • TodoWrite:一个简单的列表工具,数据在内存 AppState 中维护。教学版也保存在进程内存里,退出后清空

  • Task System:文件持久化、依赖图、并发锁、ownership

这里先不做过多拓展,在后续的 Task system 章节专门来介绍这部分,这是个挺复杂的模块。