🎯 课程主题
TodoListMiddleware(待办列表中间件)——赋予 Agent 任务规划与进度追踪能力,通过内置的 write_todo 工具自动拆解复杂任务并逐项执行。
📝 核心知识点
1. 核心概念:为什么需要 TodoListMiddleware
- 概念说明:面对多步骤、有依赖关系的复杂任务时,普通 Agent 可能在执行后期遗忘初始目标(产生幻觉),或因工具报错产生"应激反应"跳过关键验证。TodoListMiddleware 通过维护一个 Todo 列表来时刻提醒 Agent 下一步该做什么。
- 关键细节:
- 普通 Agent ≈ 实习生(无规划),TodoList Agent ≈ 资深工程师(有规划、懂分步执行)。
- 适用场景:任务链路长、步骤有多变依赖关系、前端需实时展示执行进度和思考过程。
2. 何时该用 / 何时不该用
- 概念说明:并不是所有任务都需要引入 TodoListMiddleware,需根据任务复杂度判断。
- 关键细节:
- 不需要用:简单问答、翻译、单步函数调用;或步骤固定可预见的线性流程(后者可用 LangGraph 线性节点实现)。
- 需要用:多文件工程、需要动态应对失败重试、步骤多变且存在严格先后依赖关系。
3. 内置工具 write_todo 的工作机制
- 概念说明:TodoListMiddleware 为 Agent 注入了内置的
write_todo工具,Agent 通过调用它来创建/更新 Todo 列表。 - 关键细节:
- 每个 Todo 项包含
content(任务描述)和status(状态)。 - 状态取值:
in_progress(执行中)、pending(待执行)、completed(已完成)。 - Agent 会自动先调用
write_todo规划步骤,再按计划执行用户工具,出错可重新规划。
- 每个 Todo 项包含
4. 参数说明
- 概念说明:
system_prompt:自定义指导 Todo 列表使用的提示词,一般使用默认即可。todo_description:自定义write_tools工具的描述信息,一般也使用默认值。
- 关键细节:这两个参数通常不需要手动指定,内置默认值已足够。
🏗️ 架构与工作流
用户消息 → Agent 调用 write_todo 生成计划 → 按计划调用用户工具(list/read/write/test)
→ 执行结果反馈 → 更新 Todo 状态 → 继续下一项 → 全部完成 → 模型总结
write_todo 是 Middleware 注入的内置工具,用户代码中无需定义。Agent 会在执行前自动规划,执行中动态更新状态,失败时自动重新规划(在结果中可观察到多轮 write_todo 调用)。
💻 代码实战
from langchain.agents import create_agent
from langchain.agents.middleware import TodoListMiddleware
from langchain_core.messages import HumanMessage
import os
# 模型初始化(略)
# === 工具定义 ===
def list_files(path: str = ".") -> str:
"""列出指定目录下的所有文件"""
files = os.listdir(path)
return "\n".join(files)
def read_file(path: str) -> str:
"""读取文件内容"""
with open(path, "r", encoding="utf-8") as f:
return f.read()
def write_file(path: str, content: str) -> str:
"""写入内容到文件"""
with open(path, "w", encoding="utf-8") as f:
f.write(content)
return f"写入成功: {path}"
def run_tests() -> str:
"""在工作区下运行 pytest"""
import subprocess
result = subprocess.run(["pytest", "-q"], capture_output=True, text=True)
return result.stdout + result.stderr
tools = [list_files, read_file, write_file, run_tests]
# === 创建 Agent ===
agent = create_agent(
model,
tools=tools,
middleware=[TodoListMiddleware()],
system_prompt=(
"你是一个代码修复助手。遇到多步骤任务时,先使用 write_todo 制定待办事项,"
"然后读取文件、修复代码并运行测试。全部工作在工作区下进行。"
),
)
response = agent.invoke({
"messages": [
HumanMessage(content="请测试并修复工作区下的 my_add.py 文件中的代码。")
]
})
# === 结果分析 ===
# 1. AI Message 中首先出现 write_todo 的 tool_call,生成包含多个 Todo 项的计划
# 2. 按计划依次执行 list_files → read_file → write_file → run_tests
# 3. 若测试失败,Agent 会重新调用 write_todo 更新计划并再次尝试修复
# 4. 最终每个 Todo 项的 status 变为 completed
⚠️ 常见问题与避坑指南
- 事先准备好工作区(如
todo_workspace/)和待测试文件(如my_add.py、test_my_add.py),确保工具能找到目标文件。 system_prompt中务必提示 Agent 优先使用write_todo,否则它可能直接调工具而跳过规划。write_todo是内置工具,用户代码中不要重复定义同名工具。- 复杂任务如果在
system_prompt中未明确说明任务步骤,Agent 可能规划不完整,建议在 prompt 中给出方向性指引。
💡 个人总结与延伸
TodoListMiddleware 本质上是在 Agent 的推理循环中引入了「规划-执行-复盘」的元认知能力,类似于 OpenAI 的 Deep Research 或其他研究型 Agent 的内部机制。对于需要「边想边做」的复杂工程任务(如代码修复、多文件重构),它是比传统 RAG + 单轮工具调用更有效的解决方案。