> ## Documentation Index
> Fetch the complete documentation index at: https://cndoc-langchain.site/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 "It's 60 degrees and foggy."
      return "It's 90 degrees and sunny."

  tools = [search]
  tool_node = ToolNode(tools)

  model = ChatOpenAI(model="gpt-5.4", 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 "It's 60 degrees and foggy."
    }
    return "It's 90 degrees and sunny."
  }, {
    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-5.4",
    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-%40traceable-%2F-traceable)（使用 Python 中的 `@traceable` 装饰器或 JS 中的 `traceable` 函数，或类似 `wrap_openai` 的 SDK 包装器）。如果您这样做，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-%40traceable-%2F-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 "It's 60 degrees and foggy."
      return "It's 90 degrees and sunny."

  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-5.4-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 "It's 60 degrees and foggy.";
    }
    return "It's 90 degrees and sunny.";
  }, { 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("No tool calls passed to node.");
    }
    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-5.4-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="terminal-2">
    [连接这些文档](/use-these-docs) 到 Claude、VSCode 等，通过 MCP 获取实时答案。
  </Callout>

  <Callout icon="edit">
    [在 GitHub 上编辑此页面](https://github.com/langchain-ai/docs/edit/main/src/langsmith/trace-with-langgraph.mdx) 或 [提交问题](https://github.com/langchain-ai/docs/issues/new/choose)。
  </Callout>
</div>
