Documentation Index Fetch the complete documentation index at: https://nvd-54.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
构建智能体(或任何大语言模型(LLM)应用)的难点在于让它们足够可靠。虽然它们在原型阶段可能有效,但在实际使用场景中往往会失败。
为什么智能体会失败?
当智能体失败时,通常是因为智能体内部的 LLM 调用采取了错误的操作/没有按照我们的预期执行。LLM 失败的原因有两个:
底层 LLM 能力不足
没有向 LLM 传递”正确的”上下文
更多时候——实际上是第二个原因导致智能体不够可靠。
上下文工程 是指以正确的格式提供正确的信息和工具,使 LLM 能够完成任务。这是 AI 工程师的首要工作。缺乏”正确的”上下文是构建更可靠智能体的最大障碍,而 LangChain 的智能体抽象正是为促进上下文工程而独特设计的。
初次接触上下文工程?从概念概述 开始,了解不同类型的上下文以及何时使用它们。
智能体循环
典型的智能体循环包含两个主要步骤:
模型调用 - 使用提示词和可用工具调用 LLM,返回响应或执行工具的请求
工具执行 - 执行 LLM 请求的工具,返回工具结果
此循环持续进行,直到 LLM 决定结束。
你可以控制什么
要构建可靠的智能体,你需要控制智能体循环中每个步骤发生的事情,以及步骤之间发生的事情。
上下文类型 你控制的内容 瞬态还是持久 模型上下文 模型调用中包含的内容(指令、消息历史、工具、响应格式) 瞬态 工具上下文 工具可以访问和产生的内容(对状态、存储、运行时上下文的读/写) 持久 生命周期上下文 模型和工具调用之间发生的事情(摘要、护栏、日志等) 持久
瞬态上下文 LLM 在单次调用中看到的内容。你可以修改消息、工具或提示词,而不改变保存在状态中的内容。
持久上下文 跨轮次保存在状态中的内容。生命周期钩子和工具写入会永久修改它。
数据源
在整个过程中,你的智能体会访问(读/写)不同的数据源:
数据源 别名 作用范围 示例 运行时上下文 静态配置 会话级别 用户 ID、API 密钥、数据库连接、权限、环境设置 状态 短期记忆 会话级别 当前消息、上传的文件、认证状态、工具结果 存储 长期记忆 跨会话 用户偏好、提取的洞察、记忆、历史数据
工作原理
LangChain 中间件 是底层机制,使上下文工程对使用 LangChain 的开发者来说变得实用。
中间件允许你钩入智能体生命周期的任何步骤,并:
在本指南中,你将频繁看到中间件 API 作为实现上下文工程目标的手段。
模型上下文
控制每次模型调用中包含的内容——指令、可用工具、使用哪个模型以及输出格式。这些决策直接影响可靠性和成本。
所有这些类型的模型上下文都可以从状态 (短期记忆)、存储 (长期记忆)或运行时上下文 (静态配置)中获取。
系统提示词
系统提示词设置 LLM 的行为和能力。不同的用户、上下文或对话阶段需要不同的指令。成功的智能体会利用记忆、偏好和配置来为当前对话状态提供正确的指令。
从状态中访问消息数量或对话上下文: import { createAgent } from "langchain" ;
const agent = createAgent ( {
model : "gpt-5.4" ,
tools : [ ... ] ,
middleware : [
dynamicSystemPromptMiddleware ( ( state ) => {
// 从状态读取:检查对话长度
const messageCount = state . messages . length ;
let base = "You are a helpful assistant." ;
if (messageCount > 10 ) {
base += " \n This is a long conversation - be extra concise." ;
}
return base ;
} ) ,
] ,
} ) ;
从长期记忆中访问用户偏好: import * as z from "zod" ;
import { createAgent , dynamicSystemPromptMiddleware } from "langchain" ;
const contextSchema = z . object ( {
userId : z . string () ,
} ) ;
type Context = z . infer < typeof contextSchema > ;
const agent = createAgent ( {
model : "gpt-5.4" ,
tools : [ ... ] ,
contextSchema ,
middleware : [
dynamicSystemPromptMiddleware < Context > ( async ( state , runtime ) => {
const userId = runtime . context . userId ;
// 从存储读取:获取用户偏好
const store = runtime . store ;
const userPrefs = await store . get ([ "preferences" ] , userId) ;
let base = "You are a helpful assistant." ;
if (userPrefs) {
const style = userPrefs . value ?. communicationStyle || "balanced" ;
base += ` \n User prefers ${ style } responses.` ;
}
return base ;
} ) ,
] ,
} ) ;
从运行时上下文访问用户 ID 或配置: import * as z from "zod" ;
import { createAgent , dynamicSystemPromptMiddleware } from "langchain" ;
const contextSchema = z . object ( {
userRole : z . string () ,
deploymentEnv : z . string () ,
} ) ;
type Context = z . infer < typeof contextSchema > ;
const agent = createAgent ( {
model : "gpt-5.4" ,
tools : [ ... ] ,
contextSchema ,
middleware : [
dynamicSystemPromptMiddleware < Context > ( ( state , runtime ) => {
// 从运行时上下文读取:用户角色和环境
const userRole = runtime . context . userRole ;
const env = runtime . context . deploymentEnv ;
let base = "You are a helpful assistant." ;
if (userRole === "admin" ) {
base += " \n You have admin access. You can perform all operations." ;
} else if (userRole === "viewer" ) {
base += " \n You have read-only access. Guide users to read operations only." ;
}
if (env === "production" ) {
base += " \n Be extra careful with any data modifications." ;
}
return base ;
} ) ,
] ,
} ) ;
消息组成发送给 LLM 的提示词。
管理消息的内容至关重要,以确保 LLM 拥有正确的信息来做出良好的响应。
当与当前查询相关时,从状态中注入上传的文件上下文: import { createMiddleware } from "langchain" ;
const injectFileContext = createMiddleware ( {
name : "InjectFileContext" ,
wrapModelCall : ( request , handler ) => {
// request.state 是 request.state.messages 的快捷方式
const uploadedFiles = request . state . uploadedFiles || [] ;
if (uploadedFiles . length > 0 ) {
// 构建可用文件的上下文
const fileDescriptions = uploadedFiles . map ( file =>
`- ${ file . name } ( ${ file . type } ): ${ file . summary } `
) ;
const fileContext = `Files you have access to in this conversation:
${ fileDescriptions . join ( " \n " ) }
Reference these files when answering questions.` ;
// 在最近的消息之前注入文件上下文
const messages = [
... request . messages , // 其余对话
{ role : "user" , content : fileContext }
] ;
request = request . override ( { messages } ) ;
}
return handler (request) ;
},
} ) ;
const agent = createAgent ( {
model : "gpt-5.4" ,
tools : [ ... ] ,
middleware : [injectFileContext] ,
} ) ;
从存储中注入用户的邮件写作风格以指导撰写: import * as z from "zod" ;
import { createMiddleware } from "langchain" ;
const contextSchema = z . object ( {
userId : z . string () ,
} ) ;
const injectWritingStyle = createMiddleware ( {
name : "InjectWritingStyle" ,
contextSchema ,
wrapModelCall : async ( request , handler ) => {
const userId = request . runtime . context . userId ;
// 从存储读取:获取用户的写作风格示例
const store = request . runtime . store ;
const writingStyle = await store . get ([ "writing_style" ] , userId) ;
if (writingStyle) {
const style = writingStyle . value ;
// 从存储的示例构建风格指南
const styleContext = `Your writing style:
- Tone: ${ style . tone || 'professional' }
- Typical greeting: " ${ style . greeting || 'Hi' } "
- Typical sign-off: " ${ style . signOff || 'Best' } "
- Example email you've written:
${ style . exampleEmail || '' } ` ;
// 追加到末尾——模型更关注最后的消息
const messages = [
... request . messages ,
{ role : "user" , content : styleContext }
] ;
request = request . override ( { messages } ) ;
}
return handler (request) ;
},
} ) ;
根据用户所在司法管辖区从运行时上下文注入合规规则: import * as z from "zod" ;
import { createMiddleware } from "langchain" ;
const contextSchema = z . object ( {
userJurisdiction : z . string () ,
industry : z . string () ,
complianceFrameworks : z . array (z . string ()) ,
} ) ;
type Context = z . infer < typeof contextSchema > ;
const injectComplianceRules = createMiddleware < Context > ( {
name : "InjectComplianceRules" ,
contextSchema ,
wrapModelCall : ( request , handler ) => {
// 从运行时上下文读取:获取合规要求
const { userJurisdiction , industry , complianceFrameworks } = request . runtime . context ;
// 构建合规约束
const rules = [] ;
if (complianceFrameworks . includes ( "GDPR" )) {
rules . push ( "- Must obtain explicit consent before processing personal data" ) ;
rules . push ( "- Users have right to data deletion" ) ;
}
if (complianceFrameworks . includes ( "HIPAA" )) {
rules . push ( "- Cannot share patient health information without authorization" ) ;
rules . push ( "- Must use secure, encrypted communication" ) ;
}
if (industry === "finance" ) {
rules . push ( "- Cannot provide financial advice without proper disclaimers" ) ;
}
if (rules . length > 0 ) {
const complianceContext = `Compliance requirements for ${ userJurisdiction } :
${ rules . join ( " \n " ) } ` ;
// 追加到末尾——模型更关注最后的消息
const messages = [
... request . messages ,
{ role : "user" , content : complianceContext }
] ;
request = request . override ( { messages } ) ;
}
return handler (request) ;
},
} ) ;
瞬态与持久消息更新: 上面的示例使用 wrap_model_call 进行瞬态 更新——修改单次模型调用中发送的消息,而不改变保存在状态中的内容。 对于修改状态的持久 更新,你可以:
直接从 wrapModelCall 返回 Command 来从模型调用层注入状态更新。
使用生命周期钩子如 beforeModel、afterModel 或 wrapToolCall(用于工具返回)来更新对话历史。更多详情请参阅中间件文档 。
有关更多信息,请参阅状态更新 。
工具让模型与数据库、API 和外部系统交互。你如何定义和选择工具直接影响模型是否能有效完成任务。
定义工具
每个工具需要清晰的名称、描述、参数名称和参数描述。这些不仅仅是元数据——它们指导模型关于何时以及如何使用工具的推理。
import { tool } from "@langchain/core/tools" ;
import { z } from "zod" ;
const searchOrders = tool (
async ({ userId , status , limit }) => {
// 实现代码
},
{
name : "search_orders" ,
description : `Search for user orders by status.
Use this when the user asks about order history or wants to check
order status. Always filter by the provided status.` ,
schema : z . object ( {
userId : z . string () . describe ( "Unique identifier for the user" ) ,
status : z . enum ([ "pending" , "shipped" , "delivered" ]) . describe ( "Order status to filter by" ) ,
limit : z . number () . default ( 10 ) . describe ( "Maximum number of results to return" ) ,
} ) ,
}
) ;
选择工具
并非每个工具都适合每种情况。太多的工具可能会让模型不堪重负(上下文过载)并增加错误;太少则限制能力。动态工具选择可以根据认证状态、用户权限、功能标志或对话阶段来调整可用的工具集。
仅在达到特定对话里程碑后启用高级工具: import { createMiddleware } from "langchain" ;
const stateBasedTools = createMiddleware ( {
name : "StateBasedTools" ,
wrapModelCall : ( request , handler ) => {
// 从状态读取:检查认证和对话长度
const state = request . state ;
const isAuthenticated = state . authenticated || false ;
const messageCount = state . messages . length ;
let filteredTools = request . tools ;
// 仅在认证后启用敏感工具
if ( ! isAuthenticated) {
filteredTools = request . tools . filter ( t => t . name . startsWith ( "public_" )) ;
} else if (messageCount < 5 ) {
filteredTools = request . tools . filter ( t => t . name !== "advanced_search" ) ;
}
return handler ( { ... request , tools : filteredTools } ) ;
},
} ) ;
根据存储中的用户偏好或功能标志过滤工具: import * as z from "zod" ;
import { createMiddleware } from "langchain" ;
const contextSchema = z . object ( {
userId : z . string () ,
} ) ;
const storeBasedTools = createMiddleware ( {
name : "StoreBasedTools" ,
contextSchema ,
wrapModelCall : async ( request , handler ) => {
const userId = request . runtime . context . userId ;
// 从存储读取:获取用户启用的功能
const store = request . runtime . store ;
const featureFlags = await store . get ([ "features" ] , userId) ;
let filteredTools = request . tools ;
if (featureFlags) {
const enabledFeatures = featureFlags . value ?. enabledTools || [] ;
filteredTools = request . tools . filter ( t => enabledFeatures . includes (t . name)) ;
}
return handler ( { ... request , tools : filteredTools } ) ;
},
} ) ;
根据运行时上下文中的用户权限过滤工具: import * as z from "zod" ;
import { createMiddleware } from "langchain" ;
const contextSchema = z . object ( {
userRole : z . string () ,
} ) ;
const contextBasedTools = createMiddleware ( {
name : "ContextBasedTools" ,
contextSchema ,
wrapModelCall : ( request , handler ) => {
// 从运行时上下文读取:获取用户角色
const userRole = request . runtime . context . userRole ;
let filteredTools = request . tools ;
if (userRole === "admin" ) {
// 管理员获得所有工具
} else if (userRole === "editor" ) {
filteredTools = request . tools . filter ( t => t . name !== "delete_data" ) ;
} else {
filteredTools = request . tools . filter ( t => t . name . startsWith ( "read_" )) ;
}
return handler ( { ... request , tools : filteredTools } ) ;
},
} ) ;
请参阅动态工具 了解过滤预注册工具和在运行时注册工具(例如从 MCP 服务器)的两种方式。
不同的模型有不同的优势、成本和上下文窗口。为当前任务选择合适的模型,这在智能体运行期间可能会发生变化。
根据状态中的对话长度使用不同的模型: import { createMiddleware , initChatModel } from "langchain" ;
// 在中间件外部初始化模型一次
const largeModel = initChatModel ( "claude-sonnet-4-6" ) ;
const standardModel = initChatModel ( "gpt-5.4" ) ;
const efficientModel = initChatModel ( "gpt-5.4-mini" ) ;
const stateBasedModel = createMiddleware ( {
name : "StateBasedModel" ,
wrapModelCall : ( request , handler ) => {
// request.messages 是 request.state.messages 的快捷方式
const messageCount = request . messages . length ;
let model ;
if (messageCount > 20 ) {
model = largeModel ;
} else if (messageCount > 10 ) {
model = standardModel ;
} else {
model = efficientModel ;
}
return handler ( { ... request , model } ) ;
},
} ) ;
从存储中使用用户的首选模型: import * as z from "zod" ;
import { createMiddleware , initChatModel } from "langchain" ;
const contextSchema = z . object ( {
userId : z . string () ,
} ) ;
// 初始化一次可用的模型
const MODEL_MAP = {
"gpt-5.4" : initChatModel ( "gpt-5.4" ) ,
"gpt-5.4-mini" : initChatModel ( "gpt-5.4-mini" ) ,
"claude-sonnet" : initChatModel ( "claude-sonnet-4-6" ) ,
};
const storeBasedModel = createMiddleware ( {
name : "StoreBasedModel" ,
contextSchema ,
wrapModelCall : async ( request , handler ) => {
const userId = request . runtime . context . userId ;
// 从存储读取:获取用户的首选模型
const store = request . runtime . store ;
const userPrefs = await store . get ([ "preferences" ] , userId) ;
let model = request . model ;
if (userPrefs) {
const preferredModel = userPrefs . value ?. preferredModel ;
if (preferredModel && MODEL_MAP[preferredModel]) {
model = MODEL_MAP[preferredModel] ;
}
}
return handler ( { ... request , model } ) ;
},
} ) ;
根据运行时上下文中的成本限制或环境选择模型: import * as z from "zod" ;
import { createMiddleware , initChatModel } from "langchain" ;
const contextSchema = z . object ( {
costTier : z . string () ,
environment : z . string () ,
} ) ;
// 在中间件外部初始化模型一次
const premiumModel = initChatModel ( "claude-sonnet-4-6" ) ;
const standardModel = initChatModel ( "gpt-5.4" ) ;
const budgetModel = initChatModel ( "gpt-5.4-mini" ) ;
const contextBasedModel = createMiddleware ( {
name : "ContextBasedModel" ,
contextSchema ,
wrapModelCall : ( request , handler ) => {
// 从运行时上下文读取:成本层级和环境
const costTier = request . runtime . context . costTier ;
const environment = request . runtime . context . environment ;
let model ;
if (environment === "production" && costTier === "premium" ) {
model = premiumModel ;
} else if (costTier === "budget" ) {
model = budgetModel ;
} else {
model = standardModel ;
}
return handler ( { ... request , model } ) ;
},
} ) ;
更多示例请参阅动态模型 。
响应格式
结构化输出将非结构化文本转换为经过验证的结构化数据。当提取特定字段或为下游系统返回数据时,自由格式的文本是不够的。
工作原理: 当你提供 schema 作为响应格式时,模型的最终响应保证符合该 schema。智能体运行模型/工具调用循环,直到模型完成工具调用,然后最终响应被强制转换为提供的格式。
定义格式
Schema 定义指导模型。字段名称、类型和描述指定了输出应该遵循的确切格式。
import { z } from "zod" ;
const customerSupportTicket = z . object ( {
category : z . enum ([ "billing" , "technical" , "account" , "product" ]) . describe (
"问题类别"
) ,
priority : z . enum ([ "low" , "medium" , "high" , "critical" ]) . describe (
"紧急程度"
) ,
summary : z . string () . describe (
"客户问题的一句话摘要"
) ,
customerSentiment : z . enum ([ "frustrated" , "neutral" , "satisfied" ]) . describe (
"客户的情绪基调"
) ,
} ) . describe ( "从客户消息中提取的结构化工单信息" ) ;
选择格式
动态响应格式选择可以根据用户偏好、对话阶段或角色来调整 schema——在早期返回简单格式,随着复杂度增加返回详细格式。
根据对话状态配置结构化输出: import { createMiddleware } from "langchain" ;
import { z } from "zod" ;
const simpleResponse = z . object ( {
answer : z . string () . describe ( "简短回答" ) ,
} ) ;
const detailedResponse = z . object ( {
answer : z . string () . describe ( "详细回答" ) ,
reasoning : z . string () . describe ( "推理过程说明" ) ,
confidence : z . number () . describe ( "置信度分数 0-1" ) ,
} ) ;
const stateBasedOutput = createMiddleware ( {
name : "StateBasedOutput" ,
wrapModelCall : ( request , handler ) => {
// request.state 是 request.state.messages 的快捷方式
const messageCount = request . messages . length ;
let responseFormat ;
if (messageCount < 3 ) {
// 早期对话——使用简单格式
responseFormat = simpleResponse ;
} else {
// 已建立的对话——使用详细格式
responseFormat = detailedResponse ;
}
return handler ( { ... request , responseFormat } ) ;
},
} ) ;
根据存储中的用户偏好配置输出格式: import * as z from "zod" ;
import { createMiddleware } from "langchain" ;
const contextSchema = z . object ( {
userId : z . string () ,
} ) ;
const verboseResponse = z . object ( {
answer : z . string () . describe ( "详细回答" ) ,
sources : z . array (z . string ()) . describe ( "使用的来源" ) ,
} ) ;
const conciseResponse = z . object ( {
answer : z . string () . describe ( "简短回答" ) ,
} ) ;
const storeBasedOutput = createMiddleware ( {
name : "StoreBasedOutput" ,
wrapModelCall : async ( request , handler ) => {
const userId = request . runtime . context . userId ;
// 从存储读取:获取用户的首选响应风格
const store = request . runtime . store ;
const userPrefs = await store . get ([ "preferences" ] , userId) ;
const style = userPrefs ?. value ?. responseStyle || "concise" ;
const responseFormat =
style === "verbose" ? verboseResponse : conciseResponse ;
return handler ( {
... request ,
responseFormat ,
} ) ;
},
} ) ;
根据运行时上下文(如用户角色或环境)配置输出格式: import * as z from "zod" ;
import { createMiddleware } from "langchain" ;
const contextSchema = z . object ( {
userRole : z . string () ,
environment : z . string () ,
} ) ;
const adminResponse = z . object ( {
answer : z . string () . describe ( "回答" ) ,
debugInfo : z . record (z . any ()) . describe ( "调试信息" ) ,
systemStatus : z . string () . describe ( "系统状态" ) ,
} ) ;
const userResponse = z . object ( {
answer : z . string () . describe ( "回答" ) ,
} ) ;
const contextBasedOutput = createMiddleware ( {
name : "ContextBasedOutput" ,
wrapModelCall : ( request , handler ) => {
// 从运行时上下文读取:用户角色和环境
const userRole = request . runtime . context . userRole ;
const environment = request . runtime . context . environment ;
let responseFormat ;
if (userRole === "admin" && environment === "production" ) {
responseFormat = adminResponse ;
} else {
responseFormat = userResponse ;
}
return handler ( { ... request , responseFormat } ) ;
},
} ) ;
工具上下文
工具的特殊之处在于它们既读取又写入上下文。
在最基本的情况下,当工具执行时,它接收 LLM 的请求参数并返回一条工具消息。工具完成其工作并产生结果。
工具还可以为模型获取重要信息,使其能够执行和完成任务。
大多数真实世界的工具不仅仅需要 LLM 的参数。它们需要用户 ID 来进行数据库查询、API 密钥来访问外部服务,或当前会话状态来做决策。工具从状态、存储和运行时上下文读取以访问这些信息。
从状态读取以检查当前会话信息: import * as z from "zod" ;
import { createAgent , tool , type ToolRuntime } from "langchain" ;
const checkAuthentication = tool (
async ( _ , runtime : ToolRuntime ) => {
// 从状态读取:检查当前认证状态
const currentState = runtime . state ;
const isAuthenticated = currentState . authenticated || false ;
if (isAuthenticated) {
return "User is authenticated" ;
} else {
return "User is not authenticated" ;
}
},
{
name : "check_authentication" ,
description : "Check if user is authenticated" ,
schema : z . object ( {} ) ,
}
) ;
从存储读取以访问持久化的用户偏好: import * as z from "zod" ;
import { createAgent , tool , type ToolRuntime } from "langchain" ;
const contextSchema = z . object ( {
userId : z . string () ,
} ) ;
const getPreference = tool (
async ({ preferenceKey }, runtime : ToolRuntime ) => {
const userId = runtime . context . userId ;
// 从存储读取:获取现有偏好
const store = runtime . store ;
const existingPrefs = await store . get ([ "preferences" ] , userId) ;
if (existingPrefs) {
const value = existingPrefs . value ?. [preferenceKey] ;
return value ? ` ${ preferenceKey } : ${ value } ` : `No preference set for ${ preferenceKey } ` ;
} else {
return "No preferences found" ;
}
},
{
name : "get_preference" ,
description : "Get user preference from Store" ,
schema : z . object ( {
preferenceKey : z . string () ,
} ) ,
}
) ;
从运行时上下文读取配置,如 API 密钥和用户 ID: import * as z from "zod" ;
import { tool } from "@langchain/core/tools" ;
import { createAgent } from "langchain" ;
const contextSchema = z . object ( {
userId : z . string () ,
apiKey : z . string () ,
dbConnection : z . string () ,
} ) ;
const fetchUserData = tool (
async ({ query }, runtime : ToolRuntime < any , typeof contextSchema > ) => {
// 从运行时上下文读取:获取 API 密钥和数据库连接
const { userId , apiKey , dbConnection } = runtime . context ;
// 使用配置获取数据
const results = await performDatabaseQuery (dbConnection , query , apiKey) ;
return `Found ${ results . length } results for user ${ userId } ` ;
},
{
name : "fetch_user_data" ,
description : "Fetch data using Runtime Context configuration" ,
schema : z . object ( {
query : z . string () ,
} ) ,
}
) ;
const agent = createAgent ( {
model : "gpt-5.4" ,
tools : [fetchUserData] ,
contextSchema ,
} ) ;
工具结果可以用来帮助智能体完成给定的任务。工具既可以直接向模型返回结果,也可以更新智能体的记忆,使重要上下文可用于未来的步骤。
使用 Command 写入状态以跟踪会话特定信息: import * as z from "zod" ;
import { tool } from "@langchain/core/tools" ;
import { createAgent } from "langchain" ;
import { Command } from "@langchain/langgraph" ;
const authenticateUser = tool (
async ({ password }) => {
// 执行认证
if (password === "correct" ) {
// 写入状态:使用 Command 标记为已认证
return new Command ( {
update : { authenticated : true },
} ) ;
} else {
return new Command ( { update : { authenticated : false } } ) ;
}
},
{
name : "authenticate_user" ,
description : "Authenticate user and update State" ,
schema : z . object ( {
password : z . string () ,
} ) ,
}
) ;
写入存储以跨会话持久化数据: import * as z from "zod" ;
import { createAgent , tool , type ToolRuntime } from "langchain" ;
const savePreference = tool (
async ({ preferenceKey , preferenceValue }, runtime : ToolRuntime < any , typeof contextSchema > ) => {
const userId = runtime . context . userId ;
// 读取现有偏好
const store = runtime . store ;
const existingPrefs = await store . get ([ "preferences" ] , userId) ;
// 与新偏好合并
const prefs = existingPrefs ?. value || {};
prefs[preferenceKey] = preferenceValue ;
// 写入存储:保存更新后的偏好
await store . put ([ "preferences" ] , userId , prefs) ;
return `Saved preference: ${ preferenceKey } = ${ preferenceValue } ` ;
},
{
name : "save_preference" ,
description : "Save user preference to Store" ,
schema : z . object ( {
preferenceKey : z . string () ,
preferenceValue : z . string () ,
} ) ,
}
) ;
有关在工具中访问状态、存储和运行时上下文的完整示例,请参阅工具 。
生命周期上下文
控制核心智能体步骤之间 发生的事情——拦截数据流以实现横切关注点,如摘要、护栏和日志记录。
正如你在模型上下文 和工具上下文 中看到的,中间件 是使上下文工程变得实用的机制。中间件允许你钩入智能体生命周期的任何步骤,并执行以下操作之一:
更新上下文 - 修改状态和存储以持久化更改、更新对话历史或保存洞察
在生命周期中跳转 - 根据上下文移动到智能体循环的不同步骤(例如,如果满足条件则跳过工具执行,使用修改后的上下文重复模型调用)
示例:摘要
最常见的生命周期模式之一是在对话历史变得太长时自动压缩。与模型上下文 中展示的瞬态消息裁剪不同,摘要持久更新状态 ——用为所有未来轮次保存的摘要永久替换旧消息。
LangChain 为此提供了内置中间件:
import { createAgent , summarizationMiddleware } from "langchain" ;
const agent = createAgent ( {
model : "gpt-5.4" ,
tools : [ ... ] ,
middleware : [
summarizationMiddleware ( {
model : "gpt-5.4-mini" ,
trigger : { tokens : 4000 },
keep : { messages : 20 },
} ) ,
] ,
} ) ;
当对话超过 Token 限制时,SummarizationMiddleware 会自动:
使用单独的 LLM 调用来总结较旧的消息
用摘要消息替换状态中的旧消息(永久替换)
保持最近的消息完整以提供上下文
总结后的对话历史会被永久更新——未来的轮次将看到摘要而不是原始消息。
有关内置中间件的完整列表、可用钩子以及如何创建自定义中间件,请参阅中间件文档 。
最佳实践
从简单开始 - 先使用静态提示词和工具,仅在需要时添加动态功能
增量测试 - 一次添加一个上下文工程功能
监控性能 - 跟踪模型调用、Token 使用量和延迟
使用内置中间件 - 利用 SummarizationMiddleware 、LLMToolSelectorMiddleware 等
记录你的上下文策略 - 明确说明正在传递什么上下文以及原因
理解瞬态与持久 :模型上下文更改是瞬态的(每次调用),而生命周期上下文更改会持久化到状态
相关资源
将这些文档连接 到 Claude、VSCode 等工具,通过 MCP 获取实时答案。