In Part 11 of our series, today we are focusing on Custom Middleware Hooks. This is the “internal plumbing” that allows you to control how your agent behaves at every stage of its lifecycle.
Press enter or click to view image in full size
In earlier parts of this series, we used pre-built middleware for things like summarization and human approval. But what if you need something truly custom?
Maybe you want to log every incident with a unique UUID, inject hidden instructions when a critical failure is detected, or append safety warnings to specific AI responses. To do this, you need to go “under the hood” and use Custom Middleware Hooks.
LangChain 1.2 provides four primary “Node-style” hooks that allow you to intercept the agent at specific execution points.
The Four Stages of an AI Request
Think of an agent’s execution as a timeline. Custom hooks let you “plug in” logic at any of these four points:
before_agent: Runs once at the very start of the conversation. Perfect for generating IDs or starting timers.before_model: Runs every time the agent is about to call its LLM "Brain." Use this to inject extra rules or priority context.after_model: Runs immediately after the LLM responds, but before the user sees it. Ideal for safety filtering or formatting.after_agent: Runs once at the end of the entire loop. Perfect for cleanup or logging final resolutions.
1. Initializing the Incident (before_agent)
Let’s build an Incident Commander agent. Every time a user starts a chat, we want to generate a unique incident ticket ID. We use before_agent to "hack" this ID into the conversation state.
@before_agent
def init_incident(state: dict, runtime: Any) -> dict:
incident_id = str(uuid.uuid4())[:6]
print(f"🚨 INCIDENT #{incident_id} STARTED.") # Inject a hidden SystemMessage with our ID
return {"messages": [SystemMessage(content=f"INCIDENT_ID: {incident_id}")]}
2. Dynamic Escalation (before_model)
If a user says “the server is CRASHED,” we don’t want the AI to give a generic, polite response. We want to force it into “Emergency Mode.” By using before_model, we can scan the user's input and inject a high-priority instruction right before the model processes it.
@before_model
def check_severity(state: dict, runtime: Any):
last_msg = state["messages"][-1].content.lower() if "down" in last_msg or "crash" in last_msg:
# Force the model to be brief and stay focused on the outage
return {"messages": [SystemMessage(content="URGENT: This is a P1 OUTAGE. Be brief.")]}
return None
3. The Response Guardrail (after_model)
Finally, we want to ensure that if the AI suggests a dangerous command (like “restarting a database”), we add a safety label. This is done after the model has finished thinking, using after_model.
@after_model
def safety_check(state: dict, runtime: Any):
ai_reply = state["messages"][-1].content if "restart" in ai_reply.lower():
new_content = ai_reply + "\n\n(⚠️ SAFETY WARNING: Obtain approval before executing.)"
return {"messages": [AIMessage(content=new_content)]}
return None
4. Tying It All Together
When you assemble these hooks into your agent, you get a system that follows a strict operational lifecycle:
agent = create_agent(
model=model,
middleware=[init_incident, check_severity, safety_check, close_ticket] # The lifecycle
)The result in action:
- User: “The database is DOWN!”
- 1. before_agent: Ticket
#a1b2c3is created. - 2. before_model: AI is told this is a “P1 Outage.”
- 3. after_model: AI suggests a restart, and the middleware automatically appends the Safety Warning.
- 4. after_agent: The incident is logged as “Closed” in your backend.
Conclusion: Total Control
Custom hooks turn your AI from an unpredictable black box into a structured application. You can enforce security, track metrics, and modify behavior dynamically without ever hardcoding that logic into your tools or your prompts.
By mastering the agent lifecycle, you aren’t just building a bot — you’re building a reliable, auditable, and safe AI workflow.
💬 What do you think?
Drop your thoughts, questions, or suggestions in the comments below!
Check out my YouTube channel for more exciting content! [YouTube Channel Link — Harsha Selvi]
Disclaimer: This text has been rephrased using AI tools, and some parts are derived from various sources to provide a comprehensive overview.
#AI #LangChain #SoftwareDevelopment #Python #AIEngineering #DevOps #Observability #CleanCode #Automation













