DeerFlow 2.0 — TodoMiddleware & LangChain TodoListMiddleware

DeerFlow 2.0 — TodoMiddleware & LangChain TodoListMiddleware

Two GitHub sources read together:

File Commit
langchain-ai/langchain · libs/langchain_v1/langchain/agents/middleware/todo.py 311675a
bytedance/deer-flow · backend/packages/harness/deerflow/agents/middlewares/todo_middleware.py 259a684

LangChain TodoListMiddleware (base class)

Data models

write_todos tool

System prompt injection

wrap_model_call / awrap_model_call append guidance to every model request:

after_model enforcement

Detects when the model issues multiple parallel write_todos tool calls (ambiguous because the tool replaces the whole list). Returns error ToolMessages for each violating call.


DeerFlow TodoMiddleware (extends TodoListMiddleware)

Adds two new failure-mode mitigations on top of the base class.

Helper functions

Function Purpose
_todos_in_messages(messages) True if any AIMessage has a write_todos tool call
_reminder_in_messages(messages) True if a HumanMessage(name="todo_reminder") exists
_completion_reminder_count(messages) Count of HumanMessage(name="todo_completion_reminder")
_format_todos(todos) Format todos as - [status] content lines

before_model — context-loss recovery

When context is truncated (e.g. by summarization), the original write_todos call disappears from the window. The hook fires when:

  1. todos is non-empty in state, AND
  2. No write_todos call is visible in messages, AND
  3. No todo_reminder already injected

Injects a HumanMessage(name="todo_reminder") with the current todo list inside <system_reminder> tags.

after_model — premature-exit prevention

Fires when the model produces a final AIMessage (no tool calls) but incomplete todos remain. Decorated with @hook_config(can_jump_to=["model"]).

Design notes