Skip to main content
LangChain 和 Deep Agents 为常见用例提供预构建中间件。每种中间件都已为生产环境准备就绪,并可针对您的特定需求进行配置。

与提供商无关的中间件

以下中间件可与任何 LLM 提供商配合使用:
中间件描述
摘要在接近令牌限制时自动总结对话历史。
人机回环暂停执行以供人工批准工具调用。
模型调用限制限制模型调用次数以防止成本过高。
工具调用限制通过限制调用次数来控制工具执行。
模型回退当主模型失败时自动回退到替代模型。
PII 检测检测并处理个人身份信息 (PII)。
待办事项列表为代理配备任务规划和跟踪能力。
LLM 工具选择器在调用主模型之前使用 LLM 选择相关工具。
工具重试使用指数退避自动重试失败的工具调用。
模型重试使用指数退避自动重试失败的模型调用。
LLM 工具模拟器使用 LLM 模拟工具执行以用于测试目的。
上下文编辑通过修剪或清除工具使用来管理对话上下文。
文件系统为代理提供用于存储上下文和长期记忆的文件系统。
子代理中间件添加生成子代理的能力。

摘要

在接近令牌限制时自动总结对话历史,保留最近的消息同时压缩较旧的上下文。摘要适用于以下情况:
  • 超过上下文窗口的长时间运行的对话。
  • 具有广泛历史的多轮对话。
  • 保留完整对话上下文很重要的应用程序。
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 条件(如下所示)依赖于聊天模型的配置文件数据(如果使用 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(数字):模型上下文大小的分数(0-1)
  • tokens(数字):绝对令牌计数
  • messages(数字):消息计数
每个条件必须至少指定一个属性。如果未提供,摘要将不会自动触发。
keep
object
default:"{messages: 20}"
摘要后要保留的上下文量。精确指定以下一项:
  • fraction(数字):要保留的模型上下文大小的分数(0-1)
  • tokens(数字):要保留的绝对令牌计数
  • messages(数字):要保留的最近消息数
tokenCounter
function
自定义令牌计数函数。默认为基于字符的计数。
summaryPrompt
string
用于摘要的自定义提示模板。如果未指定,则使用内置模板。模板应包含 {messages} 占位符,对话历史将插入其中。
trimTokensToSummarize
number
default:"4000"
生成摘要时要包含的最大令牌数。消息将在摘要之前被修剪以适应此限制。
summaryPrefix
string
添加到摘要消息的前缀。如果未提供,则使用默认前缀。
maxTokensBeforeSummary
number
deprecated
已弃用: 请改用 trigger: { tokens: value }。触发摘要的令牌阈值。
messagesToKeep
number
deprecated
已弃用: 请改用 keep: { messages: value }。要保留的最近消息。
摘要中间件监控消息令牌计数,并在达到阈值时自动总结较旧的消息。触发条件控制摘要何时运行:
  • 单个条件对象(指定的条件必须满足)
  • 条件数组(任何条件必须满足 - OR 逻辑)
  • 每个条件可以使用 fraction(模型上下文大小的分数)、tokens(绝对计数)或 messages(消息计数)
保留条件控制要保留的上下文量(精确指定一项):
  • fraction - 要保留的模型上下文大小的分数
  • tokens - 要保留的绝对令牌计数
  • messages - 要保留的最近消息数
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, messages: 10 },
      keep: { messages: 20 },
    }),
  ],
});

// 多个条件
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 },
    }),
  ],
});

// 使用分数限制
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 },
    }),
  ],
});

人机回环

暂停代理执行以供人工批准、编辑或拒绝工具调用,然后才执行。人机回环 适用于以下情况:
  • 需要人工批准的高风险操作(例如数据库写入、金融交易)。
  • 需要人工监督的合规工作流。
  • 人工反馈指导代理的长时间运行对话。
人机回环中间件需要一个检查点来在中断期间维护状态。
import { createAgent, humanInTheLoopMiddleware } from "langchain";

function readEmailTool(emailId: string): string {
  /** 通过 ID 读取电子邮件的模拟函数。 */
  return `Email content for ID: ${emailId}`;
}

function sendEmailTool(recipient: string, subject: string, body: string): string {
  /** 发送电子邮件的模拟函数。 */
  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,
      }
    })
  ]
});
有关完整示例、配置选项和集成模式,请参阅人机回环文档
观看此视频指南,演示人机回环中间件行为。

模型调用限制

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

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

工具调用限制

通过限制工具调用次数来控制代理执行,可以全局限制所有工具,也可以针对特定工具。工具调用限制适用于以下情况:
  • 防止对昂贵的外部 API 进行过多调用。
  • 限制网络搜索或数据库查询。
  • 对特定工具使用强制执行速率限制。
  • 防止代理循环失控。
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 的多次调用之间会持久化。需要检查点来维护状态。undefined 表示无线程限制。
runLimit
number
单次调用(一个用户消息 → 响应周期)的最大工具调用次数。每个新用户消息都会重置。undefined 表示无运行限制。注意: 必须至少指定 threadLimitrunLimit 中的一个。
exitBehavior
string
default:"continue"
达到限制时的行为:
  • 'continue'(默认) - 用错误消息阻止超出的工具调用,让其他工具和模型继续。模型根据错误消息决定何时结束。
  • 'error' - 抛出 ToolCallLimitExceededError 异常,立即停止执行
  • 'end' - 立即停止执行,并为超出的工具调用提供 ToolMessage 和 AI 消息。仅在限制单个工具时有效;如果其他工具有待处理调用,则抛出错误。
使用以下方式指定限制:
  • 线程限制 - 对话中所有运行的最大调用次数(需要检查点)
  • 运行限制 - 单次调用的最大调用次数(每轮重置)
退出行为:
  • 'continue'(默认) - 用错误消息阻止超出的调用,代理继续
  • '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],
});

模型回退

当主模型失败时自动回退到替代模型。模型回退适用于以下情况:
  • 构建能够处理模型中断的弹性代理。
  • 通过回退到更便宜的模型来优化成本。
  • 跨 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)。PII 检测适用于以下情况:
  • 具有合规要求的医疗保健和金融应用程序。
  • 需要清理日志的客户服务代理。
  • 处理敏感用户数据的任何应用程序。
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. 正则表达式模式字符串 - 简单模式匹配
  2. RegExp 对象 - 对正则表达式标志的更多控制
  3. 自定义函数 - 具有验证的复杂检测逻辑
import { createAgent, piiMiddleware, type PIIMatch } from "langchain";

// 方法 1:正则表达式模式字符串
const agent1 = createAgent({
  model: "gpt-4.1",
  tools: [],
  middleware: [
    piiMiddleware("api_key", {
      detector: "sk-[a-zA-Z0-9]{32}",
      strategy: "block",
    }),
  ],
});

// 方法 2:RegExp 对象
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",
    }),
  ],
});

// 方法 3:自定义检测器函数
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];
    // 验证:前三位数字不能是 000、666 或 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;    // 匹配的文本
  start: number;   // 内容中的起始索引
  end: number;      // 内容中的结束索引
}

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"
在执行后检查工具结果消息

待办事项列表

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

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

LLM 工具选择器

在调用主模型之前使用 LLM 智能选择相关工具。LLM 工具选择器适用于以下情况:
  • 具有许多工具(10+)的代理,其中大多数与每个查询无关。
  • 通过过滤无关工具来减少令牌使用。
  • 提高模型的专注度和准确性。
此中间件使用结构化输出来询问 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 实例。默认为代理的主模型。
systemPrompt
string
选择模型的指令。如果未指定,则使用内置提示。
maxTools
number
要选择的最大工具数。如果模型选择更多,则仅使用前 maxTools 个。如果未指定,则无限制。
alwaysInclude
string[]
无论选择如何都始终包含的工具名称。这些不计入 maxTools 限制。

工具重试

使用可配置的指数退避自动重试失败的工具调用。工具重试适用于以下情况:
  • 处理外部 API 调用中的瞬时故障。
  • 提高依赖网络的工具的可靠性。
  • 构建能够优雅处理临时错误的弹性代理。
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' - 重新引发异常,停止代理执行
  • 自定义函数 - 接受异常并返回 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" - 重新引发异常
  • 自定义函数 - 返回错误消息的函数
import { createAgent, toolRetryMiddleware } from "langchain";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

// 使用默认设置的基本用法(2 次重试,指数退避)
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool, databaseTool],
  middleware: [toolRetryMiddleware()],
});

// 仅重试特定异常
const retry = toolRetryMiddleware({
  maxRetries: 4,
  retryOn: [TimeoutError, NetworkError],
  backoffFactor: 1.5,
});

// 自定义异常过滤
function shouldRetry(error: Error): boolean {
  // 仅重试 5xx 错误
  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,
});

// 应用于特定工具并使用自定义错误处理
const formatError = (error: Error) =>
  "数据库暂时不可用。请稍后再试。";

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

// 使用 BaseTool 实例应用于特定工具
const searchDatabase = tool(
  async ({ query }) => {
    // 搜索实现
    return results;
  },
  {
    name: "search_database",
    description: "搜索数据库",
    schema: z.object({ query: z.string() }),
  }
);

const retryWithToolInstance = toolRetryMiddleware({
  maxRetries: 4,
  tools: [searchDatabase], // 传递 BaseTool 实例
});

// 恒定退避(无指数增长)
const constantBackoff = toolRetryMiddleware({
  maxRetries: 5,
  backoffFactor: 0.0, // 无指数增长
  initialDelayMs: 2000, // 始终等待 2 秒
});

// 故障时引发异常
const strictRetry = toolRetryMiddleware({
  maxRetries: 2,
  onFailure: "error", // 重新引发异常而不是返回消息
});

模型重试

使用可配置的指数退避自动重试失败的模型调用。模型重试适用于以下情况:
  • 处理模型 API 调用中的瞬时故障。
  • 提高依赖网络的模型请求的可靠性。
  • 构建能够优雅处理临时模型错误的弹性代理。
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,允许代理可能优雅地处理故障
  • 'error' - 重新引发异常,停止代理执行
  • 自定义函数 - 接受异常并返回 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";

// 使用默认设置的基本用法(2 次重试,指数退避)
const agent = createAgent({
  model: "gpt-4.1",
  tools: [searchTool],
  middleware: [modelRetryMiddleware()],
});

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

// 仅重试特定异常
const retry = modelRetryMiddleware({
  maxRetries: 4,
  retryOn: [TimeoutError, NetworkError],
  backoffFactor: 1.5,
});

// 自定义异常过滤
function shouldRetry(error: Error): boolean {
  // 仅重试速率限制错误
  if (error.name === "RateLimitError") {
    return true;
  }
  // 或检查特定的 HTTP 状态代码
  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,
});

// 返回错误消息而不是引发
const retryContinue = modelRetryMiddleware({
  maxRetries: 4,
  onFailure: "continue", // 返回 AIMessage 错误而不是抛出
});

// 自定义错误消息格式
const formatError = (error: Error) =>
  `模型调用失败:${error.message}。请稍后再试。`;

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

// 恒定退避(无指数增长)
const constantBackoff = modelRetryMiddleware({
  maxRetries: 5,
  backoffFactor: 0.0, // 无指数增长
  initialDelayMs: 2000, // 始终等待 2 秒
});

// 故障时引发异常
const strictRetry = modelRetryMiddleware({
  maxRetries: 2,
  onFailure: "error", // 重新引发异常而不是返回消息
});

LLM 工具模拟器

使用 LLM 模拟工具执行以用于测试目的,用 AI 生成的响应替换实际工具调用。LLM 工具模拟器适用于以下情况:
  • 测试代理行为而不执行真实工具。
  • 在外部工具不可用或昂贵时开发代理。
  • 在实现实际工具之前原型化代理工作流。
import { createAgent, toolEmulatorMiddleware } from "langchain";

const agent = createAgent({
  model: "gpt-4.1",
  tools: [getWeather, searchDatabase, sendEmail],
  middleware: [
    toolEmulatorMiddleware(), // 模拟所有工具
  ],
});
tools
(string | ClientTool | ServerTool)[]
要模拟的工具名称(字符串)或工具实例列表。如果 undefined(默认),将模拟所有工具。如果空数组 [],则不模拟任何工具。如果包含工具名称/实例的数组,则仅模拟这些工具。
model
string | BaseChatModel
用于生成模拟工具响应的模型。可以是模型标识符字符串(例如,'anthropic:claude-sonnet-4-6')或 BaseChatModel 实例。如果未指定,则默认为代理的模型。
中间件使用 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(),
    }),
  }
);

// 模拟所有工具(默认行为)
const agent = createAgent({
  model: "gpt-4.1",
  tools: [getWeather, sendEmail],
  middleware: [toolEmulatorMiddleware()],
});

// 按名称模拟特定工具
const agent2 = createAgent({
  model: "gpt-4.1",
  tools: [getWeather, sendEmail],
  middleware: [
    toolEmulatorMiddleware({
      tools: ["get_weather"],
    }),
  ],
});

// 通过传递工具实例模拟特定工具
const agent3 = createAgent({
  model: "gpt-4.1",
  tools: [getWeather, sendEmail],
  middleware: [
    toolEmulatorMiddleware({
      tools: [getWeather],
    }),
  ],
});

// 使用自定义模型进行模拟
const agent5 = createAgent({
  model: "gpt-4.1",
  tools: [getWeather, sendEmail],
  middleware: [
    toolEmulatorMiddleware({
      model: "claude-sonnet-4-6",
    }),
  ],
});

上下文编辑

通过在令牌限制达到时清除较旧的工具调用输出来管理对话上下文,同时保留最近的结果。这有助于在具有许多工具调用的长时间对话中保持上下文窗口可管理。上下文编辑适用于以下情况:
  • 具有许多工具调用且超过令牌限制的长时间对话
  • 通过删除不再相关的较旧工具输出来降低令牌成本
  • 在上下文中仅保留最近的 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"
触发编辑的令牌计数。当对话超过此令牌计数时,将清除较旧的工具输出。
clearAtLeast
number
default:"0"
编辑运行时要回收的最小令牌数。如果设置为 0,则根据需要清除。
keep
number
default:"3"
必须保留的最近工具结果数。这些永远不会被清除。
clearToolInputs
boolean
default:"false"
是否清除 AI 消息上的原始工具调用参数。当为 true 时,工具调用参数将替换为空对象。
excludeTools
string[]
default:"[]"
要从清除中排除的工具名称列表。这些工具的输出永远不会被清除。
placeholder
string
default:"[cleared]"
为清除的工具输出插入的占位符文本。这将替换原始工具消息内容。
当令牌限制达到时,中间件应用上下文编辑策略。最常见的策略是 ClearToolUsesEdit,它清除较旧的工具结果,同时保留最近的工具结果。工作原理:
  1. 监控对话中的令牌计数
  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]",
        }),
      ],
    }),
  ],
});

文件系统中间件

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

// FilesystemMiddleware 默认包含在 createDeepAgent 中
// 如果构建自定义代理,可以自定义它
const agent = createAgent({
  model: "claude-sonnet-4-6",
  middleware: [
    createFilesystemMiddleware({
      backend: undefined,  // 可选:自定义后端(默认为 StateBackend)
      systemPrompt: "Write to the filesystem when...",  // 可选:自定义系统提示覆盖
      customToolDescriptions: {
        ls: "Use the ls tool when...",
        read_file: "Use the read_file tool to...",
      },  // 可选:文件系统工具的自定义描述
    }),
  ],
});

短期与长期文件系统

默认情况下,这些工具写入图状态中的本地“文件系统”。要启用跨线程的持久存储,请配置一个 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: new CompositeBackend(
        new StateBackend(),
        { "/memories/": new StoreBackend() }
      ),
      systemPrompt: "Write to the filesystem when...", // 可选:自定义系统提示覆盖
      customToolDescriptions: {
        ls: "Use the ls tool when...",
        read_file: "Use the read_file tool to...",
      }, // 可选:文件系统工具的自定义描述
    }),
  ],
});
当您为 /memories/ 配置带有 StoreBackendCompositeBackend 时,任何以 /memories/ 为前缀的文件都会保存到持久存储中,并在不同线程中保留。没有此前缀的文件保留在临时状态存储中。

子代理

将任务移交给子代理可以隔离上下文,保持主(监督)代理的上下文窗口干净,同时仍然深入处理任务。 来自 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: [],
        },
      ],
    }),
  ],
});
子代理使用名称描述系统提示工具定义。您还可以为子代理提供自定义模型或附加中间件。当您希望子代理具有与主代理共享的附加状态键时,这可能特别有用。 对于更复杂的用例,您还可以提供您自己的预构建 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 提供商进行了优化。有关完整详细信息和示例,请参阅每个提供商的文档。
https://mintcdn.com/other-405835d4/agS8-xZoA1Gortud/images/providers/anthropic-icon.svg?fit=max&auto=format&n=agS8-xZoA1Gortud&q=85&s=88c98a84317065dc83e422014a1aac2c

Anthropic

适用于 Claude 模型的提示缓存、bash 工具、文本编辑器、内存和文件搜索中间件。