本页还没有译文
本页 137 段还没译成日本語,下面显示的是英文原文。LangChain v1 migration guide
还没翻译译自英文(docs.langchain.com)本页 137 段都还没译
Migrate a codebase to LangChain v1.
Migrate this codebase to LangChain v1 (requires langchain and @langchain/core at v1, and Node.js 22+).
Key changes:
createReactAgent→createAgent: replaceimport { createReactAgent } from "@langchain/langgraph/prebuilts"withimport { createAgent } from "langchain". RenameprompttosystemPrompt.- Hooks become middleware: replace
preModelHook/postModelHookcustomization with middleware usingbeforeModel,afterModel, andwrapToolCall. For human-in-the-loop tool approval, usehumanInTheLoopMiddleware({ interruptOn: {...} })fromlangchain. - Structured output: keep
responseFormat, but usetoolStrategy/providerStrategy. Prompted output is removed. - Streaming node name: when filtering or matching streamed events by node name, rename
"agent"to"model". - Runtime context: pass static context via the
contextproperty instead of onlyconfig.configurable. - Package namespace: legacy chains, indexing, and community re-exports moved to
@langchain/classic. Install@langchain/classicand update those imports. - Standard content blocks: prefer
message.contentBlocksfor provider-agnostic content. Existingmessage.contentremains valid.
Search the codebase for createReactAgent, @langchain/langgraph/prebuilts, preModelHook, postModelHook, and legacy imports that should move to @langchain/classic, and apply the necessary changes. Flag anything that cannot be migrated automatically.
This migration guide outlines the major changes in LangChain v1. To learn more about the new features of v1, see the introductory post.
To upgrade,
npm install langchain@latest @langchain/core@latestpnpm install langchain@latest @langchain/core@latestyarn add langchain@latest @langchain/core@latestbun add langchain@latest @langchain/core@latestcreateAgent
In v1, the react agent prebuilt is now in the langchain package. The table below outlines what functionality has changed:
| Section | What changed |
|---|---|
| Import path | Package moved from @langchain/langgraph/prebuilts to langchain |
| Prompts | Parameter renamed to systemPrompt, dynamic prompts use middleware |
| Pre-model hook | Replaced by middleware with beforeModel method |
| Post-model hook | Replaced by middleware with afterModel method |
| Custom state | Defined in middleware, zod objects only |
| Model | Dynamic selection via middleware, pre-bound models not supported |
| Tools | Tool error handling moved to middleware with wrapToolCall |
| Structured output | prompted output removed, use toolStrategy/providerStrategy |
| Streaming node name | Node name changed from "agent" to "model" |
| Runtime context | context property instead of config.configurable |
| Namespace | Streamlined to focus on agent building blocks, legacy code moved to @langchain/classic |
Import path
The import path for the react agent prebuilt has changed from @langchain/langgraph/prebuilts to langchain. The name of the function has changed from createReactAgent to createAgent:
import { createReactAgent } from "@langchain/langgraph/prebuilts";
import { createAgent } from "langchain";Prompts
Static prompt rename
The prompt parameter has been renamed to systemPrompt:
import { createAgent } from "langchain";
agent = createAgent({
model,
tools,
systemPrompt: "You are a helpful assistant.", // [!code highlight]
});import { createReactAgent } from "@langchain/langgraph/prebuilts";
const agent = createReactAgent({
model,
tools,
prompt: "You are a helpful assistant.", // [!code highlight]
});SystemMessage
If using SystemMessage objects in the system prompt, the string content is now used directly:
import { SystemMessage, createAgent } from "langchain";
const agent = createAgent({
model,
tools,
systemPrompt: "You are a helpful assistant.", // [!code highlight]
});import { createReactAgent } from "@langchain/langgraph/prebuilts";
const agent = createReactAgent({
model,
tools,
prompt: new SystemMessage(content: "You are a helpful assistant."), // [!code highlight]
});Dynamic prompts
Dynamic prompts are a core context engineering pattern—they adapt what you tell the model based on the current conversation state. To do this, use dynamicSystemPromptMiddleware:
import { createAgent, dynamicSystemPromptMiddleware } from "langchain";
import * as z from "zod";
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",
},
}
);import { createReactAgent } from "@langchain/langgraph/prebuilts";
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" },
},
}
);Pre-model hook
Pre-model hooks are now implemented as middleware with the beforeModel method. This pattern is more extensible--you can define multiple middlewares to run before the model is called and reuse them across agents.
Common use cases include:
- Summarizing conversation history
- Trimming messages
- Input guardrails, like PII redaction
v1 includes built-in summarization middleware:
import { createAgent, summarizationMiddleware } from "langchain";
const agent = createAgent({
model: "claude-sonnet-4-6",
tools,
middleware: [
summarizationMiddleware({
model: "claude-sonnet-4-6",
trigger: { tokens: 1000 },
}),
],
});import { createReactAgent } from "@langchain/langgraph/prebuilts";
function customSummarization(state) {
// Custom logic for message summarization
}
const agent = createReactAgent({
model: "claude-sonnet-4-6",
tools,
preModelHook: customSummarization,
});Post-model hook
Post-model hooks are now implemented as middleware with the afterModel method. This lets you compose multiple handlers after the model responds.
Common use cases include:
- Human-in-the-loop approval
- Output guardrails
v1 includes a built-in human-in-the-loop middleware:
import { createAgent, humanInTheLoopMiddleware } from "langchain";
const agent = createAgent({
model: "claude-sonnet-4-6",
tools: [readEmail, sendEmail],
middleware: [
humanInTheLoopMiddleware({
interruptOn: {
sendEmail: { allowedDecisions: ["approve", "edit", "reject"] },
},
}),
],
});import { createReactAgent } from "@langchain/langgraph/prebuilts";
function customHumanInTheLoopHook(state) {
// Custom approval logic
}
const agent = createReactAgent({
model: "claude-sonnet-4-6",
tools: [readEmail, sendEmail],
postModelHook: customHumanInTheLoopHook,
});Custom state
Custom state is now defined in middleware using the stateSchema property. Use Zod to declare additional state fields that are carried through the agent run.
import * as z from "zod";
import { createAgent, createMiddleware, tool } from "langchain";
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",
});import { getCurrentTaskInput } from "@langchain/langgraph";
import { createReactAgent } from "@langchain/langgraph/prebuilts";
import * as z from "zod";
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,
});Model
Dynamic model selection now happens via middleware. Use wrapModelCall to swap models (and tools) based on state or runtime context. In createReactAgent, this was done via a function passed to the model parameter.
This functionality has been ported to the middleware interface in v1.
Dynamic model selection
import { createAgent, createMiddleware } from "langchain";
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],
});import { createReactAgent } from "@langchain/langgraph/prebuilts";
function selectModel(state) {
return state.messages.length > 10 ? "openai:gpt-5.5" : "openai:gpt-5-nano";
}
const agent = createReactAgent({
model: selectModel,
tools,
});Pre-bound models
To better support structured output, createAgent should receive a plain model (string or instance) and a separate tools list. Avoid passing models pre-bound with tools when using structured output.
// 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
The tools argument to createAgent accepts:
- Functions created with
tool - LangChain tool instances
- Objects that represent built-in provider tools
Handling tool errors
You can now configure the handling of tool errors with middleware implementing the wrapToolCall method.
import { createAgent, createMiddleware, ToolMessage } from "langchain";
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],
});import { createReactAgent, ToolNode } from "@langchain/langgraph/prebuilts";
const agent = createReactAgent({
model: "claude-sonnet-4-6",
tools: new ToolNode(
[checkWeather, searchWeb],
{ handleToolErrors: true } // [!code highlight]
),
});Structured output
Node changes
Structured output used to be generated in a separate node from the main agent. This is no longer the case. Structured output is generated in the main loop (no extra LLM call), reducing cost and latency.
Tool and provider strategies
In v1, there are two strategies:
toolStrategyuses artificial tool calling to generate structured outputproviderStrategyuses provider-native structured output generation
import { createAgent, toolStrategy } from "langchain";
import * as z from "zod";
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]
});import { createReactAgent } from "@langchain/langgraph/prebuilts";
import * as z from "zod";
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,
});Prompted output removed
Prompted output via custom instructions in responseFormat is removed in favor of the above strategies.
Streaming node name rename
When streaming events from agents, the node name was changed from "agent" to "model" to better reflect the node's purpose.
Runtime context
When invoking an agent, pass static, read-only configuration via the context config argument. This replaces patterns that used config.configurable.
import { createAgent, HumanMessage } from "langchain";
import * as z from "zod";
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]
);import { createReactAgent, HumanMessage } from "@langchain/langgraph/prebuilts";
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]
}
);Note
The old config.configurable pattern still works for backward compatibility, but using the new context parameter is recommended for new applications or applications migrating to v1.
Standard content
In v1, messages gain provider-agnostic standard content blocks. Access them via message.contentBlocks for a consistent, typed view across providers. The existing message.content field remains unchanged for strings or provider-native structures.
What changed
- New
contentBlocksproperty on messages for normalized content. - New TypeScript types under
ContentBlockfor strong typing. - Optional serialization of standard blocks into
contentviaLC_OUTPUT_VERSION=v1oroutputVersion: "v1".
Read standardized content
import { initChatModel } from "langchain";
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
}
}Create multimodal messages
import { HumanMessage } from "langchain";
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]);
import { HumanMessage } from "langchain";
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]);
Example block types
import { ContentBlock } from "langchain";
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",
};
See the content blocks reference for more details.
Serialize standard content
Standard content blocks are not serialized into the content attribute by default. If you need to access standard content blocks in the content attribute (e.g., when sending messages to a client), you can opt-in to serializing them into content.
export LC_OUTPUT_VERSION=v1import { initChatModel } from "langchain";
const model = await initChatModel("gpt-5-nano", {
outputVersion: "v1",
});Note
Learn more: Messages and Standard content blocks. See Multimodal for input examples.
Simplified package
The langchain package namespace is streamlined to focus on agent building blocks. Legacy functionality has moved to @langchain/classic. The new package exposes only the most useful and relevant functionality.
Exports
The v1 package includes:
| Module | What's available | Notes |
|---|---|---|
| Agents | createAgent, AgentState | Core agent creation functionality |
| Messages | Message types, content blocks, trimMessages | Re-exported from @langchain/core |
| Tools | tool, tool classes | Re-exported from @langchain/core |
| Chat models | initChatModel, BaseChatModel | Unified model initialization |
@langchain/classic
If you use legacy chains, the indexing API, or functionality previously re-exported from @langchain/community, install @langchain/classic and update imports:
npm install @langchain/classicpnpm install @langchain/classicyarn add @langchain/classic
bun add @langchain/classic
// v1 (new)
import { ... } from "@langchain/classic";
import { ... } from "@langchain/classic/chains";
// v0 (old)
import { ... } from "langchain";
import { ... } from "langchain/chains";
Breaking changes
Dropped Node 18 support
All LangChain packages now require Node.js 22 or higher. Node.js 18 reached end of life in March 2025.
New build outputs
Builds for all langchain packages now use a bundler based approach instead of using raw typescript outputs. If you were importing files from the dist/ directory (which is not recommended), you will need to update your imports to use the new module system.
Legacy code moved to @langchain/classic
Legacy functionality outside the focus of standard interfaces and agents has been moved to the @langchain/classic package. See the Simplified package section for details on what's available in the core langchain package and what moved to @langchain/classic.
Removal of deprecated APIs
Methods, functions, and other objects that were already deprecated and slated for removal in 1.0 have been deleted.