代码讲解.md 2.6 KB

S05 TodoWrite 代码讲解

这一节只讲相对 S04 新增的内容:

让 Agent 在多步骤任务中先规划,再执行,并持续更新任务状态。


1. 本节新增内容

  • CURRENT_TODOS:内存中的当前任务列表。
  • _normalize_todos():校验和解析模型传来的 todos。
  • run_todo_write():更新任务列表并打印状态。
  • todo_write 工具定义:让模型可以显式写计划。
  • rounds_since_todo:检测模型太久没更新计划时提醒它。

2. Todo 数据结构

CURRENT_TODOS 是:

CURRENT_TODOS: list[dict]

每个 todo 是一个字典:

{
    "content": "读取项目结构",
    "status": "in_progress"
}

status 只能是三种:

pending
in_progress
completed

3. todo_write 工具 schema

模型调用工具时,传入的数据大概是:

{
    "todos": [
        {"content": "查看文件", "status": "completed"},
        {"content": "修改代码", "status": "in_progress"},
        {"content": "运行验证", "status": "pending"}
    ]
}

模型不是直接改 CURRENT_TODOS,而是提出一次 tool_use

程序收到后调用:

run_todo_write(todos)

4. _normalize_todos(todos)

这个函数负责把输入整理成标准列表。

为什么需要它?

模型有时可能传真正的 list:

[{"content": "...", "status": "pending"}]

也可能传 JSON 字符串:

'[{"content": "...", "status": "pending"}]'

所以 _normalize_todos() 会尝试解析,并检查:

  • todos 必须是列表。
  • 每一项必须是字典。
  • 每一项必须有 contentstatus
  • status 必须是允许的状态。

5. run_todo_write(todos)

这个函数做两件事:

1. 校验 todos
2. 更新 CURRENT_TODOS

更新后会打印当前任务状态,让人能看到 Agent 的计划变化。


6. rounds_since_todo

rounds_since_todo 是一个计数器。

每一轮模型调用工具后,如果没有调用 todo_write,计数器就增加。

当它超过阈值:

if rounds_since_todo >= 3:
    messages.append({"role": "user", "content": "<reminder>请更新你的待办事项。</reminder>"})

这相当于给模型一个提醒:

你已经执行几步了,该更新计划了

7. 本节课堂重点

TodoWrite 不是为了好看,而是让 Agent 有“任务状态”。

没有 TodoWrite 时,模型只是在连续调用工具。

有了 TodoWrite 后,模型开始显式维护:

计划是什么
现在做到哪一步
哪些已经完成
哪些还没开始