使用 LangChain
如果您在 LangGraph 中使用 LangChain 模块,只需设置几个环境变量即可启用追踪。 本指南将通过一个基本示例进行说明。有关配置的更多详细信息,请参阅 使用 LangChain 进行追踪 指南。1. 安装
安装 LangGraph 库以及 Python 和 JS 的 OpenAI 集成(下面的代码片段使用 OpenAI 集成)。 有关可用包的完整列表,请参阅 LangChain Python 文档 和 LangChain JS 文档。pip install langchain_openai langgraph
yarn add @langchain/openai @langchain/langgraph
npm install @langchain/openai @langchain/langgraph
pnpm add @langchain/openai @langchain/langgraph
2. 配置您的环境
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>
如果您在非无服务器环境中使用 LangChain.js 和 LangSmith,我们还建议明确设置以下内容以减少延迟:
export LANGCHAIN_CALLBACKS_BACKGROUND=true如果您在无服务器环境中,我们建议设置相反的值以允许追踪在函数结束前完成:export LANGCHAIN_CALLBACKS_BACKGROUND=false有关更多信息,请参阅 此 LangChain.js 指南。3. 记录追踪
设置好环境后,您可以像往常一样调用 LangChain 可运行对象。LangSmith 将推断正确的追踪配置: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
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;
查看追踪
详情视图 点击追踪,然后在右上角切换到 详情 视图。您在 LangSmith 中的追踪应 看起来像这样。 消息视图 LangSmith UI 中的 消息 视图显示了用户和智能体之间简化的对话历史记录。此视图从顶层追踪中提取消息(包括用户的初始请求、工具调用和智能体的最终响应),并以类似聊天的格式呈现它们。不使用 LangChain
如果您在 LangGraph 中使用其他 SDK 或自定义函数,则需要 适当地包装或装饰它们(使用 Python 中的@traceable 装饰器或 JS 中的 traceable 函数,或类似 wrap_openai 的 SDK 包装器)。如果您这样做,LangSmith 将自动嵌套来自这些包装方法的追踪。
这是一个示例。您也可以查看此页面获取更多信息。
1. 安装
安装 LangGraph 库以及 Python 和 JS 的 OpenAI SDK(下面的代码片段使用 OpenAI 集成)。pip install openai langsmith langgraph
yarn add openai langsmith @langchain/langgraph
npm install openai langsmith @langchain/langgraph
pnpm add openai langsmith @langchain/langgraph
2. 配置您的环境
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<your-api-key>
# 本示例使用 OpenAI,但您可以使用任何选择的 LLM 提供商
export OPENAI_API_KEY=<your-openai-api-key>
如果您在非无服务器环境中使用 LangChain.js 和 LangSmith,我们还建议明确设置以下内容以减少延迟:
export LANGCHAIN_CALLBACKS_BACKGROUND=true如果您在无服务器环境中,我们建议设置相反的值以允许追踪在函数结束前完成:export LANGCHAIN_CALLBACKS_BACKGROUND=false有关更多信息,请参阅 此 LangChain.js 指南。3. 记录追踪
设置好环境后,包装或装饰您想要追踪的自定义函数/SDK。然后 LangSmith 将推断正确的追踪配置: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"]
**注意:** 以下示例需要 `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" }]
});
查看追踪
详情视图 点击追踪,然后在右上角切换到 详情 视图。您在 LangSmith 中的追踪应 看起来像这样。 消息视图 LangSmith UI 中的 消息 视图显示了用户和智能体之间简化的对话历史记录。此视图从顶层追踪中提取消息(包括用户的初始请求、工具调用和智能体的最终响应),并以类似聊天的格式呈现它们。连接这些文档 到 Claude、VSCode 等,通过 MCP 获取实时答案。

