本迁移指南概述了 LangChain v1 中的主要变更。要了解 v1 的新功能,请参阅 介绍性文章.
要升级,
npm install langchain@latest @langchain/core@latest
pnpm install langchain@latest @langchain/core@latest
yarn add langchain@latest @langchain/core@latest
bun add langchain@latest @langchain/core@latest
createAgent
在 v1 中,react 预构建代理现在位于 langchain 包中。下表概述了哪些功能发生了变化:
| 部分 | 变更内容 |
|---|---|
| 导入路径 | 包从 @langchain/langgraph/prebuilts to langchain |
| 提示词 | 参数重命名为 systemPrompt,动态提示词使用中间件 |
| 模型前置钩子 | 由带有以下功能的中间件替换 beforeModel 方法 |
| 模型后置钩子 | 由带有以下功能的中间件替换 afterModel 方法 |
| 自定义状态 | 在中间件中定义,仅支持 zod 对象 |
| 模型 | 通过中间件动态选择,不支持预绑定模型 |
| 工具 | 工具错误处理移至中间件 |
| 结构化输出 | 提示输出已移除,请使用 toolStrategy/providerStrategy |
| 流式节点名称 | 节点名称从 "agent" to "model" |
| 运行时上下文 | context 属性替代 config.configurable |
| 命名空间 | 精简为专注于代理构建块,遗留代码移至 @langchain/classic |
导入路径
react 预构建代理的导入路径已从 @langchain/langgraph/prebuilts to langchain变更。函数名称已从 createReactAgent to createAgent:
提示词
静态提示词重命名
参数 prompt 已重命名为 systemPrompt:
agent = createAgent({
model,
tools,
systemPrompt: "You are a helpful assistant.", // [!code highlight]
});
const agent = createReactAgent({
model,
tools,
prompt: "You are a helpful assistant.", // [!code highlight]
});
SystemMessage
如果使用 SystemMessage 对象在系统提示词中,字符串内容现在直接使用:
const agent = createAgent({
model,
tools,
systemPrompt: "You are a helpful assistant.", // [!code highlight]
});
const agent = createReactAgent({
model,
tools,
prompt: new SystemMessage(content: "You are a helpful assistant."), // [!code highlight]
});
动态提示词
动态提示词是一种核心的上下文工程模式——它们根据当前对话状态调整告诉模型的内容。要实现这一点,请使用 dynamicSystemPromptMiddleware:
const contextSchema = z.object({
userRole: z.enum(["expert", "beginner"]).default("beginner"),
});
const userRolePrompt = dynamicSystemPromptMiddleware<z.infer<typeof contextSchema>>( // [!code highlight]
(_state, runtime) => {
const userRole = runtime.context.userRole;
const basePrompt = "You are a helpful assistant.";
if (userRole === "expert") {
return `${basePrompt} Provide detailed technical responses.`;
} else if (userRole === "beginner") {
return `${basePrompt} Explain concepts simply and avoid jargon.`;
}
return basePrompt; // [!code highlight]
}
);
const agent = createAgent({
model,
tools,
middleware: [userRolePrompt],
contextSchema,
});
await agent.invoke(
{
messages: [new HumanMessage("Explain async programming")],
},
{
context: {
userRole: "expert",
},
}
);
const contextSchema = z.object({
userRole: z.enum(["expert", "beginner"]),
});
const agent = createReactAgent({
model,
tools,
prompt: (state) => {
const userRole = state.context.userRole;
const basePrompt = "You are a helpful assistant.";
if (userRole === "expert") {
return `${basePrompt} Provide detailed technical responses.`;
} else if (userRole === "beginner") {
return `${basePrompt} Explain concepts simply and avoid jargon.`;
}
return basePrompt;
},
contextSchema,
});
// Use with context via config.configurable
await agent.invoke(
{
messages: [new HumanMessage("Explain async programming")],
},
{
config: {
configurable: { userRole: "expert" },
},
}
);
模型前置钩子
模型前置钩子现在作为中间件实现,使用 beforeModel 方法。这种模式更具可扩展性——你可以定义多个中间件在模型调用前运行,并可以在不同的代理之间复用。
常见用例包括: - 摘要对话历史 - 修剪消息 - 输入护栏,如 PII 删除
v1 包含内置的摘要中间件:
const agent = createAgent({
model: "claude-sonnet-4-6",
tools,
middleware: [
summarizationMiddleware({
model: "claude-sonnet-4-6",
trigger: { tokens: 1000 },
}),
],
});
function customSummarization(state) {
// Custom logic for message summarization
}
const agent = createReactAgent({
model: "claude-sonnet-4-6",
tools,
preModelHook: customSummarization,
});
模型后置钩子
后模型钩子现已实现为中间件, afterModel 方法。这允许您在模型响应后组合多个处理器。
常见用例包括: - 人工介入审批 - 输出护栏
v1 包含一个内置的人工介入中间件:
const agent = createAgent({
model: "claude-sonnet-4-6",
tools: [readEmail, sendEmail],
middleware: [
humanInTheLoopMiddleware({
interruptOn: {
sendEmail: { allowedDecisions: ["approve", "edit", "reject"] },
},
}),
],
});
function customHumanInTheLoopHook(state) {
// Custom approval logic
}
const agent = createReactAgent({
model: "claude-sonnet-4-6",
tools: [readEmail, sendEmail],
postModelHook: customHumanInTheLoopHook,
});
自定义状态
自定义状态现在在中间件中使用 stateSchema 属性定义。使用 Zod 声明在代理运行期间传递的附加状态字段。
const UserState = z.object({
userName: z.string(),
});
const userState = createMiddleware({
name: "UserState",
stateSchema: UserState,
beforeModel: (state) => {
// Access custom state properties
const name = state.userName;
// Optionally modify messages/system prompt based on state
return;
},
});
const greet = tool(
async () => {
return "Hello!";
},
{
name: "greet",
description: "Greet the user",
schema: z.object({}),
}
);
const agent = createAgent({
model: "claude-sonnet-4-6",
tools: [greet],
middleware: [userState],
});
await agent.invoke({
messages: [{ role: "user", content: "Hi" }],
userName: "Ada",
});
const UserState = z.object({
userName: z.string(),
});
const greet = tool(
async () => {
const state = await getCurrentTaskInput();
const userName = state.userName;
return `Hello ${userName}!`;
},
);
// Custom state was provided via agent-level state schema or accessed ad hoc in hooks
const agent = createReactAgent({
model: "claude-sonnet-4-6",
tools: [greet],
stateSchema: UserState,
});
模型
动态模型选择现在通过中间件进行。使用 wrapModelCall 根据状态或运行时上下文交换模型(和工具)。在 createReactAgent中,这是通过传递给 model parameter.
此功能已在 v1 中移植到中间件接口。
动态模型选择
const dynamicModel = createMiddleware({
name: "DynamicModel",
wrapModelCall: (request, handler) => {
const messageCount = request.state.messages.length;
const model = messageCount > 10 ? "openai:gpt-5.5" : "openai:gpt-5-nano";
return handler({ ...request, model });
},
});
const agent = createAgent({
model: "gpt-5-nano",
tools,
middleware: [dynamicModel],
});
function selectModel(state) {
return state.messages.length > 10 ? "openai:gpt-5.5" : "openai:gpt-5-nano";
}
const agent = createReactAgent({
model: selectModel,
tools,
});
预绑定模型
为了更好地支持结构化输出, createAgent 应接收一个普通模型(字符串或实例)和一个单独的 tools 列表。使用结构化输出时,避免传递预绑定工具的模型。
// No longer supported
// const modelWithTools = new ChatOpenAI({ model: "gpt-5.4-mini" }).bindTools([someTool]);
// const agent = createAgent({ model: modelWithTools, tools: [] });
// Use instead
const agent = createAgent({ model: "gpt-5.4-mini", tools: [someTool] });
工具
tools 参数到 createAgent accepts:
- - 使用创建的工具
tool - - LangChain 工具实例
- - 表示内置提供商工具的对象
处理工具错误
您现在可以使用实现中间件来配置工具错误处理 wrapToolCall method.
const handleToolErrors = createMiddleware({
name: "HandleToolErrors",
wrapToolCall: async (request, handler) => {
try {
return await handler(request);
} catch (error) {
// Only handle errors that occur during tool execution due to invalid inputs
// that pass schema validation but fail at runtime (e.g., invalid SQL syntax).
// Do NOT handle:
// - Network failures (use tool retry middleware instead)
// - Incorrect tool implementation errors (should bubble up)
// - Schema mismatch errors (already auto-handled by the framework)
//
// Return a custom error message to the model
return new ToolMessage({
content: `Tool error: Please check your input and try again. (${error})`,
tool_call_id: request.toolCall.id!,
});
}
},
});
const agent = createAgent({
model: "claude-sonnet-4-6",
tools: [checkWeather, searchWeb],
middleware: [handleToolErrors],
});
const agent = createReactAgent({
model: "claude-sonnet-4-6",
tools: new ToolNode(
[checkWeather, searchWeb],
{ handleToolErrors: true } // [!code highlight]
),
});
结构化输出
节点变更
结构化输出以前在独立于主代理的节点中生成。现在已不再如此。结构化输出在主循环中生成(无需额外的 LLM 调用),降低了成本和延迟。
工具和提供商策略
在 v1 中,有两种策略:
- -
toolStrategy使用人工工具调用来生成结构化输出 - -
providerStrategy使用提供商原生的结构化输出生成
const OutputSchema = z.object({
summary: z.string(),
sentiment: z.string(),
});
const agent = createAgent({
model: "gpt-5.4-mini",
tools,
// explicitly using tool strategy
responseFormat: toolStrategy(OutputSchema), // [!code highlight]
});
const OutputSchema = z.object({
summary: z.string(),
sentiment: z.string(),
});
const agent = createReactAgent({
model: "gpt-5.4-mini",
tools,
// Structured output was driven primarily via tool-calling with fewer options
responseFormat: OutputSchema,
});
已移除提示输出
通过中的自定义指令进行的提示输出 responseFormat 已被上述策略取代。
流式节点名称重命名
从代理流式传输事件时,节点名称已从 "agent" to "model" 更改为更好地反映节点的用途。
运行时上下文
调用代理时,通过 context 参数传递静态只读配置。这取代了使用 config.configurable.
const agent = createAgent({
model: "gpt-5.5",
tools,
contextSchema: z.object({ userId: z.string(), sessionId: z.string() }),
});
const result = await agent.invoke(
{ messages: [new HumanMessage("Hello")] },
{ context: { userId: "123", sessionId: "abc" } }, // [!code highlight]
);
const agent = createReactAgent({ model, tools });
// Pass context via config.configurable
const result = await agent.invoke(
{ messages: [new HumanMessage("Hello")] },
{
config: { // [!code highlight]
configurable: { userId: "123", sessionId: "abc" }, // [!code highlight]
}, // [!code highlight]
}
);
标准内容
在 v1 中,消息获得提供商无关的标准内容块。通过访问它们 message.contentBlocks 用于跨提供商的一致、类型化视图。现有 message.content 字段对于字符串或提供商原生结构保持不变。
发生了什么变化
- - 新增
contentBlocks消息上用于规范化内容的属性。 - - 下方的全新 TypeScript 类型
ContentBlock用于强类型支持。 - - 可选地将标准块序列化为
content通过LC_OUTPUT_VERSION=v1oroutputVersion: "v1".
读取标准化内容
const model = await initChatModel("gpt-5-nano");
const response = await model.invoke("Explain AI");
for (const block of response.contentBlocks) {
if (block.type === "reasoning") {
console.log(block.reasoning);
} else if (block.type === "text") {
console.log(block.text);
}
}
// Provider-native formats vary; you needed per-provider handling.
const response = await model.invoke("Explain AI");
for (const item of response.content as any[]) {
if (item.type === "reasoning") {
// OpenAI-style reasoning
} else if (item.type === "thinking") {
// Anthropic-style thinking
} else if (item.type === "text") {
// Text
}
}
创建多模态消息
const message = new HumanMessage({
contentBlocks: [
{ type: "text", text: "Describe this image." },
{ type: "image", url: "https://example.com/image.jpg" },
],
});
const res = await model.invoke([message]);
const message = new HumanMessage({
// Provider-native structure
content: [
{ type: "text", text: "Describe this image." },
{ type: "image_url", image_url: { url: "https://example.com/image.jpg" } },
],
});
const res = await model.invoke([message]);
示例块类型
const textBlock: ContentBlock.Text = {
type: "text",
text: "Hello world",
};
const imageBlock: ContentBlock.Multimodal.Image = {
type: "image",
url: "https://example.com/image.png",
mimeType: "image/png",
};
参见内容块 参考 了解更多详情。
序列化标准内容
标准内容块 **默认不序列化** 到 content 属性中。如果您需要在 content 属性中访问标准内容块(例如,向客户端发送消息时),您可以选择将它们序列化到 content.
const model = await initChatModel("gpt-5-nano", {
outputVersion: "v1",
});
简化的包
langchain 包命名空间已精简,专注于代理构建块。旧功能已移至 @langchain/classic。新包仅暴露最有用的相关功能。
导出
v1 包包含:
| 模块 | 可用内容 | 备注 |
|---|---|---|
| Agents(代理) | createAgent, AgentState | 核心代理创建功能 |
| Messages(消息) | 消息类型、内容块、 trimMessages | 从重新导出 @langchain/core |
| Tools(工具) | tool、工具类 | 从重新导出 @langchain/core |
| Chat models(聊天模型) | initChatModel, BaseChatModel | 统一模型初始化 |
@langchain/classic
如果您使用旧版链、索引 API 或之前从 @langchain/community重新导出的功能,请安装 @langchain/classic 并更新导入:
npm install @langchain/classic
pnpm install @langchain/classic
yarn add @langchain/classic
bun add @langchain/classic
// v1 (new)
// v0 (old)
破坏性变更
取消支持 Node 18
所有 LangChain 包现在需要 **Node.js 22 或更高版本**。Node.js 18 已于 停止维护 2025 年 3 月。
新的构建输出
所有 langchain 包的构建现在采用基于打包器的方法,而不是使用原始 TypeScript 输出。如果您之前从 dist/ 目录(不推荐这样做),你需要更新导入语句以使用新的模块系统。
旧代码已移至 @langchain/classic
标准接口和代理范围之外的旧功能已移至 @langchain/classic 包。请参阅 简化包 部分,了解核心 langchain 包中的可用内容以及移至 @langchain/classic.
已弃用API的移除
已在1.0版本中弃用并计划删除的方法、函数和其他对象已被删除。
View removed deprecated APIs
以下已弃用的API已在v1中移除:
#### 核心功能 - TraceGroup - 请改用LangSmith追踪 - BaseDocumentLoader.loadAndSplit - 请使用 .load() 后接文本分割器 - RemoteRunnable - 不再支持
#### 提示词 - BasePromptTemplate.serialize 和 .deserialize - 请直接使用JSON序列化 - ChatPromptTemplate.fromPromptMessages - 请使用 ChatPromptTemplate.fromMessages
#### 检索器 - BaseRetrieverInterface.getRelevantDocuments - 请使用 .invoke() 替代
#### 可运行对象 - Runnable.bind - 请使用 .bindTools() 或其他特定绑定方法 - Runnable.map - 请使用 .batch() 替代 - RunnableBatchOptions.maxConcurrency - 请使用 maxConcurrency 在配置对象中
#### 聊天模型 - BaseChatModel.predictMessages - 请使用 .invoke() 替代 - BaseChatModel.predict - 请使用 .invoke() 替代 - BaseChatModel.serialize - 请直接使用JSON序列化 - BaseChatModel.callPrompt - 请使用 .invoke() 替代 - BaseChatModel.call - 请使用 .invoke() 替代
#### 大语言模型 - BaseLLMParams.concurrency - 请使用 maxConcurrency 在配置对象中 - BaseLLM.call - 请使用 .invoke() 替代 - BaseLLM.predict - 请使用 .invoke() 替代 - BaseLLM.predictMessages - 请使用 .invoke() 替代 - BaseLLM.serialize - 请直接使用JSON序列化
#### 流式传输 - createChatMessageChunkEncoderStream - 请使用 .stream() 方法直接
#### 追踪 - BaseTracer.runMap - 请使用LangSmith追踪API - getTracingCallbackHandler - 请使用LangSmith追踪 - getTracingV2CallbackHandler - 请使用LangSmith追踪 - LangChainTracerV1 - 请使用LangSmith追踪
#### 内存和存储 - BaseListChatMessageHistory.addAIChatMessage - 请使用 .addMessage() 与 AIMessage - BaseStoreInterface - 使用特定的存储实现
#### 工具类 - getRuntimeEnvironmentSync - 使用异步 getRuntimeEnvironment()