> ## Documentation Index
> Fetch the complete documentation index at: https://langchain-zh.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 追踪 LangGraph 应用

LangSmith 与 LangGraph（Python 和 JS）无缝集成，帮助您追踪智能体，无论您使用的是 LangChain 模块还是其他 SDK。

## 使用 LangChain

如果您在 LangGraph 中使用 LangChain 模块，只需设置几个环境变量即可启用追踪。

本指南将演示一个基础示例。有关配置的更多详细信息，请参阅 [使用 LangChain 进行追踪](/langsmith/trace-with-langchain) 指南。

### 1. 安装

安装 LangGraph 库以及 Python 和 JS 的 OpenAI 集成（以下代码片段使用 OpenAI 集成）。

有关可用包的完整列表，请参阅 [LangChain Python 文档](https://docs.langchain.com/oss/python/integrations/providers/overview) 和 [LangChain JS 文档](https://docs.langchain.com/oss/javascript/integrations/providers/overview)。

<CodeGroup>
  ```bash pip theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  pip install langchain_openai langgraph
  ```

  ```bash yarn theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  yarn add @langchain/openai @langchain/langgraph
  ```

  ```bash npm theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  npm install @langchain/openai @langchain/langgraph
  ```

  ```bash pnpm theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  pnpm add @langchain/openai @langchain/langgraph
  ```
</CodeGroup>

### 2. 配置环境

```bash wrap theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<your-api-key>
# 此示例使用 OpenAI，但您可以选择任何 LLM 提供商
export OPENAI_API_KEY=<your-openai-api-key>
# 对于关联到多个工作空间的 LangSmith API 密钥，设置 LANGSMITH_WORKSPACE_ID 环境变量以指定使用哪个工作空间。
export LANGSMITH_WORKSPACE_ID=<your-workspace-id>
```

<Info>
  如果您在非无服务器环境中使用 LangChain.js 和 LangSmith，我们还建议显式设置以下变量以减少延迟：

  `export LANGCHAIN_CALLBACKS_BACKGROUND=true`

  如果您在无服务器环境中，建议设置相反的值，以便在函数结束前完成追踪：

  `export LANGCHAIN_CALLBACKS_BACKGROUND=false`

  更多信息请参阅 [此 LangChain.js 指南](https://js.langchain.com/docs/how_to/callbacks_serverless)。
</Info>

### 3. 记录追踪

设置好环境后，您可以正常调用 LangChain 可运行对象。LangSmith 将推断出正确的追踪配置：

<CodeGroup>
  ```python Python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  from typing import Literal
  from langchain.messages import HumanMessage
  from langchain_openai import ChatOpenAI
  from langchain.tools import tool
  from langgraph.prebuilt import ToolNode
  from langgraph.graph import StateGraph, MessagesState

  @tool
  def search(query: str):
      """调用以浏览网页。"""
      if "sf" in query.lower() or "san francisco" in query.lower():
          return "天气是 60 华氏度，有雾。"
      return "天气是 90 华氏度，晴朗。"

  tools = [search]
  tool_node = ToolNode(tools)

  model = ChatOpenAI(model="gpt-4.1", temperature=0).bind_tools(tools)

  def should_continue(state: MessagesState) -> Literal["tools", "__end__"]:
      messages = state['messages']
      last_message = messages[-1]
      if last_message.tool_calls:
          return "tools"
      return "__end__"

  def call_model(state: MessagesState):
      messages = state['messages']
      # 调用 `model` 将自动推断正确的追踪上下文
      response = model.invoke(messages)
      return {"messages": [response]}

  workflow = StateGraph(MessagesState)
  workflow.add_node("agent", call_model)
  workflow.add_node("tools", tool_node)
  workflow.add_edge("__start__", "agent")
  workflow.add_conditional_edges(
      "agent",
      should_continue,
  )
  workflow.add_edge("tools", 'agent')

  app = workflow.compile()

  final_state = app.invoke(
      {"messages": [HumanMessage(content="what is the weather in sf")]},
      config={"configurable": {"thread_id": 42}}
  )

  final_state["messages"][-1].content
  ```

  ```typescript TypeScript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  import { HumanMessage, AIMessage } from "@langchain/core/messages";
  import { tool } from "@langchain/core/tools";
  import { z } from "zod";
  import { ChatOpenAI } from "@langchain/openai";
  import { StateGraph, StateGraphArgs } from "@langchain/langgraph";
  import { ToolNode } from "@langchain/langgraph/prebuilt";

  interface AgentState {
    messages: HumanMessage[];
  }

  const graphState: StateGraphArgs<AgentState>["channels"] = {
    messages: {
      reducer: (x: HumanMessage[], y: HumanMessage[]) => x.concat(y),
    },
  };

  const searchTool = tool(async ({ query }: { query: string }) => {
    if (query.toLowerCase().includes("sf") || query.toLowerCase().includes("san francisco")) {
      return "天气是 60 华氏度，有雾。"
    }
    return "天气是 90 华氏度，晴朗。"
  }, {
    name: "search",
    description:
      "调用以浏览网页。",
    schema: z.object({
      query: z.string().describe("搜索中使用的查询。"),
    }),
  });

  const tools = [searchTool];
  const toolNode = new ToolNode<AgentState>(tools);

  const model = new ChatOpenAI({
    model: "gpt-4.1",
    temperature: 0,
  }).bindTools(tools);

  function shouldContinue(state: AgentState) {
    const messages = state.messages;
    const lastMessage = messages[messages.length - 1] as AIMessage;
    if (lastMessage.tool_calls?.length) {
      return "tools";
    }
    return "__end__";
  }

  async function callModel(state: AgentState) {
    const messages = state.messages;
    // 调用 `model` 将自动推断正确的追踪上下文
    const response = await model.invoke(messages);
    return { messages: [response] };
  }

  const workflow = new StateGraph<AgentState>({ channels: graphState })
    .addNode("agent", callModel)
    .addNode("tools", toolNode)
    .addEdge("__start__", "agent")
    .addConditionalEdges("agent", shouldContinue)
    .addEdge("tools", "agent");

  const app = workflow.compile();

  const finalState = await app.invoke(
    { messages: [new HumanMessage("what is the weather in sf")] },
    { configurable: { thread_id: "42" } }
  );

  finalState.messages[finalState.messages.length - 1].content;
  ```
</CodeGroup>

### 查看追踪

**详细信息视图**

点击追踪，并在右上角切换到 **详细信息** 视图。您在 LangSmith 中的追踪应 [看起来像这样](https://smith.langchain.com/public/79061a0f-c602-4012-b022-03fd46bce89e/r)。

**消息视图**

LangSmith UI 中的 **消息** 视图显示了用户与智能体之间的简化对话历史。此视图从顶层追踪（包括用户的初始请求、工具调用和智能体的最终响应）中提取消息，并以类似聊天的格式呈现。

## 不使用 LangChain

如果您在 LangGraph 中使用其他 SDK 或自定义函数，您将需要 [适当地包装或装饰它们](/langsmith/annotate-code#use-traceable--traceable)（在 Python 中使用 `@traceable` 装饰器，在 JS 中使用 `traceable` 函数，或类似 `wrap_openai` 的方法）。如果这样做，LangSmith 将自动嵌套来自这些包装方法的追踪。

以下是一个示例。您也可以查看此页面获取更多信息。

### 1. 安装

安装 LangGraph 库以及 Python 和 JS 的 OpenAI SDK（以下代码片段使用 OpenAI 集成）。

<CodeGroup>
  ```bash pip theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  pip install openai langsmith langgraph
  ```

  ```bash yarn theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  yarn add openai langsmith @langchain/langgraph
  ```

  ```bash npm theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  npm install openai langsmith @langchain/langgraph
  ```

  ```bash pnpm theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  pnpm add openai langsmith @langchain/langgraph
  ```
</CodeGroup>

### 2. 配置环境

```bash wrap theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<your-api-key>
# 此示例使用 OpenAI，但您可以选择任何 LLM 提供商
export OPENAI_API_KEY=<your-openai-api-key>
```

<Info>
  如果您在非无服务器环境中使用 LangChain.js 和 LangSmith，我们还建议显式设置以下变量以减少延迟：

  `export LANGCHAIN_CALLBACKS_BACKGROUND=true`

  如果您在无服务器环境中，建议设置相反的值，以便在函数结束前完成追踪：

  `export LANGCHAIN_CALLBACKS_BACKGROUND=false`

  更多信息请参阅 [此 LangChain.js 指南](https://js.langchain.com/docs/how_to/callbacks_serverless)。
</Info>

### 3. 记录追踪

设置好环境后，[包装或装饰您想要追踪的自定义函数/SDK](/langsmith/annotate-code#use-traceable--traceable)。LangSmith 随后将推断出正确的追踪配置：

<CodeGroup>
  ```python Python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  import json
  import openai
  import operator
  from langsmith import traceable
  from langsmith.wrappers import wrap_openai
  from typing import Annotated, Literal, TypedDict
  from langgraph.graph import StateGraph

  class State(TypedDict):
      messages: Annotated[list, operator.add]

  tool_schema = {
      "type": "function",
      "function": {
          "name": "search",
          "description": "调用以浏览网页。",
          "parameters": {
              "type": "object",
              "properties": {"query": {"type": "string"}},
              "required": ["query"],
          },
      },
  }

  # 装饰工具函数将自动使用正确的上下文进行追踪
  @traceable(run_type="tool", name="Search Tool")
  def search(query: str):
      """调用以浏览网页。"""
      if "sf" in query.lower() or "san francisco" in query.lower():
          return "天气是 60 华氏度，有雾。"
      return "天气是 90 华氏度，晴朗。"

  tools = [search]

  def call_tools(state):
      function_name_to_function = {"search": search}
      messages = state["messages"]
      tool_call = messages[-1]["tool_calls"][0]
      function_name = tool_call["function"]["name"]
      function_arguments = tool_call["function"]["arguments"]
      arguments = json.loads(function_arguments)
      function_response = function_name_to_function[function_name](**arguments)
      tool_message = {
          "tool_call_id": tool_call["id"],
          "role": "tool",
          "name": function_name,
          "content": function_response,
      }
      return {"messages": [tool_message]}

  wrapped_client = wrap_openai(openai.Client())

  def should_continue(state: State) -> Literal["tools", "__end__"]:
      messages = state["messages"]
      last_message = messages[-1]
      if last_message["tool_calls"]:
          return "tools"
      return "__end__"

  def call_model(state: State):
      messages = state["messages"]
      # 调用包装后的客户端将自动推断正确的追踪上下文
      response = wrapped_client.chat.completions.create(
          messages=messages, model="gpt-4.1-mini", tools=[tool_schema]
      )
      raw_tool_calls = response.choices[0].message.tool_calls
      tool_calls = [tool_call.to_dict() for tool_call in raw_tool_calls] if raw_tool_calls else []
      response_message = {
          "role": "assistant",
          "content": response.choices[0].message.content,
          "tool_calls": tool_calls,
      }
      return {"messages": [response_message]}

  workflow = StateGraph(State)
  workflow.add_node("agent", call_model)
  workflow.add_node("tools", call_tools)
  workflow.add_edge("__start__", "agent")
  workflow.add_conditional_edges(
      "agent",
      should_continue,
  )
  workflow.add_edge("tools", 'agent')

  app = workflow.compile()

  final_state = app.invoke(
      {"messages": [{"role": "user", "content": "what is the weather in sf"}]}
  )

  final_state["messages"][-1]["content"]
  ```

  ```typescript TypeScript theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
  **注意：** 以下示例需要 `langsmith>=0.1.39` 和 `@langchain/langgraph>=0.0.31`

  import OpenAI from "openai";
  import { StateGraph } from "@langchain/langgraph";
  import { wrapOpenAI } from "langsmith/wrappers/openai";
  import { traceable } from "langsmith/traceable";

  type GraphState = {
    messages: OpenAI.ChatCompletionMessageParam[];
  };

  const wrappedClient = wrapOpenAI(new OpenAI({}));

  const toolSchema: OpenAI.ChatCompletionTool = {
    type: "function",
    function: {
      name: "search",
      description: "使用此工具查询网页。",
      parameters: {
        type: "object",
        properties: {
          query: {
            type: "string",
          },
        },
        required: ["query"],
      }
    }
  };

  // 包装工具函数将自动使用正确的上下文进行追踪
  const search = traceable(async ({ query }: { query: string }) => {
    if (
      query.toLowerCase().includes("sf") ||
      query.toLowerCase().includes("san francisco")
    ) {
      return "天气是 60 华氏度，有雾。";
    }
    return "天气是 90 华氏度，晴朗。";
  }, { run_type: "tool", name: "Search Tool" });

  const callTools = async ({ messages }: GraphState) => {
    const mostRecentMessage = messages[messages.length - 1];
    const toolCalls = (mostRecentMessage as OpenAI.ChatCompletionAssistantMessageParam).tool_calls;
    if (toolCalls === undefined || toolCalls.length === 0) {
      throw new Error("没有工具调用传递给节点。");
    }
    const toolNameMap = {
      search,
    };
    const functionName = toolCalls[0].function.name;
    const functionArguments = JSON.parse(toolCalls[0].function.arguments);
    const response = await toolNameMap[functionName](functionArguments);
    const toolMessage = {
      tool_call_id: toolCalls[0].id,
      role: "tool",
      name: functionName,
      content: response,
    }
    return { messages: [toolMessage] };
  };

  const callModel = async ({ messages }: GraphState) => {
    // 调用包装后的客户端将自动推断正确的追踪上下文
    const response = await wrappedClient.chat.completions.create({
      messages,
      model: "gpt-4.1-mini",
      tools: [toolSchema],
    });
    const responseMessage = {
      role: "assistant",
      content: response.choices[0].message.content,
      tool_calls: response.choices[0].message.tool_calls ?? [],
    };
    return { messages: [responseMessage] };
  };

  const shouldContinue = ({ messages }: GraphState) => {
    const lastMessage =
      messages[messages.length - 1] as OpenAI.ChatCompletionAssistantMessageParam;
    if (
      lastMessage?.tool_calls !== undefined &&
      lastMessage?.tool_calls.length > 0
    ) {
      return "tools";
    }
    return "__end__";
  }

  const workflow = new StateGraph<GraphState>({
    channels: {
      messages: {
        reducer: (a: any, b: any) => a.concat(b),
      }
    }
  });

  const graph = workflow
    .addNode("model", callModel)
    .addNode("tools", callTools)
    .addEdge("__start__", "model")
    .addConditionalEdges("model", shouldContinue, {
      tools: "tools",
      __end__: "__end__",
    })
    .addEdge("tools", "model")
    .compile();

  await graph.invoke({
    messages: [{ role: "user", content: "what is the weather in sf" }]
  });
  ```
</CodeGroup>

### 查看追踪

**详细信息视图**

点击追踪，并在右上角切换到 **详细信息** 视图。您在 LangSmith 中的追踪应 [看起来像这样](https://smith.langchain.com/public/c3d128fa-c618-4b0e-b9d0-ccbb619440d8/r)。

**消息视图**

LangSmith UI 中的 **消息** 视图显示了用户与智能体之间的简化对话历史。此视图从顶层追踪（包括用户的初始请求、工具调用和智能体的最终响应）中提取消息，并以类似聊天的格式呈现。

***

<div className="source-links">
  <Callout icon="edit">
    [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/i18n\zh-CN\langsmith\trace-with-langgraph.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose).
  </Callout>

  <Callout icon="terminal-2">
    [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers.
  </Callout>
</div>
