More built-in middleware to reach for
Built-in middleware are ready-made wrappers you add to an agent for common needs, such as planning a task list, clearing old tool output, or pre-selecting tools, without writing the hook yourself.
Last updated: 27 Sep, 2026 · LangChain 1.4
Middleware you do not have to write
Middleware exposes hooks, trigger points around the agent: before the agent, before the model, around tool calls, after the model and after the agent. Whatever you attach there, such as logging or summarization, runs at that point. LangChain also ships middleware for the jobs most agents need, and you add it to the middleware list like your own, with no hook code to write. The V1 crash course first describes summarization, which condenses the messages once their count reaches a limit such as 10, then human-in-the-loop and a model call limit, and then walks through the list in the documentation:
- SummarizationMiddleware summarizes the conversation history as it approaches the token limit.
- HumanInTheLoopMiddleware pauses the run so a person can approve a tool call.
- ModelCallLimitMiddleware limits the number of model calls to prevent excessive cost.
- ToolCallLimitMiddleware controls tool execution by limiting call counts.
- ModelFallbackMiddleware switches to another model when one fails.
- TodoListMiddleware gives the agent a to-do list to plan longer tasks.
- LLMToolSelectorMiddleware picks the relevant tools when an agent has many.
- ToolRetryMiddleware tries a failing tool again.
- PIIMiddleware, also in the documentation though the clip does not name it, redacts, masks or blocks personal data.
You have already used summarization, retries, fallbacks and call limits, and human approval and PII come next. This lesson covers three more, and each one goes in the same place: the agent's middleware list.
The video lists these middleware without running them. The code below runs one of them, the to-do list, on the shop agent, so you can see what it does in practice.
Three you have not met
| Middleware | What it does | Reach for it when |
|---|---|---|
TodoListMiddleware | Gives the agent a write_todos tool to plan multi-step work | A long task it should break into steps |
ContextEditingMiddleware | Clears old tool outputs as the context nears its limit | An agent that calls many tools in a run |
LLMToolSelectorMiddleware | Asks a model to pre-pick the relevant tools each turn | An agent with a long list of tools |
Adding one to an agent
This lesson's agent answers order questions with lookup_order, the tool built in Tools: a function the model can call. Start the file with it.
from langchain.tools import tool
ORDERS = {"A17": "shipped on 3 March", "C40": "waiting for stock"}
@tool
def lookup_order(order_id: str) -> str:
"""Look up an order's shipping status by its id, such as A17."""
status = ORDERS.get(order_id)
return f"{order_id} {status}." if status else f"{order_id} is not an order we have."Pass an instance in the middleware list, the same slot the earlier ones used. Here the agent gets a planning tool.
from langchain.agents import create_agent
from langchain.agents.middleware import TodoListMiddleware
from langchain.chat_models import init_chat_model
model = init_chat_model("groq:openai/gpt-oss-120b", temperature=0) # uses your GROQ_API_KEY
agent = create_agent(model, tools=[lookup_order],
middleware=[TodoListMiddleware()]) # the agent can now plan with a todo listThe agent planning a two-step task
Give it a job with two steps and print every tool call it makes, to see whether it plans first:
result = agent.invoke({"messages": [{"role": "user", "content":
"Check A17 and C40, then tell me which one is still waiting."}]})
for message in result["messages"]:
for call in getattr(message, "tool_calls", None) or []:
print(call["name"], call["args"]) # the plan, then the lookups
print(result["messages"][-1].text)lookup_order {'order_id': 'A17'}
lookup_order {'order_id': 'C40'}
C40 is still waiting (it’s awaiting stock).The model did not use the to-do list here. Two lookups were simple enough to do directly, so it called both and answered. TodoListMiddleware gives the agent a write_todos tool; the model decides when a task is long enough to need a plan, which is usually a job with many steps, not two.
When to add one
- The agent loses track of a multi-step job: add the todo list.
- A run fills the context with tool output: add context editing.
- The model picks the wrong tool from a long list: add the tool selector.
Related
- Previous: Summarization with SummarizationMiddleware
- Next: Asking a human first
- Reference: LangChain built-in middleware
- Ask a three-step question and count the
write_todoscalls. - Add
ContextEditingMiddleware()next to the todo list and check the agent still answers. - Read the docs' built-in middleware page and pick one more to try.
Little by little, you're building something great.