Skip to main content
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>
# 이 예제는 OpenAI를 사용하지만, 원하는 LLM 제공자를 사용할 수 있습니다
export OPENAI_API_KEY=<your-openai-api-key>
# 여러 워크스페이스에 연결된 LangSmith API 키의 경우, 사용할 워크스페이스를 지정하기 위해 LANGSMITH_WORKSPACE_ID 환경 변수를 설정하세요.
export LANGSMITH_WORKSPACE_ID=<your-workspace-id>
서버리스 환경이 아닌 곳에서 LangSmith와 함께 LangChain.js를 사용하는 경우, 지연 시간을 줄이기 위해 다음을 명시적으로 설정하는 것을 권장합니다:export LANGCHAIN_CALLBACKS_BACKGROUND=true서버리스 환경에서는 함수가 종료되기 전에 추적이 완료될 수 있도록 반대로 설정하는 것을 권장합니다:export LANGCHAIN_CALLBACKS_BACKGROUND=false자세한 내용은 이 LangChain.js 가이드를 참조하세요.

3. 추적 로그 남기기

환경을 설정한 후에는 평소처럼 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
위 코드를 실행한 예제 추적은 다음과 같습니다: LangChain과 함께한 LangGraph 실행의 추적 트리

LangChain 없이 사용하기

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

1. 설치

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

2. 환경 구성하기

export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<your-api-key>
# 이 예제는 OpenAI를 사용하지만, 원하는 LLM 제공자를 사용할 수 있습니다
export OPENAI_API_KEY=<your-openai-api-key>
서버리스 환경이 아닌 곳에서 LangSmith와 함께 LangChain.js를 사용하는 경우, 지연 시간을 줄이기 위해 다음을 명시적으로 설정하는 것을 권장합니다: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": "Call to surf the web.",
        "parameters": {
            "type": "object",
            "properties": {"query": {"type": "string"}},
            "required": ["query"],
        },
    },
}

# 도구 함수를 데코레이팅하면 올바른 컨텍스트로 자동으로 추적됩니다
@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"]
    # 래핑된 클라이언트를 호출하면 올바른 추적 컨텍스트가 자동으로 추론됩니다
    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"]
위 코드를 실행한 예제 추적은 다음과 같습니다: LangChain 없이 LangGraph 실행의 추적 트리
Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.
I