正在使用 AI 编码助手?
- 安装 LangChain Docs 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 密钥
从任何受支持的模型提供商(例如,Google Gemini 或 OpenAI)获取 API 密钥。 设置 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) => `It's always sunny in ${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: "What's the weather in San Francisco?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `It's always sunny in ${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: "What's the weather in San Francisco?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `It's always sunny in ${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: "What's the weather in San Francisco?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `It's always sunny in ${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: "What's the weather in San Francisco?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `It's always sunny in ${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: "What's the weather in San Francisco?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `It's always sunny in ${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: "What's the weather in San Francisco?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `It's always sunny in ${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: "What's the weather in San Francisco?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `It's always sunny in ${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: "What's the weather in San Francisco?" }],
})
);
import { createAgent, tool } from "langchain";
import * as z from "zod";
const getWeather = tool(
(input) => `It's always sunny in ${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: "What's the weather in San Francisco?" }],
})
);
你可以通过更改代码中的模型名称并设置相应的 API 密钥来使用任何受支持的模型。
构建实际应用智能体
在接下来的示例中,你将构建一个研究智能体,它可以回答关于文本文件的问题。 在此过程中,你将探索以下概念:- 详细的系统提示,以改善智能体行为
- 创建工具,与外部数据集成
- 模型配置,以获得一致的响应
- 对话记忆,实现类似聊天的交互
- Deep Agents,提供内置功能
- 测试你的智能体
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 `Fetch failed: HTTP ${resp.status} ${resp.statusText}`;
}
return await resp.text();
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
return `Fetch failed: ${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";
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 `Fetch failed: HTTP ${resp.status} ${resp.statusText}`;
}
return await resp.text();
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
return `Fetch failed: ${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 智能体和 deep agents。
LangChain 和 deep agents 都为你提供了对工具、记忆等的细粒度控制。
两者的主要区别在于 deep agents 内置了一系列常用功能,例如规划、文件系统工具和子智能体。当你希望以最少的设置获得最大功能时,请使用 deep agents;当你需要细粒度控制时,请选择 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 `Fetch failed: HTTP ${resp.status} ${resp.statusText}`;
}
return await resp.text();
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
return `Fetch failed: ${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 智能体提供了答案,但它们是估计值。智能体缺乏回答此问题的工具。你也可能收到提示太长的错误。另一方面,deep agent 可以:
- LangChain agents
- Deep agents
**1) 包含 `Gatsby` 的行数:** `null`
**2) 包含 `Daisy` 的第一行:** `null`
**3) 概要:**
《了不起的盖茨比》讲述了神秘的百万富翁杰伊·盖茨比及其与前情人黛西·布坎南重聚的痴迷,由他的邻居尼克·卡拉韦叙述。故事背景设定在长岛的咆哮二十年代,小说探讨了财富、阶级以及美国梦的虚幻本质等主题。
**how_you_computed_counts:**
我成功使用 `fetch_text_from_url` 工具获取了电子书的全文。但是,由于我无法访问代码执行环境(如 Python)或文本处理工具(如 `grep`),我无法确定性地按换行符分割文本、遍历数千行并验证确切的行号或匹配计数。LLM 无法在没有外部计算工具的情况下,在其上下文窗口内可靠地对大量文本执行精确的行计数或索引。根据指示,我没有编造或猜测数字,而是为确切的计数和位置输出了 `null`。
根据直接从 Gutenberg URL 获取并使用文件系统搜索工具分析的文本,以下是您问题的答案:
**1) 包含子字符串 `Gatsby` 的行**
**258** 行包含精确子字符串 `Gatsby`。
**2) 包含 `Daisy` 的第一行**
第 **181** 行是文件中包含精确子字符串 `Daisy` 的第一行。
*(供参考,该行内容为:"Buchanans. Daisy was my second cousin once removed, and I’d known Tom")*
**3) 两句话的中立概要**
*《了不起的盖茨比》讲述了神秘的百万富翁杰伊·盖茨比在 1920 年代的长岛痴迷地追求与前情人黛西·布坎南重聚的故事。故事由尼克·卡拉韦叙述,他观察到了盖茨比无情野心的悲剧后果以及那个时代富有的精英阶层的浅薄物质主义。*
***
**计数是如何计算的:**
从 URL 获取文档时,文件太大无法通过标准输出显示,系统自动将其保存到本地文件系统(`/large_tool_results/x246ax2x`)。然后我使用 `grep` 工具在保存的文件中搜索精确的字面子字符串 `Gatsby` 和 `Daisy`。`grep` 工具返回了每个匹配行及其从 1 开始的行号。我手动计算了 `Gatsby` 返回的精确行数(总计 258 行),并确定了 `Daisy` 返回的第一个行号(即 181)。我还验证了没有大写变体(`GATSBY` 或 `DAISY`)会被遗漏。此过程中未遇到任何错误。
- 规划其方法,使用内置的
write_todos工具来分解研究任务。 - 加载文件,通过调用
fetch_text_from_url工具来收集信息。 - 管理上下文,使用文件系统工具(
grep和read_file)。 - 生成子智能体,根据需要将复杂的子任务委托给专门的子智能体。
跟踪智能体调用
你使用 LangChain 构建的大多数有趣的应用程序都会多次调用 LLM。随着这些应用程序变得越来越复杂,能够检查智能体内部到底发生了什么变得非常重要。最好的方法是使用 LangSmith。 注册一个 LangSmith 帐户并设置以下内容以开始记录跟踪:export LANGSMITH_TRACING="true"
export LANGSMITH_API_KEY="..."
要了解更多关于使用 LangSmith 跟踪智能体的信息,请参阅 LangSmith 文档。
后续步骤
你现在拥有的智能体可以:- 理解上下文并记住对话
- 智能地使用工具
- 以一致的格式提供结构化响应
- 通过上下文处理用户特定信息
- 在交互中维护对话状态
- 规划、研究和综合(仅限 deep agents)
将这些文档连接到 Claude、VSCode 等,通过 MCP 获取实时答案。

