What is @before_model?
@before_model is a middleware decorator that registers a function to run before each language model call inside a LangChain agent. The hook receives the full agent state dict, can mutate it freely, and must return the (modified) state. This makes it the central extension point for controlling what the model sees — trimming conversation history to control token cost, injecting retrieved context from a vector store, adding system instructions dynamically, or blocking requests that violate access control rules.
The most common production use is message history trimming. Long agent conversations accumulate messages and eventually exceed the model's context window or inflate token costs. A @before_model hook that keeps only the last N messages solves this at the middleware layer without changing the agent's core logic. A subtler version uses a summarization approach: when the history exceeds a threshold, summarize the oldest messages into a single summary message and keep only that plus the recent messages.
RAG injection is another powerful use. You can extract the user's latest message from state["messages"][-1].content, run a retrieval query against a vector store, and prepend the retrieved context as a SystemMessage or HumanMessage before the model call. This pattern decouples retrieval from the main agent graph — the agent's nodes never need to know about the retrieval step. Like @after_model, each hook must return the state dict; multiple hooks compose in registration order.
Use Cases
- • Trim history
- • Inject RAG
- • Validate input
- • Optimize tokens
- • Cost control
- • Access control
Key Features
- ✓ Pre-model hook
- ✓ State access
- ✓ Preprocessing
- ✓ Token counting
- ✓ RAG support
- ✓ Composable
When NOT to Use
For post-processing—use @after_model.
Notes
Never replace the entire messages list with an empty list
state["messages"] = [] discards all history including the system prompt and tool results from prior turns. The model then has no context. Use negative indexing to keep a window: state["messages"] = state["messages"][-N:] preserves the most recent N messages while trimming the oldest.
RAG injection should preserve the system message at index 0
If your agent has a system message as the first message, injecting context at index 0 shifts the system message to index 1, which some models treat differently. Insert context at index 1 (after the system message): state["messages"].insert(1, SystemMessage(content=context)).
Token counting is character-approximate unless you use tiktoken
Rough budget checks using len(message.content) undercount non-ASCII text and overcount English by about 4×. For accurate token budgeting, use tiktoken: enc = tiktoken.encoding_for_model("gpt-4o-mini"); tokens = sum(len(enc.encode(m.content)) for m in msgs).
Hooks are synchronous — offload heavy retrieval to a background thread if needed
The middleware system is synchronous. A slow retrieval call in @before_model blocks the entire agent turn. If your retrieval takes more than ~100ms, consider caching the retrieval result or running it outside the agent loop and injecting the pre-fetched context into initial state.
Import
from langchain.agents import before_model
How to Apply
@before_model
def trim(state):
state['messages'] = state['messages'][-10:]
return state
What It Enables
- ✓ Message trimming
- ✓ Context injection
- ✓ Validation
- ✓ Token optimization
Code Examples
Trim history to last 10 messages
from langchain.agents import before_model
@before_model
def trim(state):
state['messages'] = state['messages'][-10:]
return state
Inject RAG context before model call
from langchain.agents import before_model
from langchain_core.messages import SystemMessage
@before_model
def inject_rag(state):
query = state['messages'][-1].content
docs = retriever.invoke(query)
context = "\n".join(d.page_content for d in docs)
state['messages'].insert(0, SystemMessage(content=f'Context:\n{context}'))
return state
Token-budget guard using tiktoken
from langchain.agents import before_model
import tiktoken
enc = tiktoken.encoding_for_model("gpt-4o-mini")
def token_count(msgs):
return sum(len(enc.encode(m.content)) for m in msgs)
@before_model
def budget_guard(state):
while token_count(state['messages']) > 3000:
state['messages'].pop(1) # Remove oldest non-system
return state
Integration Patterns
agent = create_agent(model, middleware=[hook])
Runs before invoke()
Common Mistakes
❌ @before_model def hook(s): s['msgs'] = [] # Lost context
✅ @before_model def hook(s): s['msgs'] = s['msgs'][-10:]
Related LangChain References
Browse the full LangChain API reference index to explore more classes, methods, and decorators, or start with the LangChain introduction tutorial for end-to-end context on building with @before_model and the wider framework.
@before_model FAQ
What does @before_model do in LangChain?
Middleware hook running before model processes messages. @before_model is a middleware decorator that registers a function to run before each language model call inside a LangChain agent. The hook receives the full agent state dict, can mutate it freely, and must return the (modified) state. This makes it the central extension point for controlling what the model sees — trimming conversation history to control token cost, injecting retrieved context from a vector store, adding system instructions dynamically, or blocking requests t…
Which package provides @before_model?
DevShelfHub documents @before_model from the langchain.agents package. Pin your installed LangChain version and match imports to the snippet on this page.
When should I use @before_model?
Use @before_model when your LangChain agents, workflows, or pipelines need the behavior described in this guide.
When should I avoid using @before_model?
For post-processing—use @after_model.
How do I apply @before_model in Python?
Apply @before_model as a decorator above your function definition. Import it from from langchain.agents import before_model and annotate the function you want to wrap. See the code examples on this page for a complete working snippet.
Where can I explore more LangChain API reference pages?
Open the LangChain API reference index on DevShelfHub to browse classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.