LangChain LangGraph
Module 1 Module 2 Module 3
Module 3 · Middleware and HITL
1 3.2 Managing Msgs
2 3.3 HITL
3 3.4 Dyn Models
4 3.4 Dyn Prompts
5 3.4 Dyn Tools
6 3.5 Email Agent
SUM Module Summary
HomeLangChainModule 3 · Middleware and HITL3.2 Managing Msgs
📓 Notebook 📖 Explained
LANGCHAIN MODULE 3 · LESSON 3.2

Managing Message History
Summarization · Trim · RemoveMessage

This section solves the problem of context expansion in long conversations: Use SummarizationMiddleware to compress old messages, Use before_agent middleware to delete messages that should not continue to enter the model.

1 Why manage messages

The most core field in Agent's state is usually messages. The longer the conversation and the more messages there are, the more cost, latency, and context pollution go up. The first step in Module 3 is to learn to control message history.

questionPerformancePlan for this lesson
Context too longThe token exceeds the limit or the Use adjustment becomes slow.SummarizationMiddleware SummaryOld News
No Use tool messageAfter seeing the noise output, the model responded that it was off track.RemoveMessage deletes the specified message
Multiple rounds of memory confusionOld information and new questions interfere with each otherKeep only necessary messages and summaries
Core principle

Not all historical information is worth retaining. What needs to be retained is the "context still needed for the current task", not the complete transcript.

2 Use SummarizationMiddleware to compress old messages

SummarizationMiddlewareAfter the message reaches the trigger condition, the Use model Put old messages are compressed into digests while retaining the most recent original messages.

Python
from langchain.agents.middleware import SummarizationMiddleware

summarize_middleware = SummarizationMiddleware(
    model=deepseek_model(),
    trigger=("tokens", 100),
    keep=("messages", 1),
)

agent = create_agent(
    model=deepseek_model(),
    checkpointer=InMemorySaver(),
    middleware=[summarize_middleware],
)
Parameter meanings

trigger=("tokens", 100)Indicates that Summary is triggered when the number of tokens exceeds the threshold;keep=("messages", 1)Indicates that the original text of the most recent message is retained.

3 Long conversation example: lunar city Lunapolis

Notebook constructs a fictional conversation: lunar capital, weather, miners, union strike. Finally, ask, “How would you respond if you were the new president?” This question requires old context, but not necessarily a complete verbatim history.

Python
messages = [
    HumanMessage(content="What is the capital of the moon?"),
    AIMessage(content="The capital of the moon is Lunapolis."),
    HumanMessage(content="What is the weather in Lunapolis?"),
    AIMessage(content="Skies are clear, with a high of 120C and a low of -100C."),
    HumanMessage(content="How many cheese miners live in Lunapolis?"),
    AIMessage(content="There are 100,000 cheese miners living in Lunapolis."),
    HumanMessage(content="Do you think the cheese miners' union will strike?"),
    AIMessage(content="Yes, because they are unhappy with the new president."),
    HumanMessage(content="If you were Lunapolis' new president how would you respond to the cheese miners' union?"),
]

response = agent.invoke(
    {"messages": messages},
    {"configurable": {"thread_id": "1"}},
)
Why this example suits summarization

The final question relies on the preceding facts, but not on each original expression. A summary can preserve key facts while reducing context length.

4 Use before_agent to delete tool messages

The second example shows how to process state before calling Use on the model.@before_agentmiddleware reads the current messages and finds allToolMessage, then returnRemoveMessageinstructions to delete them.

Python
from langchain.messages import RemoveMessage
from langchain.agents.middleware import before_agent

@before_agent
def trim_messages(state: AgentState, runtime: Runtime) -> dict[str, Any] | None:
    """Remove all the tool messages from the state"""
    messages = state["messages"]
    tool_messages = [m for m in messages if isinstance(m, ToolMessage)]

    return {"messages": [RemoveMessage(id=m.id) for m in tool_messages]}
RemoveMessage semantics

RemoveMessage(id=...)Instead of a normal text message, this tells LangGraph to remove the message with the specified id from state.

5 Why delete ToolMessage

In the Notebook device troubleshooting example, tool messages include noisy diagnostic text such as "blorp-x7" and "greeble". If the model saw all the raw tool output when the user last asked for temperature, it might be interfered with by unreliable or irrelevant information.

Python
messages = [
    HumanMessage(content="My device won't turn on. What should I do?"),
    ToolMessage(content="blorp-x7 initiating diagnostic ping…", tool_call_id="1"),
    AIMessage(content="Is the device plugged in and turned on?"),
    HumanMessage(content="Yes, it's plugged in and turned on."),
    ToolMessage(content="temp=42C voltage=2.9v … greeble complete.", tool_call_id="2"),
    AIMessage(content="Is the device showing any lights or indicators?"),
    HumanMessage(content="What's the temperature of the device?"),
]

agent = create_agent(
    model=deepseek_model(),
    checkpointer=InMemorySaver(),
    middleware=[trim_messages],
)
When to use it

You can delete low-value tool logs, sensitive intermediate data, and API raw responses with messy formats, and only put necessary conclusions and keep them for the model.

6 Lesson takeaway