快速入门
本快速入门演示如何使用 LangGraph Graph API 或 Functional API 构建一个计算器智能体。
构建 LangGraph 计算器快速入门:
按照 LangGraph 快速入门指南,在当前工作目录中构建一个 LangGraph 计算器智能体。
第 1 步:阅读指南
检测该项目使用的是 Python 还是 TypeScript/JavaScript。获取并遵循匹配的页面;将其作为包名、模型字符串和代码的权威来源:
- Python: https://docs.langchain.com/oss/python/langgraph/quickstart.md
- TypeScript: https://docs.langchain.com/oss/javascript/langgraph/quickstart.md
询问用户使用 Graph API 还是 Functional API。如果用户没有偏好,请使用 Graph API 路径。
第 2 步:安装依赖项
使用该项目中已使用的包管理器安装所选路径所需的包。
第 3 步:配置模型凭据
本快速入门默认使用 Anthropic。检查是否设置了 ANTHROPIC_API_KEY。如果未设置,请提示用户创建密钥并在 Shell 或 .env 文件中进行设置,然后暂停并等待确认。切勿捏造、硬编码或提交 API 密钥。如果用户偏好集成文档中的其他聊天模型提供商,请在确认后相应调整示例。
第 4 步:实现计算器智能体
端到端实现所选的快速入门路径:加法、乘法和除法工具;智能体图或函数式工作流;以及演练工具调用的调用示例。打印最终结果,以便用户验证运行。
规则
- 保持在本次快速入门的范围内。除非用户要求,否则请勿添加部署、评估或无关框架。
- 优先使用所获取指南中显示的 API 和结构,而不是发明不同的智能体模式。
- 当密钥、API 选择或项目约定不明确时,请主动询问而不是盲目猜测。
使用 AI 编程助手?
安装 LangChain 文档 MCP 服务器,以便你的智能体能够访问最新的 LangChain 文档和示例。
连接 LangChain 文档 MCP 服务器: 将两个 LangChain 文档 MCP 服务器连接到我的编程智能体,以便其能够查阅最新的 LangChain、LangGraph 和 LangSmith 文档及 API 参考。
要添加的服务器:
docs-langchain: https://docs.langchain.com/mcpreference-langchain: https://reference.langchain.com/mcp
检测我使用的是哪个智能体或编辑器(Claude Code、Cursor、Codex CLI、Claude Desktop、Deep Agents Code、VS Code、Antigravity 或其他兼容 MCP 的客户端)。使用 https://docs.langchain.com/use-these-docs.md 中匹配的设置:
- Claude Code: 为每个服务器运行
claude mcp add --transport http(默认项目范围;仅当我要求全局访问时才使用--scope user)。 - Codex CLI: 运行
codex mcp add并附带每个服务器 URL。 - Cursor、Deep Agents Code、VS Code 或 Antigravity: 使用该页面上为我的客户端显示的字段名称,将两个条目合并到 MCP 设置 JSON 中。
- Claude Desktop: 在 Settings > Connectors 下添加两个 URL。
不要捏造其他 MCP URL。配置后,确认两个服务器均已列出且可访问。
安装 LangChain Skills 以提升你的智能体在 LangChain 生态系统任务上的表现。
安装 LangChain Skills: 为我的编程智能体安装 LangChain Skills,使其在 LangChain、LangGraph 和 Deep Agents 任务上表现更佳。
使用来自 https://github.com/langchain-ai/langchain-skills 的 Agent Skills 安装程序:
bashnpx skills add langchain-ai/langchain-skills --skill '*' --yes如果我要求全局安装,请使用:
bashnpx skills add langchain-ai/langchain-skills --skill '*' --yes --global检测我使用的是哪个智能体或编辑器。如果我使用 Claude Code 并且偏好插件路径,请遵循该仓库 README 中的市场安装(
/plugin marketplace add然后/plugin install)。不要捏造替代技能包名称或安装 URL。安装后,确认技能可供智能体使用。
- 如果你偏好将智能体定义为节点和边的图,请参阅使用 Graph API。
- 如果你偏好将智能体定义为单个函数,请参阅使用 Functional API。
有关概念信息,请参阅 Graph API 概览和 Functional API 概览。
INFO
对于此示例,你需要设置一个 Claude (Anthropic) 账户并获取 API 密钥。然后,在终端中设置 ANTHROPIC_API_KEY 环境变量。有关所有可用提供商,请参阅聊天模型集成。如果你使用 LangSmith Gateway,你可以自带提供商密钥或使用 Gateway 积分在没有提供商密钥的情况下访问模型。
使用 Graph API
1. 定义工具与模型
在此示例中,我们将使用 Claude Sonnet 4.5 模型,并定义加法、乘法和除法工具。
import { ChatAnthropic } from "@langchain/anthropic";
import { tool } from "@langchain/core/tools";
import * as z from "zod";
const model = new ChatAnthropic({
model: "claude-sonnet-4-6",
temperature: 0,
});
// 定义工具
const add = tool(({ a, b }) => a + b, {
name: "add",
description: "Add two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
const multiply = tool(({ a, b }) => a * b, {
name: "multiply",
description: "Multiply two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
const divide = tool(({ a, b }) => a / b, {
name: "divide",
description: "Divide two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
// 使用工具增强 LLM
const toolsByName = {
[add.name]: add,
[multiply.name]: multiply,
[divide.name]: divide,
};
const tools = Object.values(toolsByName);
const modelWithTools = model.bindTools(tools);2. 定义状态
图的状态用于存储消息和 LLM 调用次数。
TIP
LangGraph 中的状态在智能体的整个执行过程中保持持久化。
MessagesValue 提供了用于追加消息的内置 reducer。llmCalls 字段使用带有 (x, y) => x + y 的 ReducedValue 来累计计数。
import {
StateGraph,
StateSchema,
MessagesValue,
ReducedValue,
GraphNode,
ConditionalEdgeRouter,
START,
END,
} from "@langchain/langgraph";
import { z } from "zod/v4";
const MessagesState = new StateSchema({
messages: MessagesValue,
llmCalls: new ReducedValue(
z.number().default(0),
{ reducer: (x, y) => x + y }
),
});3. 定义模型节点
模型节点用于调用 LLM 并决定是否调用工具。
import { SystemMessage } from "@langchain/core/messages";
const llmCall: GraphNode<typeof MessagesState> = async (state) => {
const response = await modelWithTools.invoke([
new SystemMessage(
"You are a helpful assistant tasked with performing arithmetic on a set of inputs."
),
...state.messages,
]);
return {
messages: [response],
llmCalls: 1,
};
};4. 定义工具节点
工具节点用于调用工具并返回结果。
import { AIMessage, ToolMessage } from "@langchain/core/messages";
const toolNode: GraphNode<typeof MessagesState> = async (state) => {
const lastMessage = state.messages.at(-1);
if (lastMessage == null || !AIMessage.isInstance(lastMessage)) {
return { messages: [] };
}
const result: ToolMessage[] = [];
for (const toolCall of lastMessage.tool_calls ?? []) {
const tool = toolsByName[toolCall.name];
const observation = await tool.invoke(toolCall);
result.push(observation);
}
return { messages: result };
};5. 定义结束逻辑
条件边函数用于根据 LLM 是否发起了工具调用来路由到工具节点或结束。
const shouldContinue: ConditionalEdgeRouter<{ InputSchema: typeof MessagesState; Nodes: "toolNode" }> = (state) => {
const lastMessage = state.messages.at(-1);
// 在访问 tool_calls 之前检查它是否是 AIMessage
if (!lastMessage || !AIMessage.isInstance(lastMessage)) {
return END;
}
// 如果 LLM 发起了工具调用,则执行相应操作
if (lastMessage.tool_calls?.length) {
return "toolNode";
}
// 否则,停止并回复用户
return END;
};6. 构建并编译智能体
使用 StateGraph 类构建智能体,并使用 compile 方法进行编译。
const agent = new StateGraph(MessagesState)
.addNode("llmCall", llmCall)
.addNode("toolNode", toolNode)
.addEdge(START, "llmCall")
.addConditionalEdges("llmCall", shouldContinue, ["toolNode", END])
.addEdge("toolNode", "llmCall")
.compile();
// 调用
import { HumanMessage } from "@langchain/core/messages";
const result = await agent.invoke({
messages: [new HumanMessage("Add 3 and 4.")],
});
for (const message of result.messages) {
console.log(`[${message.type}]: ${message.text}`);
}TIP
使用 LangSmith 跟踪和调试你的智能体。按照跟踪快速入门进行设置。准备好投入生产后,请参阅部署了解托管选项。
我们还建议你设置 LangSmith Engine,它可以监控你的跟踪、检测问题并提出修复建议。
恭喜!你已经使用 LangGraph Graph API 构建了你的第一个智能体。
完整代码示例
// Step 1: Define tools and model
import { ChatAnthropic } from "@langchain/anthropic";
import { tool } from "@langchain/core/tools";
import * as z from "zod";
const model = new ChatAnthropic({
model: "claude-sonnet-4-6",
temperature: 0,
});
// Define tools
const add = tool(({ a, b }) => a + b, {
name: "add",
description: "Add two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
const multiply = tool(({ a, b }) => a * b, {
name: "multiply",
description: "Multiply two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
const divide = tool(({ a, b }) => a / b, {
name: "divide",
description: "Divide two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
// Augment the LLM with tools
const toolsByName = {
[add.name]: add,
[multiply.name]: multiply,
[divide.name]: divide,
};
const tools = Object.values(toolsByName);
const modelWithTools = model.bindTools(tools);// Step 2: Define state
import {
StateGraph,
StateSchema,
MessagesValue,
ReducedValue,
GraphNode,
ConditionalEdgeRouter,
START,
END,
} from "@langchain/langgraph";
import * as z from "zod";
const MessagesState = new StateSchema({
messages: MessagesValue,
llmCalls: new ReducedValue(
z.number().default(0),
{ reducer: (x, y) => x + y }
),
});// Step 3: Define model node
import { SystemMessage, AIMessage, ToolMessage } from "@langchain/core/messages";
const llmCall: GraphNode<typeof MessagesState> = async (state) => {
return {
messages: [await modelWithTools.invoke([
new SystemMessage(
"You are a helpful assistant tasked with performing arithmetic on a set of inputs."
),
...state.messages,
])],
llmCalls: 1,
};
};
// Step 4: Define tool node
const toolNode: GraphNode<typeof MessagesState> = async (state) => {
const lastMessage = state.messages.at(-1);
if (lastMessage == null || !AIMessage.isInstance(lastMessage)) {
return { messages: [] };
}
const result: ToolMessage[] = [];
for (const toolCall of lastMessage.tool_calls ?? []) {
const tool = toolsByName[toolCall.name];
const observation = await tool.invoke(toolCall);
result.push(observation);
}
return { messages: result };
};// Step 5: Define logic to determine whether to end
import { ConditionalEdgeRouter, END } from "@langchain/langgraph";
const shouldContinue: ConditionalEdgeRouter<{ InputSchema: typeof MessagesState; Nodes: "toolNode" }> = (state) => {
const lastMessage = state.messages.at(-1);
// Check if it's an AIMessage before accessing tool_calls
if (!lastMessage || !AIMessage.isInstance(lastMessage)) {
return END;
}
// If the LLM makes a tool call, then perform an action
if (lastMessage.tool_calls?.length) {
return "toolNode";
}
// Otherwise, we stop (reply to the user)
return END;
};// Step 6: Build and compile the agent
import { HumanMessage } from "@langchain/core/messages";
import { StateGraph, START, END } from "@langchain/langgraph";
const agent = new StateGraph(MessagesState)
.addNode("llmCall", llmCall)
.addNode("toolNode", toolNode)
.addEdge(START, "llmCall")
.addConditionalEdges("llmCall", shouldContinue, ["toolNode", END])
.addEdge("toolNode", "llmCall")
.compile();
// Invoke
const result = await agent.invoke({
messages: [new HumanMessage("Add 3 and 4.")],
});
for (const message of result.messages) {
console.log(`[${message.type}]: ${message.text}`);
}使用 Functional API
1. 定义工具与模型
在此示例中,我们将使用 Claude Sonnet 4.5 模型,并定义加法、乘法和除法工具。
import { ChatAnthropic } from "@langchain/anthropic";
import { tool } from "@langchain/core/tools";
import * as z from "zod";
const model = new ChatAnthropic({
model: "claude-sonnet-4-6",
temperature: 0,
});
// 定义工具
const add = tool(({ a, b }) => a + b, {
name: "add",
description: "Add two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
const multiply = tool(({ a, b }) => a * b, {
name: "multiply",
description: "Multiply two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
const divide = tool(({ a, b }) => a / b, {
name: "divide",
description: "Divide two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
// 使用工具增强 LLM
const toolsByName = {
[add.name]: add,
[multiply.name]: multiply,
[divide.name]: divide,
};
const tools = Object.values(toolsByName);
const modelWithTools = model.bindTools(tools);2. 定义模型节点
模型节点用于调用 LLM 并决定是否调用工具。
import { task, entrypoint } from "@langchain/langgraph";
import { SystemMessage } from "@langchain/core/messages";
const callLlm = task({ name: "callLlm" }, async (messages: BaseMessage[]) => {
return modelWithTools.invoke([
new SystemMessage(
"You are a helpful assistant tasked with performing arithmetic on a set of inputs."
),
...messages,
]);
});3. 定义工具节点
工具节点用于调用工具并返回结果。
import type { ToolCall } from "@langchain/core/messages/tool";
const callTool = task({ name: "callTool" }, async (toolCall: ToolCall) => {
const tool = toolsByName[toolCall.name];
return tool.invoke(toolCall);
});4. 定义智能体
import { addMessages } from "@langchain/langgraph";
import { type BaseMessage } from "@langchain/core/messages";
const agent = entrypoint({ name: "agent" }, async (messages: BaseMessage[]) => {
let modelResponse = await callLlm(messages);
while (true) {
if (!modelResponse.tool_calls?.length) {
break;
}
// 执行工具
const toolResults = await Promise.all(
modelResponse.tool_calls.map((toolCall) => callTool(toolCall))
);
messages = addMessages(messages, [modelResponse, ...toolResults]);
modelResponse = await callLlm(messages);
}
return messages;
});
// 调用
import { HumanMessage } from "@langchain/core/messages";
const result = await agent.invoke([new HumanMessage("Add 3 and 4.")]);
for (const message of result) {
console.log(`[${message.getType()}]: ${message.text}`);
}TIP
使用 LangSmith 跟踪和调试你的智能体。按照跟踪快速入门进行设置。准备好投入生产后,请参阅部署了解托管选项。
我们还建议你设置 LangSmith Engine,它可以监控你的跟踪、检测问题并提出修复建议。
恭喜!你已经使用 LangGraph Functional API 构建了你的第一个智能体。
完整代码示例
import { ChatAnthropic } from "@langchain/anthropic";
import { tool } from "@langchain/core/tools";
import {
task,
entrypoint,
addMessages,
} from "@langchain/langgraph";
import {
SystemMessage,
HumanMessage,
type BaseMessage,
} from "@langchain/core/messages";
import type { ToolCall } from "@langchain/core/messages/tool";
import * as z from "zod";
// Step 1: Define tools and model
const model = new ChatAnthropic({
model: "claude-sonnet-4-6",
temperature: 0,
});
// Define tools
const add = tool(({ a, b }) => a + b, {
name: "add",
description: "Add two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
const multiply = tool(({ a, b }) => a * b, {
name: "multiply",
description: "Multiply two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
const divide = tool(({ a, b }) => a / b, {
name: "divide",
description: "Divide two numbers",
schema: z.object({
a: z.number().describe("First number"),
b: z.number().describe("Second number"),
}),
});
// Augment the LLM with tools
const toolsByName = {
[add.name]: add,
[multiply.name]: multiply,
[divide.name]: divide,
};
const tools = Object.values(toolsByName);
const modelWithTools = model.bindTools(tools);
// Step 2: Define model node
const callLlm = task({ name: "callLlm" }, async (messages: BaseMessage[]) => {
return modelWithTools.invoke([
new SystemMessage(
"You are a helpful assistant tasked with performing arithmetic on a set of inputs."
),
...messages,
]);
});
// Step 3: Define tool node
const callTool = task({ name: "callTool" }, async (toolCall: ToolCall) => {
const tool = toolsByName[toolCall.name];
return tool.invoke(toolCall);
});
// Step 4: Define agent
const agent = entrypoint({ name: "agent" }, async (messages: BaseMessage[]) => {
let modelResponse = await callLlm(messages);
while (true) {
if (!modelResponse.tool_calls?.length) {
break;
}
// Execute tools
const toolResults = await Promise.all(
modelResponse.tool_calls.map((toolCall) => callTool(toolCall))
);
messages = addMessages(messages, [modelResponse, ...toolResults]);
modelResponse = await callLlm(messages);
}
return messages;
});
// Invoke
const result = await agent.invoke([new HumanMessage("Add 3 and 4.")]);
for (const message of result) {
console.log(`[${message.type}]: ${message.text}`);
}