Skip to main content
LangChain 和 Deep Agents 为常见用例提供了预构建的中间件。每个中间件都是生产就绪的,并且可根据您的具体需求进行配置。

与提供商无关的中间件

以下中间件适用于任何 LLM 提供商:
中间件描述
摘要 (Summarization)当接近 token 限制时自动总结对话历史记录。
Human-in-the-loop暂停执行以等待人工批准工具调用。
模型调用限制 (Model call limit)限制模型调用次数以防止过多成本。
工具调用限制 (Tool call limit)通过限制调用计数来控制工具执行。
模型回退 (Model fallback)当主模型失败时自动回退到替代模型。
PII 检测 (PII detection)检测并处理个人身份信息 (PII)。
待办事项列表 (To-do list)为 agent 配备任务规划和跟踪能力。
LLM 工具选择器 (LLM tool selector)在调用主模型之前使用 LLM 选择相关工具。
工具重试 (Tool retry)自动使用指数退避重试失败的工具调用。
模型重试 (Model retry)自动使用指数退避重试失败的模型调用。
LLM 工具模拟器 (LLM tool emulator)使用 LLM 模拟工具执行以进行测试。
上下文编辑 (Context editing)通过修剪或清除工具使用来管理对话上下文。
文件系统 (Filesystem)为 agent 提供文件系统以存储上下文和长期记忆。
子智能体中间件 (Subagent middleware)添加生成子智能体的能力。

摘要 (Summarization)

当接近 token 限制时自动总结对话历史记录,保留最近的消息同时压缩旧的上下文。摘要对于以下情况很有用:
  • 超过上下文窗口的长时间运行的对话。
  • 具有大量历史记录的多轮对话。
  • 保留完整对话上下文很重要的应用程序。
import { createAgent, summarizationMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [weatherTool, calculatorTool],
  middleware: [
    summarizationMiddleware({
      model: "gpt-4.1-mini",
      trigger: { tokens: 4000 },
      keep: { messages: 20 },
    }),
  ],
});
triggerkeepfraction 条件(如下所示)依赖于聊天模型的 profile data(如果使用 langchain@1.1.0)。如果数据不可用,请使用其他条件或手动指定:
const customProfile: ModelProfile = {
    maxInputTokens: 100_000,
    // ...
}
model = await initChatModel("...", {
    profile: customProfile,
});
model
string | BaseChatModel
required
用于生成摘要的模型。可以是模型标识符字符串(例如 'openai:gpt-4.1-mini')或 BaseChatModel 实例。
trigger
object | object[]
触发摘要的条件。可以是:
  • 单个条件对象(必须满足所有属性 - AND 逻辑)
  • 条件对象数组(必须满足任何条件 - OR 逻辑)
每个条件可以包括:
  • fraction (number): 模型上下文大小的分数 (0-1)
  • tokens (number): 绝对 token 计数
  • messages (number): 消息计数
每个条件必须至少指定一个属性。如果未提供,摘要将不会自动触发。
keep
object
default:"{messages: 20}"
摘要后保留多少上下文。准确指定以下之一:
  • fraction (number): 要保留的模型上下文大小的分数 (0-1)
  • tokens (number): 要保留的绝对 token 计数
  • messages (number): 要保留的最近消息数
tokenCounter
function
自定义 token 计数函数。默认为基于字符的计数。
summaryPrompt
string
摘要的自定义提示模板。如果未指定,则使用内置模板。模板应包含 {messages} 占位符,对话历史记录将插入其中。
trimTokensToSummarize
number
default:"4000"
生成摘要时包含的最大 token 数。消息将在摘要之前被修剪以适应此限制。
summaryPrefix
string
添加到摘要消息的前缀。如果未提供,则使用默认前缀。
maxTokensBeforeSummary
number
deprecated
已弃用: 请改用 trigger: { tokens: value }。触发摘要的 token 阈值。
messagesToKeep
number
deprecated
已弃用: 请改用 keep: { messages: value }。要保留的最近消息。
摘要中间件监控消息 token 计数并在达到阈值时自动总结旧消息。触发条件 控制摘要何时运行:
  • 单个条件对象(必须满足指定条件)
  • 条件数组(必须满足任何条件 - OR 逻辑)
  • 每个条件可以使用 fraction(模型上下文大小的分数)、tokens(绝对计数)或 messages(消息计数)
保留条件 控制要保留多少上下文(准确指定一个):
  • fraction - 要保留的模型上下文大小的分数
  • tokens - 要保留的绝对 token 计数
  • messages - 要保留的最近消息数
import { createAgent, summarizationMiddleware } from "langchain";

// Single condition
const agent = createAgent({
  model: "gpt-4.1",
  tools: [weatherTool, calculatorTool],
  middleware: [
    summarizationMiddleware({
      model: "gpt-4.1-mini",
      trigger: { tokens: 4000, messages: 10 },
      keep: { messages: 20 },
    }),
  ],
});

// Multiple conditions
const agent2 = createAgent({
  model: "gpt-4.1",
  tools: [weatherTool, calculatorTool],
  middleware: [
    summarizationMiddleware({
      model: "gpt-4.1-mini",
      trigger: [
        { tokens: 3000, messages: 6 },
      ],
      keep: { messages: 20 },
    }),
  ],
});

// Using fractional limits
const agent3 = createAgent({
  model: "gpt-4.1",
  tools: [weatherTool, calculatorTool],
  middleware: [
    summarizationMiddleware({
      model: "gpt-4.1-mini",
      trigger: { fraction: 0.8 },
      keep: { fraction: 0.3 },
    }),
  ],
});

Human-in-the-loop

暂停 agent 执行以供人工批准、编辑或拒绝工具调用,然后再执行它们。Human-in-the-loop 对于以下情况很有用:
  • 需要人工批准的高风险操作(例如数据库写入、金融交易)。
  • 强制要求人工监督的合规工作流。
  • 人工反馈指导 agent 的长时间运行的对话。
Human-in-the-loop 中间件需要 checkpointer 以在中断期间保持状态。
import { createAgent, humanInTheLoopMiddleware } from "langchain";

function readEmailTool(emailId: string): string {
  /** Mock function to read an email by its ID. */
  return `Email content for ID: ${emailId}`;
}

function sendEmailTool(recipient: string, subject: string, body: string): string {
  /** Mock function to send an email. */
  return `Email sent to ${recipient} with subject '${subject}'`;
}

const agent = createAgent({
  model: "gpt-4.1",
  tools: [readEmailTool, sendEmailTool],
  middleware: [
    humanInTheLoopMiddleware({
      interruptOn: {
        sendEmailTool: {
          allowedDecisions: ["approve", "edit", "reject"],
        },
        readEmailTool: false,
      }
    })
  ]
});
有关完整示例、配置选项和集成模式,请参阅 Human-in-the-loop 文档
观看此 视频指南 演示 Human-in-the-loop 中间件行为。

模型调用限制 (Model call limit)

限制模型调用次数以防止无限循环或过多成本。模型调用限制对于以下情况很有用:
  • 防止失控的 agent 进行过多的 API 调用。
  • 对生产部署实施成本控制。
  • 在特定调用预算内测试 agent 行为。
import { createAgent, modelCallLimitMiddleware } from "langchain";
import { MemorySaver } from "@langchain/langgraph";

const agent = createAgent({
  model: "gpt-4.1",
  checkpointer: new MemorySaver(), // Required for thread limiting
  tools: [],
  middleware: [
    modelCallLimitMiddleware({
      threadLimit: 10,
      runLimit: 5,
      exitBehavior: "end",
    }),
  ],
});
观看此 视频指南 演示模型调用限制中间件行为。
threadLimit
number
线程中所有运行的最大模型调用次数。默认为无限制。
runLimit
number
每次单个调用的最大模型调用次数。默认为无限制。
exitBehavior
string
default:"end"
达到限制时的行为。选项:'end'(优雅终止)或 'error'(抛出异常)

工具调用限制 (Tool call limit)

通过限制工具调用次数来控制 agent 执行,既可以针对所有工具全局限制,也可以针对特定工具限制。工具调用限制对于以下情况很有用:
  • 防止过度调用昂贵的外部 API。
  • 限制网络搜索或数据库查询。
  • 对特定工具使用实施速率限制。
  • 防止失控的 agent 循环。
import { createAgent, toolCallLimitMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, databaseTool],
  middleware: [
    toolCallLimitMiddleware({ threadLimit: 20, runLimit: 10 }),
    toolCallLimitMiddleware({
      toolName: "search",
      threadLimit: 5,
      runLimit: 3,
    }),
  ],
});
观看此 视频指南 演示工具调用限制中间件行为。
toolName
string
要限制的特定工具的名称。如果未提供,限制将应用于全局所有工具
threadLimit
number
线程(对话)中所有运行的最大工具调用次数。在具有相同线程 ID 的多次调用中持久存在。需要 checkpointer 来维持状态。undefined 意味着无线程限制。
runLimit
number
每次单个调用(一个用户消息 → 响应周期)的最大工具调用次数。每个新用户消息重置。undefined 意味着无运行限制。注意: 必须指定 threadLimitrunLimit 中的至少一个。
exitBehavior
string
default:"continue"
达到限制时的行为:
  • 'continue' (默认) - 阻止超出的工具调用并显示错误消息,让其他工具和模型继续。模型根据错误消息决定何时结束。
  • 'error' - 抛出 ToolCallLimitExceededError 异常,立即停止执行
  • 'end' - 使用 ToolMessage 和 AI 消息立即停止执行超出的工具调用。仅在限制单个工具时有效;如果其他工具具有挂起的调用,则抛出错误。
指定限制:
  • Thread limit - 对话中所有运行的最大调用次数(需要 checkpointer)
  • Run limit - 每次单个调用的最大调用次数(每轮重置)
退出行为:
  • 'continue' (默认) - 用错误消息阻止超出的调用,agent 继续
  • 'error' - 立即引发异常
  • 'end' - 用 ToolMessage + AI 消息停止(仅限单工具场景)
import { createAgent, toolCallLimitMiddleware } from "langchain";

const globalLimiter = toolCallLimitMiddleware({ threadLimit: 20, runLimit: 10 });
const searchLimiter = toolCallLimitMiddleware({ toolName: "search", threadLimit: 5, runLimit: 3 });
const databaseLimiter = toolCallLimitMiddleware({ toolName: "query_database", threadLimit: 10 });
const strictLimiter = toolCallLimitMiddleware({ toolName: "scrape_webpage", runLimit: 2, exitBehavior: "error" });

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, databaseTool, scraperTool],
  middleware: [globalLimiter, searchLimiter, databaseLimiter, strictLimiter],
});

模型回退 (Model fallback)

当主模型失败时自动回退到替代模型。模型回退对于以下情况很有用:
  • 构建能够处理模型中断的弹性 agent。
  • 通过回退到更便宜的模型来优化成本。
  • 跨 OpenAI、Anthropic 等的提供商冗余。
import { createAgent, modelFallbackMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [],
  middleware: [
    modelFallbackMiddleware(
      "gpt-4.1-mini",
      "claude-3-5-sonnet-20241022"
    ),
  ],
});
中间件按顺序接受可变数量的表示回退模型的字符串参数:
...models
string[]
required
当主模型失败时要按顺序尝试的一个或多个回退模型字符串
modelFallbackMiddleware(
  "first-fallback-model",
  "second-fallback-model",
  // ... more models
)

PII 检测 (PII detection)

使用可配置的策略在对话中检测并处理个人身份信息 (PII)。PII 检测对于以下情况很有用:
  • 具有合规要求的医疗保健和金融应用程序。
  • 需要清理日志的客户服务 agent。
  • 任何处理敏感用户数据的应用程序。
import { createAgent, piiMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [],
  middleware: [
    piiMiddleware("email", { strategy: "redact", applyToInput: true }),
    piiMiddleware("credit_card", { strategy: "mask", applyToInput: true }),
  ],
});

自定义 PII 类型

您可以通过提供 detector 参数来创建自定义 PII 类型。这允许您检测特定于您用例的模式,这超出了内置类型的范围。 创建自定义检测器的三种方法:
  1. Regex 模式字符串 - 简单的模式匹配
  2. RegExp 对象 - 对正则表达式标志的更多控制
  3. 自定义函数 - 具有验证的复杂检测逻辑
import { createAgent, piiMiddleware, type PIIMatch } from "langchain";

// Method 1: Regex pattern string
const agent1 = createAgent({
  model: "gpt-4.1",
  tools: [],
  middleware: [
    piiMiddleware("api_key", {
      detector: "sk-[a-zA-Z0-9]{32}",
      strategy: "block",
    }),
  ],
});

// Method 2: RegExp object
const agent2 = createAgent({
  model: "gpt-4.1",
  tools: [],
  middleware: [
    piiMiddleware("phone_number", {
      detector: /\+?\d{1,3}[\s.-]?\d{3,4}[\s.-]?\d{4}/,
      strategy: "mask",
    }),
  ],
});

// Method 3: Custom detector function
function detectSSN(content: string): PIIMatch[] {
  const matches: PIIMatch[] = [];
  const pattern = /\d{3}-\d{2}-\d{4}/g;
  let match: RegExpExecArray | null;

  while ((match = pattern.exec(content)) !== null) {
    const ssn = match[0];
    // Validate: first 3 digits shouldn't be 000, 666, or 900-999
    const firstThree = parseInt(ssn.substring(0, 3), 10);
    if (firstThree !== 0 && firstThree !== 666 && !(firstThree >= 900 && firstThree <= 999)) {
      matches.push({
        text: ssn,
        start: match.index ?? 0,
        end: (match.index ?? 0) + ssn.length,
      });
    }
  }
  return matches;
}

const agent3 = createAgent({
  model: "gpt-4.1",
  tools: [],
  middleware: [
    piiMiddleware("ssn", {
      detector: detectSSN,
      strategy: "hash",
    }),
  ],
});
自定义检测器函数签名: 检测器函数必须接受一个字符串 (内容) 并返回匹配项: 返回 PIIMatch 对象数组:
interface PIIMatch {
  text: string;    // The matched text
  start: number;   // Start index in content
  end: number;      // End index in content
}

function detector(content: string): PIIMatch[] {
  return [
    { text: "matched_text", start: 0, end: 12 },
    // ... more matches
  ];
}
对于自定义检测器:
  • 对简单模式使用正则表达式字符串
  • 当您需要标志(例如不区分大小写的匹配)时使用 RegExp 对象
  • 当您需要超出模式匹配的验证逻辑时使用自定义函数
  • 自定义函数使您可以完全控制检测逻辑,并可以实现复杂的验证规则
piiType
string
required
要检测的 PII 类型。可以是内置类型(emailcredit_cardipmac_addressurl)或自定义类型名称。
strategy
string
default:"redact"
如何处理检测到的 PII。选项:
  • 'block' - 检测到时抛出错误
  • 'redact' - 替换为 [REDACTED_TYPE]
  • 'mask' - 部分屏蔽(例如 ****-****-****-1234
  • 'hash' - 替换为确定性哈希(例如 <email_hash:a1b2c3d4>
detector
RegExp | string | function
自定义检测器。可以是:
  • RegExp - 用于匹配的正则表达式模式
  • string - 正则表达式模式字符串(例如 "sk-[a-zA-Z0-9]{32}"
  • function - 自定义检测器函数 (content: string) => PIIMatch[]
如果未提供,则使用 PII 类型的内置检测器。
applyToInput
boolean
default:"true"
在模型调用之前检查用户消息
applyToOutput
boolean
default:"false"
在模型调用之后检查 AI 消息
applyToToolResults
boolean
default:"false"
执行后检查工具结果消息

待办事项列表 (To-do list)

为 agent 配备任务规划和跟踪能力,以处理复杂的多步骤任务。待办事项列表对于以下情况很有用:
  • 需要跨多个工具进行协调的复杂多步骤任务。
  • 进度可见性很重要的长时间运行的操作。
此中间件自动为 agent 提供 write_todos 工具和系统提示,以指导有效的任务规划。
import { createAgent, todoListMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [readFile, writeFile, runTests],
  middleware: [todoListMiddleware()],
});
观看此 视频指南 演示待办事项列表中间件行为。
没有可用的配置选项(使用默认值)。

LLM 工具选择器 (LLM tool selector)

在调用主模型之前,使用 LLM 智能地选择相关工具。LLM 工具选择器对于以下情况很有用:
  • 具有许多工具 (10+) 的 agent,其中大多数与每个查询都不相关。
  • 通过过滤不相关的工具来减少 token 使用量。
  • 提高模型焦点和准确性。
此中间件使用结构化输出询问 LLM 哪些工具与当前查询最相关。结构化输出架构定义了可用的工具名称和描述。模型提供商通常在幕后将此结构化输出信息添加到系统提示中。
import { createAgent, llmToolSelectorMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [tool1, tool2, tool3, tool4, tool5, ...],
  middleware: [
    llmToolSelectorMiddleware({
      model: "gpt-4.1-mini",
      maxTools: 3,
      alwaysInclude: ["search"],
    }),
  ],
});
model
string | BaseChatModel
用于工具选择的模型。可以是模型标识符字符串(例如 'openai:gpt-4.1-mini')或 BaseChatModel 实例。默认为 agent 的主模型。
systemPrompt
string
选择模型的说明。如果未指定,则使用内置提示。
maxTools
number
要选择的最大工具数。如果模型选择更多,则仅使用前 maxTools 个。如果未指定,则无限制。
alwaysInclude
string[]
无论选择如何都始终包含的工具名称。这些不计入 maxTools 限制。

工具重试 (Tool retry)

自动使用可配置的指数退避重试失败的工具调用。工具重试对于以下情况很有用:
  • 处理外部 API 调用中的暂时性故障。
  • 提高网络依赖型工具的可靠性。
  • 构建能够优雅地处理临时错误的弹性 agent。
API 参考: toolRetryMiddleware
import { createAgent, toolRetryMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, databaseTool],
  middleware: [
    toolRetryMiddleware({
      maxRetries: 3,
      backoffFactor: 2.0,
      initialDelayMs: 1000,
    }),
  ],
});
maxRetries
number
default:"2"
初始调用后的最大重试尝试次数(默认总共 3 次尝试)。必须 >= 0。
tools
(ClientTool | ServerTool | string)[]
要应用重试逻辑的工具或工具名称的可选数组。可以是 BaseTool 实例或工具名称字符串的列表。如果为 undefined,则应用于所有工具。
retryOn
((error: Error) => boolean) | (new (...args: any[]) => Error)[]
default:"() => true"
要重试的错误构造函数数组,或者是接受错误并返回 true(如果应该重试)的函数。默认为重试所有错误。
onFailure
'error' | 'continue' | ((error: Error) => string)
default:"continue"
耗尽所有重试时的行为。选项:
  • 'continue' (默认) - 返回带有错误详细信息的 ToolMessage,允许 LLM 处理故障并可能恢复
  • 'error' - 重新引发异常,停止 agent 执行
  • 自定义函数 - 接受异常并返回 ToolMessage 内容字符串的函数,允许自定义错误格式
已弃用的值: 'raise' (改用 'error') 和 'return_message' (改用 'continue')。这些已弃用的值仍然有效,但会显示警告。
backoffFactor
number
default:"2.0"
指数退避的乘数。每次重试等待 initialDelayMs * (backoffFactor ** retryNumber) 毫秒。设置为 0.0 表示恒定延迟。必须 >= 0。
initialDelayMs
number
default:"1000"
第一次重试前的初始延迟(以毫秒为单位)。必须 >= 0。
maxDelayMs
number
default:"60000"
重试之间的最大延迟(以毫秒为单位)(限制指数退避增长)。必须 >= 0。
jitter
boolean
default:"true"
是否向延迟添加随机抖动 (±25%) 以避免惊群效应
中间件自动使用指数退避重试失败的工具调用。关键配置:
  • maxRetries - 重试尝试次数 (默认: 2)
  • backoffFactor - 指数退避乘数 (默认: 2.0)
  • initialDelayMs - 毫秒起始延迟 (默认: 1000ms)
  • maxDelayMs - 延迟增长上限 (默认: 60000ms)
  • jitter - 添加随机变化 (默认: true)
故障处理:
  • onFailure: "continue" (默认) - 返回错误消息
  • onFailure: "error" - 重新引发异常
  • Custom function - 返回错误消息的函数
import { createAgent, toolRetryMiddleware } from "langchain";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

// Basic usage with default settings (2 retries, exponential backoff)
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, databaseTool],
  middleware: [toolRetryMiddleware()],
});

// Retry specific exceptions only
const retry = toolRetryMiddleware({
  maxRetries: 4,
  retryOn: [TimeoutError, NetworkError],
  backoffFactor: 1.5,
});

// Custom exception filtering
function shouldRetry(error: Error): boolean {
  // Only retry on 5xx errors
  if (error.name === "HTTPError" && "statusCode" in error) {
    const statusCode = (error as any).statusCode;
    return 500 <= statusCode && statusCode < 600;
  }
  return false;
}

const retryWithFilter = toolRetryMiddleware({
  maxRetries: 3,
  retryOn: shouldRetry,
});

// Apply to specific tools with custom error handling
const formatError = (error: Error) =>
  "Database temporarily unavailable. Please try again later.";

const retrySpecificTools = toolRetryMiddleware({
  maxRetries: 4,
  tools: ["search_database"],
  onFailure: formatError,
});

// Apply to specific tools using BaseTool instances
const searchDatabase = tool(
  async ({ query }) => {
    // Search implementation
    return results;
  },
  {
    name: "search_database",
    description: "Search the database",
    schema: z.object({ query: z.string() }),
  }
);

const retryWithToolInstance = toolRetryMiddleware({
  maxRetries: 4,
  tools: [searchDatabase], // Pass BaseTool instance
});

// Constant backoff (no exponential growth)
const constantBackoff = toolRetryMiddleware({
  maxRetries: 5,
  backoffFactor: 0.0, // No exponential growth
  initialDelayMs: 2000, // Always wait 2 seconds
});

// Raise exception on failure
const strictRetry = toolRetryMiddleware({
  maxRetries: 2,
  onFailure: "error", // Re-raise exception instead of returning message
});

模型重试 (Model retry)

自动使用可配置的指数退避重试失败的模型调用。模型重试对于以下情况很有用:
  • 处理模型 API 调用中的暂时性故障。
  • 提高网络依赖型模型请求的可靠性。
  • 构建能够优雅地处理临时模型错误的弹性 agent。
API 参考: modelRetryMiddleware
import { createAgent, modelRetryMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, databaseTool],
  middleware: [
    modelRetryMiddleware({
      maxRetries: 3,
      backoffFactor: 2.0,
      initialDelayMs: 1000,
    }),
  ],
});
maxRetries
number
default:"2"
初始调用后的最大重试尝试次数(默认总共 3 次尝试)。必须 >= 0。
retryOn
((error: Error) => boolean) | (new (...args: any[]) => Error)[]
default:"() => true"
要重试的错误构造函数数组,或者是接受错误并返回 true(如果应该重试)的函数。默认为重试所有错误。
onFailure
'error' | 'continue' | ((error: Error) => string)
default:"continue"
耗尽所有重试时的行为。选项:
  • 'continue' (默认) - 返回带有错误详细信息的 AIMessage,允许 agent 可能优雅地处理故障
  • 'error' - 重新引发异常,停止 agent 执行
  • 自定义函数 - 接受异常并返回 AIMessage 内容字符串的函数,允许自定义错误格式
backoffFactor
number
default:"2.0"
指数退避的乘数。每次重试等待 initialDelayMs * (backoffFactor ** retryNumber) 毫秒。设置为 0.0 表示恒定延迟。必须 >= 0。
initialDelayMs
number
default:"1000"
第一次重试前的初始延迟(以毫秒为单位)。必须 >= 0。
maxDelayMs
number
default:"60000"
重试之间的最大延迟(以毫秒为单位)(限制指数退避增长)。必须 >= 0。
jitter
boolean
default:"true"
是否向延迟添加随机抖动 (±25%) 以避免惊群效应
中间件自动使用指数退避重试失败的模型调用。
import { createAgent, modelRetryMiddleware } from "langchain";

// Basic usage with default settings (2 retries, exponential backoff)
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
  middleware: [modelRetryMiddleware()],
});

class TimeoutError extends Error {
    // ...
}
class NetworkError extends Error {
    // ...
}

// Retry specific exceptions only
const retry = modelRetryMiddleware({
  maxRetries: 4,
  retryOn: [TimeoutError, NetworkError],
  backoffFactor: 1.5,
});

// Custom exception filtering
function shouldRetry(error: Error): boolean {
  // Only retry on rate limit errors
  if (error.name === "RateLimitError") {
    return true;
  }
  // Or check for specific HTTP status codes
  if (error.name === "HTTPError" && "statusCode" in error) {
    const statusCode = (error as any).statusCode;
    return statusCode === 429 || statusCode === 503;
  }
  return false;
}

const retryWithFilter = modelRetryMiddleware({
  maxRetries: 3,
  retryOn: shouldRetry,
});

// Return error message instead of raising
const retryContinue = modelRetryMiddleware({
  maxRetries: 4,
  onFailure: "continue", // Return AIMessage with error instead of throwing
});

// Custom error message formatting
const formatError = (error: Error) =>
  `Model call failed: ${error.message}. Please try again later.`;

const retryWithFormatter = modelRetryMiddleware({
  maxRetries: 4,
  onFailure: formatError,
});

// Constant backoff (no exponential growth)
const constantBackoff = modelRetryMiddleware({
  maxRetries: 5,
  backoffFactor: 0.0, // No exponential growth
  initialDelayMs: 2000, // Always wait 2 seconds
});

// Raise exception on failure
const strictRetry = modelRetryMiddleware({
  maxRetries: 2,
  onFailure: "error", // Re-raise exception instead of returning message
});

LLM 工具模拟器 (LLM tool emulator)

使用 LLM 模拟工具执行以进行测试,用 AI 生成的响应替换实际工具调用。LLM 工具模拟器对于以下情况很有用:
  • 无需执行实际工具即可测试 agent 行为。
  • 当外部工具不可用或昂贵时开发 agent。
  • 在实施实际工具之前对 agent 工作流进行原型设计。
import { createAgent, toolEmulatorMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [getWeather, searchDatabase, sendEmail],
  middleware: [
    toolEmulatorMiddleware(), // Emulate all tools
  ],
});
tools
(string | ClientTool | ServerTool)[]
要模拟的工具名称 (字符串) 或工具实例的列表。如果为 undefined (默认),将模拟所有工具。如果为空数组 [],将不模拟任何工具。如果是包含工具名称/实例的数组,则仅模拟这些工具。
model
string | BaseChatModel
用于生成模拟工具响应的模型。可以是模型标识符字符串(例如 'anthropic:claude-sonnet-4-6')或 BaseChatModel 实例。如果未指定,默认为 agent 的模型。
中间件使用 LLM 为工具调用生成合理的响应,而不是执行实际工具。
import { createAgent, toolEmulatorMiddleware, tool } from "langchain";
import * as z from "zod";

const getWeather = tool(
  async ({ location }) => `Weather in ${location}`,
  {
    name: "get_weather",
    description: "Get the current weather for a location",
    schema: z.object({ location: z.string() }),
  }
);

const sendEmail = tool(
  async ({ to, subject, body }) => "Email sent",
  {
    name: "send_email",
    description: "Send an email",
    schema: z.object({
      to: z.string(),
      subject: z.string(),
      body: z.string(),
    }),
  }
);

// Emulate all tools (default behavior)
const agent = createAgent({
  model: "gpt-4.1",
  tools: [getWeather, sendEmail],
  middleware: [toolEmulatorMiddleware()],
});

// Emulate specific tools by name
const agent2 = createAgent({
  model: "gpt-4.1",
  tools: [getWeather, sendEmail],
  middleware: [
    toolEmulatorMiddleware({
      tools: ["get_weather"],
    }),
  ],
});

// Emulate specific tools by passing tool instances
const agent3 = createAgent({
  model: "gpt-4.1",
  tools: [getWeather, sendEmail],
  middleware: [
    toolEmulatorMiddleware({
      tools: [getWeather],
    }),
  ],
});

// Use custom model for emulation
const agent5 = createAgent({
  model: "gpt-4.1",
  tools: [getWeather, sendEmail],
  middleware: [
    toolEmulatorMiddleware({
      model: "claude-sonnet-4-6",
    }),
  ],
});

上下文编辑 (Context editing)

通过在达到 token 限制时清除旧的工具调用输出来管理对话上下文,同时保留最近的结果。这有助于在具有许多工具调用的长对话中保持上下文窗口的可管理性。上下文编辑对于以下情况很有用:
  • 具有许多工具调用且超过 token 限制的长对话
  • 通过删除不再相关的旧工具输出来降低 token 成本
  • 仅在上下文中保留最近的 N 个工具结果
import { createAgent, contextEditingMiddleware, ClearToolUsesEdit } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [],
  middleware: [
    contextEditingMiddleware({
      edits: [
        new ClearToolUsesEdit({
          triggerTokens: 100000,
          keep: 3,
        }),
      ],
    }),
  ],
});
edits
ContextEdit[]
default:"[new ClearToolUsesEdit()]"
要应用的 ContextEdit 策略数组
ClearToolUsesEdit 选项:
triggerTokens
number
default:"100000"
触发编辑的 token 计数。当对话超过此 token 计数时,将清除较旧的工具输出。
clearAtLeast
number
default:"0"
编辑运行时要回收的最小 token 数。如果设置为 0,则根据需要清除尽可能多的 token。
keep
number
default:"3"
必须保留的最近工具结果的数量。这些永远不会被清除。
clearToolInputs
boolean
default:"false"
是否清除 AI 消息上的原始工具调用参数。当为 true 时,工具调用参数将替换为空对象。
excludeTools
string[]
default:"[]"
要从清除中排除的工具名称列表。这些工具的输出永远不会被清除。
placeholder
string
default:"[cleared]"
为已清除的工具输出插入的占位符文本。这将替换原始工具消息内容。
中间件在达到 token 限制时应用上下文编辑策略。最常见的策略是 ClearToolUsesEdit,它清除较旧的工具结果,同时保留最近的结果。工作原理:
  1. 监控对话中的 token 计数
  2. 达到阈值时,清除较旧的工具输出
  3. 保留最近的 N 个工具结果
  4. 可选地保留工具调用参数以作为上下文
import { createAgent, contextEditingMiddleware, ClearToolUsesEdit } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, calculatorTool, databaseTool],
  middleware: [
    contextEditingMiddleware({
      edits: [
        new ClearToolUsesEdit({
          triggerTokens: 2000,
          keep: 3,
          clearToolInputs: false,
          excludeTools: [],
          placeholder: "[cleared]",
        }),
      ],
    }),
  ],
});

文件系统中间件 (Filesystem middleware)

上下文工程是构建有效 agent 的主要挑战。当使用返回可变长度结果的工具(例如 web_search 和 RAG)时,这尤其困难,因为长的工具结果会迅速填满您的上下文窗口。 来自 deep agentsFilesystemMiddleware 提供了四个用于与短期和长期记忆交互的工具:
  • ls: 列出文件系统中的文件
  • read_file: 读取整个文件或文件中的一定数量的行
  • write_file: 向文件系统写入新文件
  • edit_file: 编辑文件系统中的现有文件
import { createAgent } from "langchain";
import { createFilesystemMiddleware } from "deepagents";

// FilesystemMiddleware is included by default in createDeepAgent
// You can customize it if building a custom agent
const agent = createAgent({
  model: "claude-sonnet-4-6",
  middleware: [
    createFilesystemMiddleware({
      backend: undefined,  // Optional: custom backend (defaults to StateBackend)
      systemPrompt: "Write to the filesystem when...",  // Optional custom system prompt override
      customToolDescriptions: {
        ls: "Use the ls tool when...",
        read_file: "Use the read_file tool to...",
      },  // Optional: Custom descriptions for filesystem tools
    }),
  ],
});

短期与长期文件系统

默认情况下,这些工具会写入图状态中的本地“文件系统”。要启用跨线程的持久存储,请配置 CompositeBackend,将特定路径(如 /memories/)路由到 StoreBackend
import { createAgent } from "langchain";
import { createFilesystemMiddleware, CompositeBackend, StateBackend, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph-checkpoint";

const store = new InMemoryStore();

const agent = createAgent({
  model: "claude-sonnet-4-6",
  store,
  middleware: [
    createFilesystemMiddleware({
      backend: (config) => new CompositeBackend(
        new StateBackend(config),
        { "/memories/": new StoreBackend(config) }
      ),
      systemPrompt: "Write to the filesystem when...", // Optional custom system prompt override
      customToolDescriptions: {
        ls: "Use the ls tool when...",
        read_file: "Use the read_file tool to...",
      }, // Optional: Custom descriptions for filesystem tools
    }),
  ],
});
当您为 /memories/ 配置带有 StoreBackendCompositeBackend 时,任何以 /memories/ 为前缀的文件都将保存到持久存储中,并在不同线程之间保留。没有此前缀的文件将保留在临时状态存储中。

子智能体 (Subagent)

将任务移交给子智能体可以隔离上下文,使主(监督)智能体的上下文窗口保持清洁,同时仍然深入任务。 来自 deep agents 的子智能体中间件允许您通过 task 工具提供子智能体。
import { tool } from "langchain";
import { createAgent } from "langchain";
import { createSubAgentMiddleware } from "deepagents";
import { z } from "zod";

const getWeather = tool(
  async ({ city }: { city: string }) => {
    return `The weather in ${city} is sunny.`;
  },
  {
    name: "get_weather",
    description: "Get the weather in a city.",
    schema: z.object({
      city: z.string(),
    }),
  },
);

const agent = createAgent({
  model: "claude-sonnet-4-6",
  middleware: [
    createSubAgentMiddleware({
      defaultModel: "claude-sonnet-4-6",
      defaultTools: [],
      subagents: [
        {
          name: "weather",
          description: "This subagent can get weather in cities.",
          systemPrompt: "Use the get_weather tool to get the weather in a city.",
          tools: [getWeather],
          model: "gpt-4.1",
          middleware: [],
        },
      ],
    }),
  ],
});
子智能体通过 namedescriptionsystem prompttools 定义。您还可以为子智能体提供自定义 model 或其他 middleware。当您想给子智能体一个额外的状态键以与主智能体共享时,这特别有用。 对于更复杂的用例,您还可以提供自己的预构建 LangGraph 图作为子智能体。
import { tool, createAgent } from "langchain";
import { createSubAgentMiddleware, type SubAgent } from "deepagents";
import { z } from "zod";

const getWeather = tool(
  async ({ city }: { city: string }) => {
    return `The weather in ${city} is sunny.`;
  },
  {
    name: "get_weather",
    description: "Get the weather in a city.",
    schema: z.object({
      city: z.string(),
    }),
  },
);

const weatherSubagent: SubAgent = {
  name: "weather",
  description: "This subagent can get weather in cities.",
  systemPrompt: "Use the get_weather tool to get the weather in a city.",
  tools: [getWeather],
  model: "gpt-4.1",
  middleware: [],
};

const agent = createAgent({
  model: "claude-sonnet-4-6",
  middleware: [
    createSubAgentMiddleware({
      defaultModel: "claude-sonnet-4-6",
      defaultTools: [],
      subagents: [weatherSubagent],
    }),
  ],
});
除了任何用户定义的子智能体之外,主智能体还可以随时访问 general-purpose 子智能体。此子智能体具有与主智能体相同的指令及其有权访问的所有工具。general-purpose 子智能体的主要目的是上下文隔离——主智能体可以将复杂任务委托给此子智能体,并在没有中间工具调用的情况下获得简洁的回复。

提供商特定中间件

这些中间件针对特定的 LLM 提供商进行了优化。有关完整的详细信息和示例,请参阅每个提供商的文档。