DS DevShelfHub Projects · AI tools
Tutorials / LangChain / Reference / Decorators / @after_model
Decorator langchain.agents

@after_model: Reference Guide

By DevShelfHub

Middleware hook running after model generates response.

What is @after_model?

@after_model is a middleware decorator in LangChain's agent middleware system. It registers a function that runs after every call to the language model within an agent created with create_agent(). The decorated function receives the full agent state dict — including the messages list, any tool results, and custom state fields you've defined — and must return the (potentially modified) state. Unlike a callback handler, @after_model can mutate the state and the changes are visible to the next step in the agent loop.

The primary use cases fall into three categories: observability (logging token usage, latency, and response content for monitoring), safety (checking the model's output against a content policy and either filtering or flagging it), and transformation (reformatting the model's response before it reaches the tool dispatcher or the user). Because the hook fires after the model but before tool execution, it is the right place to intercept tool_calls in the AIMessage and validate or modify the arguments before the tools run.

Multiple middleware functions can be chained — they execute in the order provided to create_agent(middleware=[hook1, hook2]). Each hook receives the state returned by the previous hook, so a logging hook and a safety-filtering hook can be composed without coupling them. The hook must return the state (even if unmodified); returning None causes the agent to raise a TypeError on the next state access.

Use Cases

  • Log responses
  • Validate output
  • Safety checks
  • Transform output
  • Track metadata
  • Audit trails

Key Features

  • Post-model hook
  • Full state
  • Filtering support
  • Logging
  • Transformation
  • Error recovery

When NOT to Use

For preprocessing—use @before_model.

Notes

Must return state — returning None breaks the agent loop

Every @after_model hook must return the state dict, even if you made no changes. Returning None causes a TypeError on the very next state access. Always end with return state.

The hook fires before tool execution — inspect tool_calls here

At the point @after_model runs, the AIMessage is in state["messages"][-1]. If the model decided to call a tool, state["messages"][-1].tool_calls contains the list of tool invocations. You can validate or modify the tool arguments before they are dispatched, which is useful for blocking unsafe tool calls.

Multiple hooks compose in registration order

create_agent(model, middleware=[hook1, hook2]) runs hook1 first, then passes its returned state to hook2. Each hook sees the state as modified by all preceding hooks. Order hooks from most critical (safety) to most optional (logging) to ensure safety checks run even if a logging hook raises.

@after_model hooks are synchronous — no async support yet

The middleware system does not support async hook functions. If you need to make an async call inside the hook (e.g., write to an async database), run it synchronously or use asyncio.run() carefully. For heavy I/O, push the work to a background task via a thread pool.

Import

python
from langchain.agents import after_model

How to Apply

python
@after_model
def log(state):
    print(f'Response: {state["messages"][-1].content}')
    return state

What It Enables

  • Logging
  • Filtering
  • Safety checks
  • Metadata enrichment

Code Examples

Log model responses

python
from langchain.agents import after_model
@after_model
def log(state):
    print(state['messages'][-1])
    return state

Content safety filter

python
from langchain.agents import after_model
BLOCKED_PHRASES = ["confidential", "password"]
@after_model
def safety_filter(state):
    last = state['messages'][-1]
    if any(p in last.content.lower() for p in BLOCKED_PHRASES):
        last.content = '[Response blocked by safety filter]'
    return state

Track model call latency in state

python
from langchain.agents import after_model
import time
_start_time = {}
@after_model
def track_latency(state):
    elapsed = time.time() - _start_time.get('t', time.time())
    state.setdefault('metadata', {})['model_latency_ms'] = round(elapsed * 1000)
    return state

Integration Patterns

agent = create_agent(model, middleware=[hook])
Runs after invoke()

Common Mistakes

❌ @after_model def hook(s): s['msgs'][0] = x # Wrong index

✅ @after_model def hook(s): s['msgs'][-1].content = x

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 @after_model and the wider framework.

@after_model FAQ

What does @after_model do in LangChain?

Middleware hook running after model generates response. @after_model is a middleware decorator in LangChain's agent middleware system. It registers a function that runs after every call to the language model within an agent created with create_agent(). The decorated function receives the full agent state dict — including the messages list, any tool results, and custom state fields you've defined — and must return the (potentially modified) state. Unlike a callback handler, @after_model can mutate the state and the changes are visi…

Which package provides @after_model?

DevShelfHub documents @after_model from the langchain.agents package. Pin your installed LangChain version and match imports to the snippet on this page.

When should I use @after_model?

Use @after_model when your LangChain agents, workflows, or pipelines need the behavior described in this guide.

When should I avoid using @after_model?

For preprocessing—use @before_model.

How do I apply @after_model in Python?

Apply @after_model as a decorator above your function definition. Import it from from langchain.agents import after_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.