LangSmith Guide 2025: LLM Observability, Tracing & Evaluation
LangSmith is LangChain's platform for debugging, testing, and monitoring LLM applications. It traces every chain, agent run, and raw API call — giving you full visibility into what your LLMs are doing, how much they cost, and whether they are producing correct outputs. Free tier supports 5,000 traces per month.
What Is LangSmith?
LangSmith is an observability, evaluation, and prompt management platform built by LangChain, Inc. Where LangChain gives you the framework to build LLM pipelines, LangSmith gives you the telescope to see inside them. Every trace captures the full input and output at each step — the user message, the retrieved documents, the prompt sent to the model, the completion, token counts, latency, and cost.
Key capabilities:
- Tracing — automatic for LangChain apps; manual via
@traceablefor any Python code - Prompt Hub — version, share, and pull prompts in code
- Datasets & Evals — build datasets from traces, run LLM-as-judge evaluators, track metrics over time
- Playground — test and compare prompts interactively in the UI
Pricing: free up to 5,000 traces/month (Developer plan); Developer+ at $39/month for 50k traces; Teams and Enterprise plans for larger usage. Sign up at smith.langchain.com.
Setup: Install & Configure
Install the LangSmith Python package and set the two required environment variables. That is the entire setup for a LangChain application:
Install
pip install langsmith
Environment variables (.env)
LANGCHAIN_API_KEY=ls__... # from smith.langchain.com → Settings → API Keys LANGCHAIN_TRACING_V2=true LANGCHAIN_PROJECT=my-app # optional — groups traces into a named project
Get your API key at smith.langchain.com → Settings → API Keys → Create API Key.
Auto-Tracing with LangChain
With LANGCHAIN_TRACING_V2=true, every LangChain chain, agent, retriever, and tool call is traced automatically — no code changes needed. The trace tree in the LangSmith UI shows each node with its inputs, outputs, token usage, and latency:
rag_chain.py — traced automatically
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "ls__..."
os.environ["LANGCHAIN_PROJECT"] = "rag-demo"
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.chains import RetrievalQA
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_texts(["LangSmith traces LangChain apps."], embeddings)
retriever = vectorstore.as_retriever()
llm = ChatOpenAI(model="gpt-4o-mini")
qa_chain = RetrievalQA.from_chain_type(llm=llm, retriever=retriever)
# This call is fully traced in LangSmith — retrieval + LLM + chain
result = qa_chain.invoke({"query": "What does LangSmith do?"})
print(result["result"]) Open smith.langchain.com → Projects → rag-demo to see the trace tree with all steps.
@traceable Decorator: Trace Any Python Code
The @traceable decorator wraps any Python function — not just LangChain — and records it as a span in LangSmith. Use it to trace OpenAI SDK calls, Anthropic SDK calls, database lookups, or custom business logic:
traceable_example.py
from langsmith import traceable
from openai import OpenAI
import anthropic
openai_client = OpenAI()
anthropic_client = anthropic.Anthropic()
@traceable(name="openai-call", run_type="llm")
def call_openai(user_message: str) -> str:
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": user_message}],
)
return response.choices[0].message.content
@traceable(name="anthropic-call", run_type="llm")
def call_anthropic(user_message: str) -> str:
message = anthropic_client.messages.create(
model="claude-3-5-haiku-20241022",
max_tokens=1024,
messages=[{"role": "user", "content": user_message}],
)
return message.content[0].text
@traceable(name="my-pipeline")
def pipeline(query: str) -> str:
openai_answer = call_openai(query)
anthropic_answer = call_anthropic(query)
return f"OpenAI: {openai_answer}\nAnthropic: {anthropic_answer}"
result = pipeline("Summarize observability in one sentence.")
All three functions appear as nested spans in a single trace in LangSmith. The run_type parameter categorises the span (llm, chain, tool, retriever, embedding, prompt).
Prompt Hub: Version & Share Prompts
The LangSmith Prompt Hub lets you save prompts as versioned, named artifacts — similar to how Docker Hub stores images. Pull prompts in code instead of hardcoding them:
Push a prompt to Prompt Hub
from langsmith import Client
from langchain_core.prompts import ChatPromptTemplate
client = Client()
# Create and push a versioned prompt
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant that answers in {language}."),
("human", "{question}"),
])
client.push_prompt("my-qa-prompt", object=prompt)
# Creates: smith.langchain.com/hub/your-org/my-qa-prompt Pull a prompt in code
from langchain import hub
# Pull the latest version
prompt = hub.pull("your-org/my-qa-prompt")
# Pull a specific commit hash for reproducibility
prompt = hub.pull("your-org/my-qa-prompt:abc12345")
# Use in a chain
from langchain_openai import ChatOpenAI
chain = prompt | ChatOpenAI(model="gpt-4o-mini")
result = chain.invoke({"language": "French", "question": "What is LangSmith?"}) Every prompt push creates a new commit. You can compare versions side-by-side in the Hub UI and roll back to any prior version instantly.
Evaluations: Datasets & LLM-as-Judge
LangSmith's evaluation workflow lets you build a dataset of input/output pairs, define evaluators (including LLM-as-judge), and run them in a batch. Results are tracked over time so you can compare model or prompt versions:
Create dataset and run eval
from langsmith import Client
from langsmith.evaluation import evaluate, LangChainStringEvaluator
from langchain_openai import ChatOpenAI
client = Client()
# 1. Create a dataset
dataset = client.create_dataset("qa-eval-dataset", description="QA pairs for eval")
client.create_examples(
inputs=[
{"question": "What is the capital of France?"},
{"question": "Who invented the telephone?"},
],
outputs=[
{"answer": "Paris"},
{"answer": "Alexander Graham Bell"},
],
dataset_id=dataset.id,
)
# 2. Define the system under test
def my_app(inputs: dict) -> dict:
llm = ChatOpenAI(model="gpt-4o-mini")
response = llm.invoke(inputs["question"])
return {"answer": response.content}
# 3. Run evaluation with LLM-as-judge
results = evaluate(
my_app,
data="qa-eval-dataset",
evaluators=[
LangChainStringEvaluator("qa"), # correctness judge
LangChainStringEvaluator("criteria", # custom criterion
config={"criteria": "conciseness"}),
],
experiment_prefix="gpt-4o-mini-baseline",
)
print(results.to_pandas())
Each evaluate() call creates an Experiment in LangSmith. You can compare experiments side-by-side in the UI to see which prompt or model version scores higher.
LangSmith Playground
The Playground is LangSmith's interactive prompt editor built into the UI. You can:
- Open any trace and click "Open in Playground" to replay it with different prompts or models
- Switch between GPT-4o, Claude 3.5, Gemini, and other models in one click
- Run inline evals directly from the Playground to score outputs without writing code
- Compare two prompt variants side-by-side with the same input
- Save a Playground session back to the Prompt Hub as a new version
The Playground is especially useful for prompt engineering iteration: find a failing trace, tweak the system prompt, run it, and commit the improved version — all without leaving the browser.
Datasets from Traces
One of LangSmith's most practical features is building datasets from real production traces. Instead of writing test cases manually, you annotate traces as good or bad examples and add them to a dataset:
Add trace examples to a dataset via API
from langsmith import Client
client = Client()
# Get runs from a project that you've flagged as interesting
runs = client.list_runs(
project_name="my-app",
filter='and(eq(feedback_key, "user_thumbs_down"), eq(feedback_score, 0))',
)
# Add them to a dataset for later eval
dataset = client.read_dataset(dataset_name="failures-dataset")
client.create_examples(
inputs=[run.inputs for run in runs],
outputs=[run.outputs for run in runs],
dataset_id=dataset.id,
) In the UI: open any trace, click the bookmark icon, and select a dataset. The run's input and output are added instantly. Build a regression suite from your worst production failures.
LangSmith vs Langfuse vs MLflow vs Weights & Biases
| Platform | Open-source | Self-host | Free tier | LangChain integration | Eval features |
|---|---|---|---|---|---|
| LangSmith | No | No (cloud only) | 5k traces/mo | Native (env var) | LLM-as-judge, Prompt Hub, Playground |
| Langfuse | Yes (MIT) | Yes (Docker) | Generous cloud free | Callback handler | LLM-as-judge, custom scorers, datasets |
| MLflow | Yes (Apache 2) | Yes | Fully free OSS | Manual callback | LLM eval module, metrics, model registry |
| Weights & Biases | No | Enterprise only | Free for individuals | Via Weave | Weave evals, experiment tracking, Tables |
Choose LangSmith if your stack is LangChain-first and you want the fastest path to traces and evals. Choose Langfuse if you need open-source, self-hosting, or multi-framework support. Choose MLflow if you already use it for ML experiment tracking and want LLM observability in the same system. See also: Langfuse guide · MLflow guide
Keep Your Entire LLM Stack Healthy
LangSmith tells you what your LLMs are doing. Prismix tells you when your LLM providers go down. Together they keep your AI app healthy.
Monitor LLM Provider Status →