正在使用 AI 编程助手?
- 安装 LangChain 文档 MCP 服务器,让你的智能体能够访问最新的 LangChain 文档和示例。
- 安装 LangChain Skills 来提升你的智能体在 LangChain 生态系统任务上的表现。
安装依赖
安装以下包以跟随教程:npm install deepagents langchain @langchain/core
# 需要 Node.js 20+
pnpm add deepagents langchain @langchain/core
# 需要 Node.js 20+
yarn add deepagents langchain @langchain/core
# 需要 Node.js 20+
bun add deepagents langchain @langchain/core
# 需要 Bun v1.0.0+
设置 API 密钥
从任何支持的模型提供商获取 API 密钥(例如 Google Gemini 或 OpenAI)。 设置 API 密钥,例如:- OpenAI
- Google Gemini
- Claude (Anthropic)
- OpenRouter
- Fireworks
- Baseten
- Ollama
- Azure
- AWS Bedrock
- HuggingFace
- 其他
export OPENAI_API_KEY="your-api-key"
export GOOGLE_API_KEY="your-api-key"
export ANTHROPIC_API_KEY="your-api-key"
export OPENROUTER_API_KEY="your-api-key"
export FIREWORKS_API_KEY="your-api-key"
export BASETEN_API_KEY="your-api-key"
# 本地:Ollama 必须正在运行 (https://ollama.com)
# 云端:设置你的 Ollama API 密钥用于托管推理
export OLLAMA_API_KEY="your-api-key"
export AZURE_OPENAI_API_KEY="your-api-key"
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com"
export AZURE_OPENAI_DEPLOYMENT_NAME="your-deployment"
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_REGION="us-east-1"
export HUGGINGFACEHUB_API_TOKEN="hf_..."
查看完整的聊天模型集成列表。
构建基础智能体
首先创建一个可以回答问题和调用工具的简单智能体。本示例中的智能体使用选定的语言模型、一个基础天气函数作为工具,以及一个简单的提示词来指导其行为:import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `${input.city} 永远阳光明媚!`,
{
name: "get_weather",
description: "Get the weather for a given city",
schema: z.object({
city: z.string().describe("The city to get the weather for"),
}),
}
);
const agent = createAgent({
model: "gpt-5.4",
tools: [getWeather],
});
console.log(
await agent.invoke({
messages: [{ role: "user", content: "旧金山的天气怎么样?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `${input.city} 永远阳光明媚!`,
{
name: "get_weather",
description: "Get the weather for a given city",
schema: z.object({
city: z.string().describe("The city to get the weather for"),
}),
}
);
const agent = createAgent({
model: "google-genai:gemini-2.5-flash-lite",
tools: [getWeather],
});
console.log(
await agent.invoke({
messages: [{ role: "user", content: "旧金山的天气怎么样?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `${input.city} 永远阳光明媚!`,
{
name: "get_weather",
description: "Get the weather for a given city",
schema: z.object({
city: z.string().describe("The city to get the weather for"),
}),
}
);
const agent = createAgent({
model: "claude-sonnet-4-6",
tools: [getWeather],
});
console.log(
await agent.invoke({
messages: [{ role: "user", content: "旧金山的天气怎么样?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `${input.city} 永远阳光明媚!`,
{
name: "get_weather",
description: "Get the weather for a given city",
schema: z.object({
city: z.string().describe("The city to get the weather for"),
}),
}
);
const agent = createAgent({
model: "openrouter:anthropic/claude-sonnet-4-6",
tools: [getWeather],
});
console.log(
await agent.invoke({
messages: [{ role: "user", content: "旧金山的天气怎么样?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `${input.city} 永远阳光明媚!`,
{
name: "get_weather",
description: "Get the weather for a given city",
schema: z.object({
city: z.string().describe("The city to get the weather for"),
}),
}
);
const agent = createAgent({
model: "fireworks:accounts/fireworks/models/qwen3p5-397b-a17b",
tools: [getWeather],
});
console.log(
await agent.invoke({
messages: [{ role: "user", content: "旧金山的天气怎么样?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `${input.city} 永远阳光明媚!`,
{
name: "get_weather",
description: "Get the weather for a given city",
schema: z.object({
city: z.string().describe("The city to get the weather for"),
}),
}
);
const agent = createAgent({
model: "baseten:zai-org/GLM-5",
tools: [getWeather],
});
console.log(
await agent.invoke({
messages: [{ role: "user", content: "旧金山的天气怎么样?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `${input.city} 永远阳光明媚!`,
{
name: "get_weather",
description: "Get the weather for a given city",
schema: z.object({
city: z.string().describe("The city to get the weather for"),
}),
}
);
const agent = createAgent({
model: "ollama:devstral-2",
tools: [getWeather],
});
console.log(
await agent.invoke({
messages: [{ role: "user", content: "旧金山的天气怎么样?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `${input.city} 永远阳光明媚!`,
{
name: "get_weather",
description: "Get the weather for a given city",
schema: z.object({
city: z.string().describe("The city to get the weather for"),
}),
}
);
const agent = createAgent({
model: "azure_openai:gpt-5.4",
tools: [getWeather],
});
console.log(
await agent.invoke({
messages: [{ role: "user", content: "旧金山的天气怎么样?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `${input.city} 永远阳光明媚!`,
{
name: "get_weather",
description: "Get the weather for a given city",
schema: z.object({
city: z.string().describe("The city to get the weather for"),
}),
}
);
const agent = createAgent({
model: "bedrock:gpt-5.4",
tools: [getWeather],
});
console.log(
await agent.invoke({
messages: [{ role: "user", content: "旧金山的天气怎么样?" }],
})
);
构建实际应用智能体
在以下示例中,你将构建一个可以回答关于文本文件问题的研究智能体。 在此过程中,你将探索以下概念:- 详细的系统提示词以获得更好的智能体行为
- 创建工具与外部数据集成
- 模型配置以获得一致的响应
- 对话记忆用于类聊天交互
- 深度智能体提供内置功能
- 测试你的智能体
1
定义系统提示词
系统提示词定义了你的智能体的角色和行为。保持具体且可操作:
const SYSTEM_PROMPT = `You are a literary data assistant.
## Capabilities
- \`fetch_text_from_url\`: loads document text from a URL into the conversation.
Do not guess line counts or positions—ground them in tool results from the saved file.`;
2
创建工具
工具让模型通过调用你定义的函数来与外部系统交互。
工具可以依赖运行时上下文,也可以与智能体记忆交互。本示例使用一个工具从给定 URL 加载文档:
import { tool } from "@langchain/core/tools";
import { createAgent, initChatModel } from "langchain";
import { z } from "zod";
const fetchTextFromUrl = tool(
async ({ url }: { url: string }): Promise<string> => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 120_000);
try {
const resp = await fetch(url, {
headers: {
"User-Agent": "Mozilla/5.0 (compatible; quickstart-research/1.0)",
},
signal: controller.signal,
});
if (!resp.ok) {
return `获取失败: HTTP ${resp.status} ${resp.statusText}`;
}
return await resp.text();
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
return `获取失败: ${msg}`;
} finally {
clearTimeout(timeoutId);
}
},
{
name: "fetch_text_from_url",
description: "Fetch the document from a URL.",
schema: z.object({ url: z.string().url() }),
},
);
Zod 是一个用于验证和解析预定义模式的库。你可以用它来定义工具的输入模式,确保智能体只使用正确的参数调用工具。或者,你也可以将
schema 属性定义为 JSON schema 对象。请注意,JSON schema 不会在运行时进行验证。示例:使用 JSON schema 作为工具输入
示例:使用 JSON schema 作为工具输入
import { tool } from "@langchain/core/tools";
const fetchTextFromUrl = tool(
async ({ url }: { url: string }): Promise<string> => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 120_000);
try {
const resp = await fetch(url, {
headers: {
"User-Agent": "Mozilla/5.0 (compatible; quickstart-research/1.0)",
},
signal: controller.signal,
});
if (!resp.ok) {
return `获取失败: HTTP ${resp.status} ${resp.statusText}`;
}
return await resp.text();
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
return `获取失败: ${msg}`;
} finally {
clearTimeout(timeoutId);
}
},
{
name: "fetch_text_from_url",
description: "Fetch the document from a URL.",
schema: {
type: "object",
properties: {
url: {
type: "string",
description: "The URL of the document to fetch.",
format: "uri",
},
},
required: ["url"],
},
},
);
3
配置你的模型
根据你的使用场景设置语言模型的适当参数。例如:根据所选的模型和提供商,初始化参数可能有所不同;请参考其参考页面了解详情。
import { initChatModel } from "langchain";
const model = await initChatModel("gpt-5.4", {
temperature: 0.5,
timeout: 300,
maxTokens: 25000,
});
import { initChatModel } from "langchain";
const model = await initChatModel("gemini-3.1-pro-preview", {
modelProvider: "google-genai",
temperature: 0.5,
timeout: 600_000,
maxTokens: 25000,
});
import { initChatModel } from "langchain";
const model = await initChatModel("claude-sonnet-4-6", {
temperature: 0.5,
timeout: 300,
maxTokens: 25000,
});
import { initChatModel } from "langchain";
const model = await initChatModel("openrouter:anthropic/claude-sonnet-4-6", {
temperature: 0.5,
timeout: 300,
maxTokens: 25000,
});
import { initChatModel } from "langchain";
const model = await initChatModel(
"fireworks:accounts/fireworks/models/qwen3p5-397b-a17b",
{ temperature: 0.5, timeout: 300, maxTokens: 25000 }
);
import { initChatModel } from "langchain";
const model = await initChatModel("baseten:zai-org/GLM-5", {
temperature: 0.5,
timeout: 300,
maxTokens: 25000,
});
import { initChatModel } from "langchain";
const model = await initChatModel("ollama:devstral-2", {
temperature: 0.5,
timeout: 300,
maxTokens: 25000,
});
import { initChatModel } from "langchain";
const model = await initChatModel("azure_openai:gpt-5.4", {
temperature: 0.5,
timeout: 300,
maxTokens: 25000,
});
import { initChatModel } from "langchain";
const model = await initChatModel("bedrock:gpt-5.4", {
temperature: 0.5,
timeout: 300,
maxTokens: 25000,
});
4
5
创建并运行智能体
现在组装你的智能体的所有组件并运行它。有两种不同的框架用于创建智能体:LangChain 智能体和深度智能体。
LangChain 智能体和深度智能体都为你提供对工具、记忆等的细粒度控制。
两者的主要区别在于,深度智能体内置了一系列常用功能,如规划、文件系统工具和子智能体。当你想要以最少的设置获得最大能力时使用深度智能体;当你需要细粒度控制时选择 LangChain 智能体。让我们两种都试试:
由于代码使用《了不起的盖茨比》的全文调用模型,它会使用大量的 Token。你可以在下一步查看示例输出。
async function main() {
const agent = createAgent({
model,
tools: [fetchTextFromUrl],
systemPrompt: SYSTEM_PROMPT,
checkpointer,
});
const deepAgent = createDeepAgent({
model,
tools: [fetchTextFromUrl],
systemPrompt: SYSTEM_PROMPT,
checkpointer,
});
const content = `Project Gutenberg hosts a full plain-text copy of F. Scott Fitzgerald's The Great Gatsby.
URL: https://www.gutenberg.org/files/64317/64317-0.txt
Answer as much as you can:
1) How many lines in the complete Gutenberg file contain the substring \`Gatsby\` (count lines, not occurrences within a line, each line ends with a line break).
2) The 1-based line number of the first line in the file that contains \`Daisy\`.
3) A two-sentence neutral synopsis.
Do your best on (1) and (2). If at any point you realize you cannot **verify** an exact answer with
your available tools and reasoning, do not fabricate numbers: use \`null\` for that field and spell out
the limitation in \`how_you_computed_counts\`. If you encounter any errors please report what the error was and what the error message was.`;
const agentResult = await agent.invoke(
{ messages: [{ role: "user", content }] },
{ configurable: { thread_id: "great-gatsby-lc" } },
);
const deepAgentResult = await deepAgent.invoke(
{ messages: [{ role: "user", content }] },
{ configurable: { thread_id: "great-gatsby-da" } },
);
const agentMessages = agentResult.messages;
const deepMessages = deepAgentResult.messages;
console.log(agentMessages[agentMessages.length - 1]!.content_blocks);
console.log("\n");
console.log(deepMessages[deepMessages.length - 1]!.content_blocks);
}
main().catch((err) => {
console.error(err);
process.exitCode = 1;
});
Show 完整示例代码
Show 完整示例代码
import { MemorySaver } from "@langchain/langgraph";
import { createDeepAgent } from "deepagents";
import { tool } from "@langchain/core/tools";
import { createAgent, initChatModel } from "langchain";
import { z } from "zod";
const SYSTEM_PROMPT = `You are a literary data assistant.
## Capabilities
- \`fetch_text_from_url\`: loads document text from a URL into the conversation.
Do not guess line counts or positions—ground them in tool results from the saved file.`;
const fetchTextFromUrl = tool(
async ({ url }: { url: string }): Promise<string> => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 120_000);
try {
const resp = await fetch(url, {
headers: {
"User-Agent": "Mozilla/5.0 (compatible; quickstart-research/1.0)",
},
signal: controller.signal,
});
if (!resp.ok) {
return `获取失败: HTTP ${resp.status} ${resp.statusText}`;
}
return await resp.text();
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
return `获取失败: ${msg}`;
} finally {
clearTimeout(timeoutId);
}
},
{
name: "fetch_text_from_url",
description: "Fetch the document from a URL.",
schema: z.object({ url: z.string().url() }),
},
);
const model = await initChatModel("gemini-3.1-pro-preview", {
modelProvider: "google-genai",
temperature: 0.5,
timeout: 600_000,
maxTokens: 25000,
streaming: true,
});
const checkpointer = new MemorySaver();
async function main() {
const agent = createAgent({
model,
tools: [fetchTextFromUrl],
systemPrompt: SYSTEM_PROMPT,
checkpointer,
});
const deepAgent = createDeepAgent({
model,
tools: [fetchTextFromUrl],
systemPrompt: SYSTEM_PROMPT,
checkpointer,
});
const content = `Project Gutenberg hosts a full plain-text copy of F. Scott Fitzgerald's The Great Gatsby.
URL: https://www.gutenberg.org/files/64317/64317-0.txt
Answer as much as you can:
1) How many lines in the complete Gutenberg file contain the substring \`Gatsby\` (count lines, not occurrences within a line, each line ends with a line break).
2) The 1-based line number of the first line in the file that contains \`Daisy\`.
3) A two-sentence neutral synopsis.
Do your best on (1) and (2). If at any point you realize you cannot **verify** an exact answer with
your available tools and reasoning, do not fabricate numbers: use \`null\` for that field and spell out
the limitation in \`how_you_computed_counts\`. If you encounter any errors please report what the error was and what the error message was.`;
const agentResult = await agent.invoke(
{ messages: [{ role: "user", content }] },
{ configurable: { thread_id: "great-gatsby-lc" } },
);
const deepAgentResult = await deepAgent.invoke(
{ messages: [{ role: "user", content }] },
{ configurable: { thread_id: "great-gatsby-da" } },
);
const agentMessages = agentResult.messages;
const deepMessages = deepAgentResult.messages;
console.log(agentMessages[agentMessages.length - 1]!.content_blocks);
console.log("\n");
console.log(deepMessages[deepMessages.length - 1]!.content_blocks);
}
main().catch((err) => {
console.error(err);
process.exitCode = 1;
});
6
查看结果
结果会因模型和执行情况而异。如果你查看两个标签页的输出,你会注意到 LangChain 智能体提供了答案但它们是估计值。该智能体缺乏回答此问题的工具。你也可能收到提示词过长的错误。另一方面,深度智能体可以:
- LangChain 智能体
- 深度智能体
**1) 包含 `Gatsby` 的行数:** `null`
**2) 包含 `Daisy` 的第一行:** `null`
**3) 概要:**
The Great Gatsby follows the mysterious millionaire Jay Gatsby and his obsession with reuniting with his former lover, Daisy Buchanan, as narrated by his neighbor Nick Carraway. Set against the backdrop of the Roaring Twenties on Long Island, the novel explores themes of wealth, class, and the elusive nature of the American Dream.
**how_you_computed_counts:**
I successfully fetched the full text of the eBook using the `fetch_text_from_url` tool. However, because I do not have access to a code execution environment (like Python) or text-processing tools (like `grep`), I cannot deterministically split the text by line breaks, iterate through the thousands of lines, and verify the exact line numbers or match counts. LLMs cannot reliably perform exact line-counting or indexing over massive texts within their context window without external computational tools. As instructed, rather than fabricating or guessing a number, I have output `null` for the exact counts and positions.
Based on the text fetched directly from the Gutenberg URL and analyzed using filesystem search tools, here are the answers to your questions:
**1) Lines containing the substring `Gatsby`**
**258** lines contain the exact substring `Gatsby`.
**2) First line containing `Daisy`**
Line **181** is the first line in the file that contains the exact substring `Daisy`.
*(For context, the line reads: "Buchanans. Daisy was my second cousin once removed, and I'd known Tom")*
**3) Two-sentence neutral synopsis**
*The Great Gatsby* follows the mysterious millionaire Jay Gatsby and his obsessive pursuit to reunite with his former lover, Daisy Buchanan, in 1920s Long Island. The story is narrated by Nick Carraway, who observes the tragic consequences of Gatsby's relentless ambition and the shallow materialism of the era's wealthy elite.
***
**How counts were computed:**
When fetching the document from the URL, the file was too large for the standard output and was automatically saved to the local filesystem by the system (`/large_tool_results/x246ax2x`). I then used the `grep` tool to search the saved file for the exact literal substrings `Gatsby` and `Daisy`. The `grep` tool returned every matching line along with its 1-based line number. I manually counted the exact number of lines returned for `Gatsby` (which totaled 258) and identified the first line number returned for `Daisy` (which was 181). I also verified there were no uppercase variations (`GATSBY` or `DAISY`) that would have been missed. No errors were encountered during this process.
- 规划方法,使用内置的
write_todos工具分解研究任务。 - 加载文件,通过调用
fetch_text_from_url工具收集信息。 - 管理上下文,通过使用文件系统工具(
grep和read_file)。 - 生成子智能体,根据需要将复杂子任务委派给专门的子智能体。
追踪智能体调用
你使用 LangChain 构建的大多数有趣应用都会对 LLM 进行多次调用。随着这些应用变得更加复杂,能够检查智能体内部到底发生了什么变得越来越重要。最好的方法是使用 LangSmith。 注册一个 LangSmith 账户并设置以下内容开始记录追踪:export LANGSMITH_TRACING="true"
export LANGSMITH_API_KEY="..."
要了解更多关于使用 LangSmith 追踪智能体的信息,请参阅 LangSmith 文档。
下一步
你现在拥有可以:- 理解上下文并记住对话
- 智能使用工具
- 以一致的格式提供结构化响应
- 通过上下文处理用户特定信息
- 在交互之间维护对话状态
- 规划、研究和综合(仅限深度智能体)
连接这些文档到 Claude、VSCode 等,通过 MCP 获取实时答案。

