Provider-agnostic middleware
The following middleware work with any LLM provider:Summarization
Automatically summarize conversation history when approaching token limits, preserving recent messages while compressing older context. Summarization is useful for the following:- Long-running conversations that exceed context windows.
- Multi-turn dialogues with extensive history.
- Applications where preserving full conversation context matters.
keep still include their original multimodal blocks, while older multimodal messages that are summarized are represented only by the generated text summary. For image-heavy applications, store media in a filesystem or object store and pass URLs or file references through message history.SummarizationMiddleware
Configuration options
Configuration options
'openai:gpt-5.4-mini') or a BaseChatModel instance. See init_chat_model for more information.- A single
ContextSizetuple (the specified threshold must be met) - A single
TriggerClausedict (all specified thresholds must be met - AND logic) - A list mixing either form (any item must be met - OR logic)
fraction(float): Fraction of model’s context size (0-1)tokens(int): Absolute token countmessages(int): Message count
ContextSize tuple expresses exactly one threshold. A TriggerClause dict can include one or more thresholds, e.g. {"tokens": 4000, "messages": 10}, and all thresholds in the dict must be met (AND).Each TriggerClause dict must specify at least one threshold. If trigger is not provided, summarization will not trigger automatically.See the API reference for ContextSize and TriggerClause for more information.fraction(float): Fraction of model’s context size to keep (0-1)tokens(int): Absolute token count to keepmessages(int): Number of recent messages to keep
ContextSize for more information.{messages} placeholder where conversation history will be inserted.summary_prompt to provide the full prompt instead.trigger: ("tokens", value) instead. Token threshold for triggering summarization.keep: ("messages", value) instead. Recent messages to preserve.Full example
Full example
- A single threshold triggers when that threshold is met
- A trigger clause with multiple thresholds triggers only when all thresholds are met (AND logic)
- A list of trigger conditions triggers when any item is met (OR logic)
- Each threshold can use
fraction(of model’s context size),tokens(absolute count), ormessages(message count)
fraction- Fraction of model’s context size to keeptokens- Absolute token count to keepmessages- Number of recent messages to keep
Human-in-the-loop
Pause agent execution for human approval, editing, or rejection of tool calls before they execute. Human-in-the-loop is useful for the following:- High-stakes operations requiring human approval (e.g. database writes, financial transactions).
- Compliance workflows where human oversight is mandatory.
- Long-running conversations where human feedback guides the agent.
HumanInTheLoopMiddleware
Model call limit
Limit the number of model calls to prevent infinite loops or excessive costs. Model call limit is useful for the following:- Preventing runaway agents from making too many API calls.
- Enforcing cost controls on production deployments.
- Testing agent behavior within specific call budgets.
ModelCallLimitMiddleware
Configuration options
Configuration options
'end' (graceful termination) or 'error' (raise exception)Tool call limit
Control agent execution by limiting the number of tool calls, either globally across all tools or for specific tools. Tool call limits are useful for the following:- Preventing excessive calls to expensive external APIs.
- Limiting web searches or database queries.
- Enforcing rate limits on specific tool usage.
- Protecting against runaway agent loops.
ToolCallLimitMiddleware
Configuration options
Configuration options
None means no thread limit.None means no run limit.Note: At least one of thread_limit or run_limit must be specified.'continue'(default) - Block exceeded tool calls with error messages, let other tools and the model continue. The model decides when to end based on the error messages.'error'- Raise aToolCallLimitExceededErrorexception, stopping execution immediately'end'- Stop execution immediately with aToolMessageand AI message for the exceeded tool call. Only works when limiting a single tool; raisesNotImplementedErrorif other tools have pending calls.
Full example
Full example
- Thread limit - Max calls across all runs in a conversation (requires checkpointer)
- Run limit - Max calls per single invocation (resets each turn)
'continue'(default) - Block exceeded calls with error messages, agent continues'error'- Raise exception immediately'end'- Stop with ToolMessage + AI message (single-tool scenarios only)
Model fallback
Automatically fallback to alternative models when the primary model fails. Model fallback is useful for the following:- Building resilient agents that handle model outages.
- Cost optimization by falling back to cheaper models.
- Provider redundancy across OpenAI, Anthropic, etc.
ModelFallbackMiddleware
Configuration options
Configuration options
PII detection
Detect and handle Personally Identifiable Information (PII) in conversations using configurable strategies. PII detection is useful for the following:- Healthcare and financial applications with compliance requirements.
- Customer service agents that need to sanitize logs.
- Any application handling sensitive user data.
apply_to_output=True, PIIMiddleware also redacts streamed wire output—text deltas, tool-call args, tool outputs, and state snapshots—via a registered stream transformer. Requires langchain>=1.3.2. See Register transformers on middleware.PIIMiddleware
Custom PII types
You can create custom PII types by providing adetector parameter. This allows you to detect patterns specific to your use case beyond the built-in types.
Three ways to create custom detectors:
- Regex pattern string - Simple pattern matching
- Custom function - Complex detection logic with validation
text, start, and end keys:
Configuration options
Configuration options
email, credit_card, ip, mac_address, url) or a custom type name.'block'- Raise exception when detected'redact'- Replace with[REDACTED_{PII_TYPE}]'mask'- Partially mask (e.g.,****-****-****-1234)'hash'- Replace with deterministic hash
langchain>=1.3.2, also redacts streamed wire output (text deltas, tool-call args, tool outputs, state snapshots) via a registered stream transformer. See event streaming.To-do list
Equip agents with task planning and tracking capabilities for complex multi-step tasks. To-do lists are useful for the following:- Complex multi-step tasks requiring coordination across multiple tools.
- Long-running operations where progress visibility is important.
write_todos tool and system prompts to guide effective task planning.TodoListMiddleware
Configuration options
Configuration options
LLM tool selector
Use an LLM to intelligently select relevant tools before calling the main model. LLM tool selectors are useful for the following:- Agents with many tools (10+) where most aren’t relevant per query.
- Reducing token usage by filtering irrelevant tools.
- Improving model focus and accuracy.
LLMToolSelectorMiddleware
Configuration options
Configuration options
'openai:gpt-5.4-mini') or a BaseChatModel instance. See init_chat_model for more information.Defaults to the agent’s main model.Tool error
Catch exceptions raised during tool execution and convert them into errorToolMessages that the model can see and recover from, instead of halting the agent run. Tool error is useful for the following:
- Letting the model retry a failed tool call with corrected arguments.
- Surfacing controlled, sanitized error messages instead of raw exception details.
- Preventing unexpected tool exceptions from crashing the agent.
middleware list) and configured with on_failure="error" so that exceptions reach the tool error middleware. See the full example below.ToolErrorMiddleware
ToolErrorMiddleware requires langchain>=1.3.14.Configuration options
Configuration options
str or list of content blocks) to convert the exception into a ToolMessage(status="error"). Return None or omit a return statement to let the exception propagate. Used on the sync path and, unless aon_error is given, on the async path.on_error when not provided.None, applies to all tools.Tool error full example
Tool error full example
on_error handler receives the exception and the ToolCallRequest (which includes the tool call dict with name, args, and call ID). Return None for exceptions you do not want to handle, and they will propagate normally.on_error handler controls disclosure: the raw exception message is never sent to the model unless you choose to include it.Tool retry
Automatically retry failed tool calls with configurable exponential backoff. Tool retry is useful for the following:- Handling transient failures in external API calls.
- Improving reliability of network-dependent tools.
- Building resilient agents that gracefully handle temporary errors.
ToolRetryMiddleware
Configuration options
Configuration options
None, applies to all tools.True if it should be retried. By default, all exceptions are retried. Exceptions that do not match propagate immediately and are not handled by on_failure.'continue'(default) - Return aToolMessagewith error details, allowing the LLM to handle the failure'error'- Re-raise the exception, stopping agent execution- Custom callable - Function that takes the exception and returns a string for the
ToolMessagecontent
'return_message' (use 'continue' instead) and 'raise' (use 'error' instead).initial_delay * (backoff_factor ** retry_number) seconds. Set to 0.0 for constant delay.±25%) to delay to avoid thundering herdFull example
Full example
max_retries- Number of retry attempts (default: 2)backoff_factor- Multiplier for exponential backoff (default: 2.0)initial_delay- Starting delay in seconds (default: 1.0)max_delay- Cap on delay growth (default: 60.0)jitter- Add random variation (default: True)
on_failure='continue'(default) - Return error messageon_failure='error'- Re-raise exception- Custom function - Function returning error message
Model retry
Automatically retry failed model calls with configurable exponential backoff. Model retry is useful for the following:- Handling transient failures in model API calls.
- Improving reliability of network-dependent model requests.
- Building resilient agents that gracefully handle temporary model errors.
ModelRetryMiddleware
Configuration options
Configuration options
True if it should be retried.'continue'(default) - Return anAIMessagewith error details, allowing the agent to potentially handle the failure gracefully'error'- Re-raise the exception (stops agent execution)- Custom callable - Function that takes the exception and returns a string for the
AIMessagecontent
initial_delay * (backoff_factor ** retry_number) seconds. Set to 0.0 for constant delay.±25%) to delay to avoid thundering herdFull example
Full example
LLM tool emulator
Emulate tool execution using an LLM for testing purposes, replacing actual tool calls with AI-generated responses. LLM tool emulators are useful for the following:- Testing agent behavior without executing real tools.
- Developing agents when external tools are unavailable or expensive.
- Prototyping agent workflows before implementing actual tools.
LLMToolEmulator
Configuration options
Configuration options
None (default), ALL tools will be emulated. If empty list [], no tools will be emulated. If array with tool names/instances, only those tools will be emulated.'google_genai:gemini-3.5-flash') or a BaseChatModel instance. Defaults to the agent’s model if not specified. See init_chat_model for more information.Full example
Full example
Context editing
Manage conversation context by clearing older tool call outputs when token limits are reached, while preserving recent results. This helps keep context windows manageable in long conversations with many tool calls. Context editing is useful for the following:- Long conversations with many tool calls that exceed token limits
- Reducing token costs by removing older tool outputs that are no longer relevant
- Maintaining only the most recent N tool results in context
ContextEditingMiddleware, ClearToolUsesEdit
Configuration options
Configuration options
ContextEdit strategies to apply'approximate' or 'model'ClearToolUsesEdit options:True, tool call arguments are replaced with empty objects.Full example
Full example
ClearToolUsesEdit, which clears older tool results while preserving recent ones.How it works:- Monitor token count in conversation
- When threshold is reached, clear older tool outputs
- Keep most recent N tool results
- Optionally preserve tool call arguments for context
Provider tool search
Defer selected tools behind model providers’ server-side tool search, so the model discovers them on demand instead of receiving every tool schema up front. Provider tool search is useful for:- Reducing context bloat when using many tools.
- Improving tool selection accuracy by surfacing only relevant tools.
ValueError.ProviderToolSearchMiddleware
Configuration options
Configuration options
extras={"defer_loading": True} are deferred regardless of this option; if searchable_tools is omitted, only those pre-marked tools are deferred.Full example
Full example
searchable_tools for deferral and search. A tool can also opt into deferral at construction time by setting extras={"defer_loading": True}.Shell tool
Expose a persistent shell session to agents for command execution. Shell tool middleware is useful for the following:- Agents that need to execute system commands
- Development and deployment automation tasks
- Testing and validation workflows
- File system operations and script execution
ShellToolMiddleware
Configuration options
Configuration options
HostExecutionPolicy- Full host access (default); best for trusted environments where the agent already runs inside a container or VMDockerExecutionPolicy- Launches a separate Docker container for each agent run, providing harder isolationCodexSandboxExecutionPolicy- Reuses the Codex CLI sandbox for additional syscall/filesystem restrictions
/bin/bash.Full example
Full example
HostExecutionPolicy(default) - Native execution with full host accessDockerExecutionPolicy- Isolated Docker container executionCodexSandboxExecutionPolicy- Sandboxed execution via Codex CLI
File search
Provide Glob and Grep search tools over a filesystem. File search middleware is useful for the following:- Code exploration and analysis
- Finding files by name patterns
- Searching code content with regex
- Large codebases where file discovery is needed
FilesystemFileSearchMiddleware
Configuration options
Configuration options
Full example
Full example
- Supports patterns like
**/*.py,src/**/*.ts - Returns matching file paths sorted by modification time
- Full regex syntax support
- Filter by file patterns with
includeparameter - Three output modes:
files_with_matches,content,count
Filesystem middleware
Context engineering is a main challenge in building effective agents. This is particularly difficult when using tools that return variable-length results (for example,web_search and RAG), as long tool results can quickly fill your context window.
FilesystemMiddleware from Deep Agents provides four tools for interacting with both short-term and long-term memory:
ls: List the files in the filesystemread_file: Read an entire file or a certain number of lines from a filewrite_file: Write a new file to the filesystemedit_file: Edit an existing file in the filesystem
Short-term vs. long-term filesystem
By default, these tools write to a local “filesystem” in your graph state. To enable persistent storage across threads, configure aCompositeBackend that routes specific paths (like /memories/) to a StoreBackend.
CompositeBackend with a StoreBackend for /memories/, any files prefixed with /memories/ are saved to persistent storage and survive across different threads. Files without this prefix remain in ephemeral state storage.
Subagent
Handing off tasks to subagents isolates context, keeping the main (supervisor) agent’s context window clean while still going deep on a task. The subagents middleware from Deep Agents allows you to supply subagents through atask tool.
general-purpose subagent at all times. This subagent has the same instructions as the main agent and all the tools it has access to. The primary purpose of the general-purpose subagent is context isolation—the main agent can delegate a complex task to this subagent and get a concise answer back without bloat from intermediate tool calls.
Rubric grading
RubricMiddleware requires deepagents>=0.6.5. It is in beta; the API may change in the future.RubricMiddleware lets you declare what done looks like as a rubric and have the agent self-evaluate and iterate until the rubric is satisfied or a maximum iteration cap is hit.
API reference: RubricMiddleware

