TodoListMiddleware赋予Agent显式的规划和任务跟踪能力。它强制Agent将复杂的多步骤目标分解为一组结构化的可执行项从而将被动型Agent转变为主动型Agent。它通过拦截Agent的推理循环来注入规划逻辑和工具规划工具它为Agent提供了write_todos工具来创建、更新和替换其整个任务列表状态管理它维护一个PlanningState状态来跟踪当前任务列表系统提示注入它注入系统提示词用来指导LLM何时进行规划以及如何有效地使用任务列表以避免在长时间运行的任务中出现目标漂移Agent通常以简单的思考-行动-观察循环运行DeepAgents则利用TodoListMiddleware来处理长期任务合理使用它可以带来以下好处降低识别负荷可以动态卸载不必要的任务防止它们占据上下文窗口。也就是说上下文窗口可以指存储必要的任务列表以提高推理性能可视性和调试它实时存储了任务列表及其状态如果Agent遇到问题这些信息会准确地显示它正在尝试执行的步骤结构化委托当与SubAgentMiddleware一起使用时待办事项列表充当交接点Main-Agent可以在此定义专门的Sub-Agent的任务。1. 提供工具将TodoList写入当前状态我们先来看看TodoListMiddleware维护的状态类型PlanningState。PlanningState是一个AgentState的子类它利用todos字段存储表示任务列表的一组Todo对象。表示单个待办事项的Todo是一个TypedDict两个字段content和status分别表示任务内容描述和当前状态。从todos字段的定义可以看出由于没有指定reduer函数所以对应的通道类型为LastValue这意味着它采用的是全量更新而非增量添加。classPlanningState(AgentState[ResponseT]):todos:Annotated[NotRequired[list[Todo]],OmitFromInput]classTodo(TypedDict):content:strstatus:Literal[pending,in_progress,completed]TodoListMiddleware利用注入的提示词指导LLM采用结构化的方式来创建和管理待办事项列表并提供了一个配套write_todos工具来提供辅助。当我们调用__init__方法创建TodoListMiddleware实例时可以指定该工具的描述和系统提示词。如果你不能保证提供的工具描述和系统提示词比默认提供的更好那么建议直接使用默认值即可。任务写入工具对应的函数内嵌在__init__方法中的write_todos它接受一个待办事项列表和自动注入的工具调用ID针对任务的全量更新利用返回的Command完成。classTodoListMiddleware(AgentMiddleware[PlanningState[ResponseT],ContextT,ResponseT]):state_schemaPlanningStatedef__init__(self,*,system_prompt:strWRITE_TODOS_SYSTEM_PROMPT,tool_description:strWRITE_TODOS_TOOL_DESCRIPTION,)-None:super().__init__()self.system_promptsystem_prompt self.tool_descriptiontool_descriptiontool(descriptionself.tool_description)defwrite_todos(todos:list[Todo],tool_call_id:Annotated[str,InjectedToolCallId])-Command[Any]:returnCommand(update{todos:todos,messages:[ToolMessage(fUpdated todo list to{todos},tool_call_idtool_call_id)],})self.tools[write_todos]如下所示的是TodoListMiddleware为提供的工具write_todos的定义的描述可以作为工具描述的范本。Use this tool to create and manage a structured task list for your current work session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user. Only use this tool if you think it will be helpful in staying organized. If the users request is trivial and takes less than 3 steps, it is better to NOT use this tool and just do the task directly. ## When to Use This Tool Use this tool in these scenarios: 1. Complex multi-step tasks - When a task requires 3 or more distinct steps or actions 2. Non-trivial and complex tasks - Tasks that require careful planning or multiple operations 3. User explicitly requests todo list - When the user directly asks you to use the todo list 4. User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated) 5. The plan may need future revisions or updates based on results from the first few steps ## How to Use This Tool 1. When you start working on a task - Mark it as in_progress BEFORE beginning work. 2. After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation. 3. You can also update future tasks, such as deleting them if they are no longer necessary, or adding new tasks that are necessary. Dont change previously completed tasks. 4. You can make several updates to the todo list at once. For example, when you complete a task, you can mark the next task you need to start as in_progress. ## When NOT to Use This Tool It is important to skip using this tool when: 1. There is only a single, straightforward task 2. The task is trivial and tracking it provides no benefit 3. The task can be completed in less than 3 trivial steps 4. The task is purely conversational or informational ## Task States and Management 1. **Task States**: Use these states to track progress: - pending: Task not yet started - in_progress: Currently working on (you can have multiple tasks in_progress at a time if they are not related to each other and can be run in parallel) - completed: Task finished successfully 2. **Task Management**: - Update task status in real-time as you work - Mark tasks complete IMMEDIATELY after finishing (dont batch completions) - Complete current tasks before starting new ones - Remove tasks that are no longer relevant from the list entirely - IMPORTANT: When you write this todo list, you should mark your first task (or tasks) as in_progress immediately!. - IMPORTANT: Unless all tasks are completed, you should always have at least one task in_progress to show the user that you are working on something. 3. **Task Completion Requirements**: - ONLY mark a task as completed when you have FULLY accomplished it - If you encounter errors, blockers, or cannot finish, keep the task as in_progress - When blocked, create a new task describing what needs to be resolved - Never mark a task as completed if: - There are unresolved issues or errors - Work is partial or incomplete - You encountered blockers that prevent completion - You couldnt find necessary resources or dependencies - Quality standards havent been met 4. **Task Breakdown**: - Create specific, actionable items - Break complex tasks into smaller, manageable steps - Use clear, descriptive task names Being proactive with task management demonstrates attentiveness and ensures you complete all requirements successfully Remember: If you only need to make a few tool calls to complete a task, and it is clear what you need to do, it is better to just do the task directly and NOT call this tool at all.2. 通过系统提示词指导LLM进行规划系统提示词的设置通过重写的wrap_model_call/awrap_model_call方法来实现的。由于任务列表采用全量更新的方式所以在同一个推理步骤中针对write_todos工具的多次调用会导致之前的任务列表被覆盖这是我们不希望看到的也是不应该出现的现象。TodoListMiddleware重写了wrap_tool_call/awrap_tool_call方法来检测是否出现了并行修改任务列表的情况并生成一个警告性的ToolMessage。classTodoListMiddleware(AgentMiddleware[PlanningState[ResponseT],ContextT,ResponseT]):defwrap_model_call(self,request:ModelRequest[ContextT],handler:Callable[[ModelRequest[ContextT]],ModelResponse[ResponseT]],)-ModelResponse[ResponseT]|AIMessageasyncdefawrap_model_call(self,request:ModelRequest[ContextT],handler:Callable[[ModelRequest[ContextT]],Awaitable[ModelResponse[ResponseT]]],)-ModelResponse[ResponseT]|AIMessageoverridedefafter_model(self,state:PlanningState[ResponseT],runtime:Runtime[ContextT])-dict[str,Any]|Noneoverrideasyncdefaafter_model(self,state:PlanningState[ResponseT],runtime:Runtime[ContextT])-dict[str,Any]|None如下所示的是TodoListMiddleware提供的默认系统提示词的内容。我个人觉得去学习如何写好提示词的最好途径就是去阅读框架内部的提示词是如何撰写的比如DeepAgents的很多中间件提供的提示词都非常具有指导性和启发性。## write_todos You have access to the write_todos tool to help you manage and plan complex objectives. Use this tool for complex objectives to ensure that you are tracking each necessary step and giving the user visibility into your progress. This tool is very helpful for planning complex objectives, and for breaking down these larger complex objectives into smaller steps. It is critical that you mark todos as completed as soon as you are done with a step. Do not batch up multiple steps before marking them as completed. For simple objectives that only require a few steps, it is better to just complete the objective directly and NOT use this tool. Writing todos takes time and tokens, use it when it is helpful for managing complex many-step problems! But not for simple few-step requests. ## Important To-Do List Usage Notes to Remember - The write_todos tool should never be called multiple times in parallel. - Dont be afraid to revise the To-Do list as you go. New information may reveal new tasks that need to be done, or old tasks that are irrelevant.3. 利用TodoListMiddleware指定一个旅游规划在下面的演示程序中我们创建了一个Agent并在其中注册了TodoListMiddleware。我们通过调用Agent帮助规划一个为期三天的赴日旅行安排。演示程序展示了如何使用TodoListMiddleware来实现一个结构化的任务管理流程以及如何通过系统提示词来指导Agent进行有效的规划。由于我们在提供的提示词中建议Agent尽可能多地使用write_todos工具来管理任务列表因此在Agent的推理过程中我们可以看到它多次调用write_todos工具来更新任务列表并且每次更新都会生成一个新的工具调用结果显示当前的待办事项列表。fromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportTodoListMiddlewarefromlangchain_openaiimportChatOpenAIfromdotenvimportload_dotenvimportasyncio load_dotenv()agentcreate_agent(modelChatOpenAI(modelgpt-5.2-chat),middleware[TodoListMiddleware()],)prompt\ Conduct a simple plan to travle in Japan for 3 days, including the cities to visit, the attractions to see, the food to try, and the transportation to use. Provide a day-by-day itinerary with specific recommendations and tips for each day. Try to use write_todos tool as possible as you can. asyncdefmain():resultawaitagent.ainvoke(input{messages:[{role:user,content:prompt}]})formessageinresult[messages]:message.pretty_print()asyncio.run(main())输出 Human Message Conduct a simple plan to travle in Japan for 3 days, including the cities to visit, the attractions to see, the food to try, and the transportation to use. Provide a day-by-day itinerary with specific recommendations and tips for each day. Try to use write_todos tool as possible as you can. Ai Message Tool Calls: write_todos (call_qedNqFlya1ESQdj9sqmtvwwi) Call ID: call_qedNqFlya1ESQdj9sqmtvwwi Args: todos: [{content: Design overall 3-day Japan itinerary structure and choose cities, status: in_progress}, {content: Create detailed Day 1 itinerary (Tokyo) with attractions, food, transport, tips, status: pending}, {content: Create detailed Day 2 itinerary (Kyoto) with attractions, food, transport, tips, status: pending}, {content: Create detailed Day 3 itinerary (Osaka) with attractions, food, transport, tips, status: pending}, {content: Review itinerary for clarity and add general travel tips, status: pending}] Tool Message Name: write_todos Updated todo list to [{content: Design overall 3-day Japan itinerary structure and choose cities, status: in_progress}, {content: Create detailed Day 1 itinerary (Tokyo) with attractions, food, transport, tips, status: pending}, {content: Create detailed Day 2 itinerary (Kyoto) with attractions, food, transport, tips, status: pending}, {content: Create detailed Day 3 itinerary (Osaka) with attractions, food, transport, tips, status: pending}, {content: Review itinerary for clarity and add general travel tips, status: pending}] Ai Message Tool Calls: write_todos (call_BW4mtEOTYpQOQkbTCNkyNuJK) Call ID: call_BW4mtEOTYpQOQkbTCNkyNuJK Args: todos: [{content: Design overall 3-day Japan itinerary structure and choose cities, status: completed}, {content: Create detailed Day 1 itinerary (Tokyo) with attractions, food, transport, tips, status: in_progress}, {content: Create detailed Day 2 itinerary (Kyoto) with attractions, food, transport, tips, status: pending}, {content: Create detailed Day 3 itinerary (Osaka) with attractions, food, transport, tips, status: pending}, {content: Review itinerary for clarity and add general travel tips, status: pending}] Tool Message Name: write_todos Updated todo list to [{content: Design overall 3-day Japan itinerary structure and choose cities, status: completed}, {content: Create detailed Day 1 itinerary (Tokyo) with attractions, food, transport, tips, status: in_progress}, {content: Create detailed Day 2 itinerary (Kyoto) with attractions, food, transport, tips, status: pending}, {content: Create detailed Day 3 itinerary (Osaka) with attractions, food, transport, tips, status: pending}, {content: Review itinerary for clarity and add general travel tips, status: pending}] Ai Message Tool Calls: write_todos (call_wk8Dp7mtu5j1DnxHnZAFpQ9b) Call ID: call_wk8Dp7mtu5j1DnxHnZAFpQ9b Args: todos: [{content: Create detailed Day 1 itinerary (Tokyo) with attractions, food, transport, tips, status: completed}, {content: Create detailed Day 2 itinerary (Kyoto) with attractions, food, transport, tips, status: in_progress}, {content: Create detailed Day 3 itinerary (Osaka) with attractions, food, transport, tips, status: pending}, {content: Review itinerary for clarity and add general travel tips, status: pending}] Tool Message Name: write_todos Updated todo list to [{content: Create detailed Day 1 itinerary (Tokyo) with attractions, food, transport, tips, status: completed}, {content: Create detailed Day 2 itinerary (Kyoto) with attractions, food, transport, tips, status: in_progress}, {content: Create detailed Day 3 itinerary (Osaka) with attractions, food, transport, tips, status: pending}, {content: Review itinerary for clarity and add general travel tips, status: pending}] Ai Message Tool Calls: write_todos (call_764zNPUyX5zQ0m8TfXu1OKwt) Call ID: call_764zNPUyX5zQ0m8TfXu1OKwt Args: todos: [{content: Create detailed Day 2 itinerary (Kyoto) with attractions, food, transport, tips, status: completed}, {content: Create detailed Day 3 itinerary (Osaka) with attractions, food, transport, tips, status: in_progress}, {content: Review itinerary for clarity and add general travel tips, status: pending}] Tool Message Name: write_todos Updated todo list to [{content: Create detailed Day 2 itinerary (Kyoto) with attractions, food, transport, tips, status: completed}, {content: Create detailed Day 3 itinerary (Osaka) with attractions, food, transport, tips, status: in_progress}, {content: Review itinerary for clarity and add general travel tips, status: pending}] Ai Message Tool Calls: write_todos (call_nEtItfmDhsDxJE0b26L93AdH) Call ID: call_nEtItfmDhsDxJE0b26L93AdH Args: todos: [{content: Create detailed Day 3 itinerary (Osaka) with attractions, food, transport, tips, status: completed}, {content: Review itinerary for clarity and add general travel tips, status: in_progress}] Tool Message Name: write_todos Updated todo list to [{content: Create detailed Day 3 itinerary (Osaka) with attractions, food, transport, tips, status: completed}, {content: Review itinerary for clarity and add general travel tips, status: in_progress}] Ai Message Tool Calls: write_todos (call_uBOYfWFACuFyvQPhlJudPwtq) Call ID: call_uBOYfWFACuFyvQPhlJudPwtq Args: todos: [{content: Review itinerary for clarity and add general travel tips, status: completed}] Tool Message Name: write_todos Updated todo list to [{content: Review itinerary for clarity and add general travel tips, status: completed}] Ai Message Below is a **simple, first‑time‑friendly 3‑day Japan travel plan** covering **Tokyo, Kyoto, and Osaka**. It balances famous sights, local food, and efficient transportation, with practical tips each day. --- ## 3‑Day Japan Travel Itinerary (Tokyo → Kyoto → Osaka) ### Overview - **Best for**: First-time visitors - **Pace**: Moderate (highlights only) - **Main transport**: Trains (Shinkansen local lines) - **Cities**: Tokyo → Kyoto → Osaka --- ## Day 1: Tokyo – Modern City Tradition ### Morning **Visit: Asakusa Senso‑ji Temple** - Tokyo’s oldest Buddhist temple - Walk through **Nakamise Street** for souvenirs and snacks **Try food:** - Ningyo-yaki (sweet cakes) - Melon pan - Matcha ice cream **Transport:** - Tokyo Metro (Ginza Line / Asakusa Line) --- ### Afternoon **Visit: Shibuya** - Famous **Shibuya Crossing** - Hachiko Statue (photo spot) **Lunch suggestion:** - Ramen (Ichiran / Ippudo) - Gyudon (Sukiya, Yoshinoya) --- ### Evening **Visit: Shinjuku** - Tokyo Metropolitan Government Building (free city view) - Kabukicho lights at night **Dinner:** - Izakaya (Japanese pub) - Yakitori (grilled chicken skewers) **Tips for Day 1** - Buy a **Suica or Pasmo IC card** for easy transport - Avoid rush hours (7–9 AM, 5–7 PM) - Wear comfortable walking shoes --- ## Day 2: Kyoto – Culture History ### Morning **Travel: Tokyo → Kyoto** - **Shinkansen (bullet train)** - ⏱ ~2.5 hours - Nozomi or Hikari trains --- ### Late Morning **Visit: Fushimi Inari Shrine** - Famous red torii gates - Walk as far as comfortable (no need to finish full hike) --- ### Afternoon **Visit: Kiyomizu‑dera Temple** - Wooden temple with city views - Walk through **Higashiyama** historic streets **Lunch:** - Udon or soba noodles - Yudofu (tofu specialty) --- ### Evening **Visit: Gion District** - Traditional streets - Chance to spot geiko/maiko **Dinner:** - Kaiseki (if budget allows) - Simple Kyoto-style set meal **Tips for Day 2** - Kyoto buses get crowded—trains are often faster - Dress modestly at temples - Carry cash for small shops --- ## Day 3: Osaka – Food Fun ### Morning **Travel: Kyoto → Osaka** - JR Train (15–30 minutes) --- ### Morning Visit **Osaka Castle** - Symbol of Osaka - Nice park for walking and photos --- ### Afternoon **Visit: Dotonbori** - Neon signs street food heaven - Glico running man sign **Must‑try food:** - Takoyaki (octopus balls) - Okonomiyaki (savory pancake) - Kushikatsu (deep-fried skewers) --- ### Evening **Option 1:** Umeda Sky Building (city view) **Option 2:** Shinsaibashi shopping street **Tips for Day 3** - Osaka is casual—relaxed manners - Street food is best eaten standing near stalls - Trains run late but check last train times --- ## ✅ General Travel Tips - **Wi‑Fi/SIM**: Rent pocket Wi‑Fi or buy eSIM - **Luggage**: Use coin lockers or luggage delivery - **Language**: Basic English is common in cities - **Payments**: IC cards some cash recommended --- If you want, I can: - Adjust this for **budget / luxury** - Make it **family‑friendly** - Focus on **anime, food, or nature** - Add **hotel recommendations** Just tell me!