Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.langchain.com/llms.txt

Use this file to discover all available pages before exploring further.

Middleware provides a way to more tightly control what happens inside the agent. Middleware is useful for the following: Add middleware by passing them to createAgent:
import {
  createAgent,
  summarizationMiddleware,
  humanInTheLoopMiddleware,
} from "langchain";

const agent = createAgent({
  model: "gpt-5.4",
  tools: [...],
  middleware: [summarizationMiddleware, humanInTheLoopMiddleware],
});

The agent loop

The core agent loop involves calling a model, letting it choose tools to execute, and then finishing when it calls no more tools: Core agent loop diagram Middleware exposes hooks before and after each of those steps: Middleware flow diagram

Use middleware inside a LangGraph workflow

Middleware is not a separate runtime: hooks run inside the compiled LangGraph that create_agent returns. You can drop the whole agent (middleware and all) into a larger StateGraph as a node or subgraph, and every middleware hook continues to run. Reach for this pattern when the surrounding topology is more than a standard “loop until done”: classifying input before routing to one of several agents, fanning out work in parallel, or stitching agent calls together with deterministic steps. HumanInTheLoopMiddleware matches against each tool’s .name. In Python, @tool-decorated functions take their name from the function (so the key below is "send_email"); in TypeScript, the key matches the name you pass to tool({...}, { name }).
import { AgentState, createAgent, humanInTheLoopMiddleware } from "langchain";
import { StateGraph, START } from "@langchain/langgraph";

// Assumes readEmail, sendEmail, classifyNode, and route are defined elsewhere.
// readEmail / sendEmail are registered with name: "read_email" / "send_email".
const emailAgent = createAgent({
  model: "claude-sonnet-4-6",
  tools: [readEmail, sendEmail],
  middleware: [humanInTheLoopMiddleware({ interruptOn: { send_email: true } })],
});

const graph = new StateGraph(AgentState)
  .addNode("classify", classifyNode)
  .addNode("emailAgent", emailAgent)
  .addEdge(START, "classify")
  .addConditionalEdges("classify", route)
  .compile();
The HITL interrupt, summarization, PII redaction, retries, and any custom hooks all travel with the agent node. See Use subgraphs for the full set of composition patterns, including subgraph checkpointer scoping (per-invocation versus per-thread).

Additional resources

Built-in middleware

Explore built-in middleware for common use cases.

Custom middleware

Build your own middleware with hooks and decorators.

Middleware API reference

Complete API reference for middleware.

Middleware integrations

Provider-specific middleware for Anthropic, AWS, OpenAI, and more.

Testing agents

Test your agents with LangSmith.