Skip to content

快速入门 ​

本快速入门演示如何使用 LangGraph Graph API 或 Functional API 构建一个计算器智能体。

构建 LangGraph 计算器快速入门:

按照 LangGraph 快速入门指南,在当前工作目录中构建一个 LangGraph 计算器智能体。

第 1 步:阅读指南 ​

检测该项目使用的是 Python 还是 TypeScript/JavaScript。获取并遵循匹配的页面;将其作为包名、模型字符串和代码的权威来源:

询问用户使用 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 参考。

    要添加的服务器:

    检测我使用的是哪个智能体或编辑器(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 安装程序:

    bash
    npx skills add langchain-ai/langchain-skills --skill '*' --yes

    如果我要求全局安装,请使用:

    bash
    npx skills add langchain-ai/langchain-skills --skill '*' --yes --global

    检测我使用的是哪个智能体或编辑器。如果我使用 Claude Code 并且偏好插件路径,请遵循该仓库 README 中的市场安装(/plugin marketplace add 然后 /plugin install)。不要捏造替代技能包名称或安装 URL。安装后,确认技能可供智能体使用。

有关概念信息,请参阅 Graph API 概览和 Functional API 概览。

INFO

对于此示例,你需要设置一个 Claude (Anthropic) 账户并获取 API 密钥。然后,在终端中设置 ANTHROPIC_API_KEY 环境变量。有关所有可用提供商,请参阅聊天模型集成。如果你使用 LangSmith Gateway,你可以自带提供商密钥或使用 Gateway 积分在没有提供商密钥的情况下访问模型。

使用 Graph API ​

1. 定义工具与模型 ​

在此示例中,我们将使用 Claude Sonnet 4.5 模型,并定义加法、乘法和除法工具。

typescript
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 来累计计数。

typescript
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 并决定是否调用工具。

typescript
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. 定义工具节点 ​

工具节点用于调用工具并返回结果。

typescript
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 是否发起了工具调用来路由到工具节点或结束。

typescript
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 方法进行编译。

typescript
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 构建了你的第一个智能体。

完整代码示例
typescript
// 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);
typescript
// 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 }
  ),
});
typescript
// 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 };
};
typescript
// 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;
};
typescript
// 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 模型,并定义加法、乘法和除法工具。

typescript
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 并决定是否调用工具。

typescript
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. 定义工具节点 ​

工具节点用于调用工具并返回结果。

typescript
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. 定义智能体 ​

typescript
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 构建了你的第一个智能体。

完整代码示例
typescript
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}`);
}