LangSmith는 LangGraph(Python 및 JS)와 원활하게 통합되어 LangChain 모듈이나 다른 SDK를 사용하는지 여부와 관계없이 에이전트를 추적할 수 있도록 도와줍니다.

LangChain과 함께 사용

LangGraph 내에서 LangChain 모듈을 사용하는 경우, 추적을 활성화하기 위해 몇 가지 환경 변수만 설정하면 됩니다. 이 가이드는 기본 예제를 안내합니다. 구성에 대한 자세한 내용은 LangChain으로 추적하기 가이드를 참조하세요.

1. 설치

Python 및 JS용 LangGraph 라이브러리와 OpenAI 통합을 설치합니다(아래 코드 스니펫에서는 OpenAI 통합을 사용합니다). 사용 가능한 패키지의 전체 목록은 LangChain Python 문서LangChain JS 문서를 참조하세요.
pip install langchain_openai langgraph

2. 환경 구성

export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<your-api-key>
# This example uses OpenAI, but you can use any LLM provider of choice
export OPENAI_API_KEY=<your-openai-api-key>
# For LangSmith API keys linked to multiple workspaces, set the LANGSMITH_WORKSPACE_ID environment variable to specify which workspace to use.
export LANGSMITH_WORKSPACE_ID=<your-workspace-id>
LangSmith와 함께 LangChain.js를 사용하고 서버리스 환경이 아닌 경우, 지연 시간을 줄이기 위해 다음을 명시적으로 설정하는 것이 좋습니다:export LANGCHAIN_CALLBACKS_BACKGROUND=true서버리스 환경에서는 함수가 종료되기 전에 추적이 완료될 수 있도록 반대로 설정하는 것이 좋습니다:export LANGCHAIN_CALLBACKS_BACKGROUND=false자세한 내용은 이 LangChain.js 가이드를 참조하세요.

3. trace 로깅

환경을 설정한 후에는 평소처럼 LangChain runnable을 호출할 수 있습니다. 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):
    """Call to surf the web."""
    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-4o", 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']
    # Invoking `model` will automatically infer the correct tracing context
    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
위 코드를 실행한 trace 예제는 다음과 같습니다: LangChain을 사용한 LangGraph 실행의 Trace 트리

LangChain 없이 사용

LangGraph 내에서 다른 SDK나 커스텀 함수를 사용하는 경우, 적절하게 래핑하거나 데코레이팅해야 합니다(Python에서는 @traceable 데코레이터, JS에서는 traceable 함수 사용, 또는 SDK의 경우 wrap_openai와 같은 것 사용). 그렇게 하면 LangSmith가 래핑된 메서드의 trace를 자동으로 중첩합니다. 다음은 예제입니다. 자세한 내용은 이 페이지를 참조하세요.

1. 설치

Python 및 JS용 LangGraph 라이브러리와 OpenAI SDK를 설치합니다(아래 코드 스니펫에서는 OpenAI 통합을 사용합니다).
pip install openai langsmith langgraph

2. 환경 구성

export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<your-api-key>
# This example uses OpenAI, but you can use any LLM provider of choice
export OPENAI_API_KEY=<your-openai-api-key>
LangSmith와 함께 LangChain.js를 사용하고 서버리스 환경이 아닌 경우, 지연 시간을 줄이기 위해 다음을 명시적으로 설정하는 것이 좋습니다:export LANGCHAIN_CALLBACKS_BACKGROUND=true서버리스 환경에서는 함수가 종료되기 전에 추적이 완료될 수 있도록 반대로 설정하는 것이 좋습니다:export LANGCHAIN_CALLBACKS_BACKGROUND=false자세한 내용은 이 LangChain.js 가이드를 참조하세요.

3. trace 로깅

환경을 설정한 후, 추적하려는 커스텀 함수/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": "Call to surf the web.",
        "parameters": {
            "type": "object",
            "properties": {"query": {"type": "string"}},
            "required": ["query"],
        },
    },
}

# Decorating the tool function will automatically trace it with the correct context
@traceable(run_type="tool", name="Search Tool")
def search(query: str):
    """Call to surf the web."""
    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"]
    # Calling the wrapped client will automatically infer the correct tracing context
    response = wrapped_client.chat.completions.create(
        messages=messages, model="gpt-4o-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"]
위 코드를 실행한 trace 예제는 다음과 같습니다: LangChain 없이 LangGraph 실행의 Trace 트리
Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
I