Deciding automatically whether an answer was any good — the piece that turns a pile of test cases into a score you can watch move over time.
WHEN TO USE
SCOPE
USE FOR
Grade agent responses for accuracy with an LLM-as-judge evaluator.
Write a deterministic code check that verifies an agent's tool-call sequence.
Attach a real-time quality check to a live production project.
Capture an agent's full execution trajectory so it can be scored against an expected path.
Run a local evaluation pass on a dataset before uploading the evaluator to LangSmith.
This is a saved copy of the skill's SKILL.md instructions. It may differ from the upstream file or the version you install.
Three core components: (1) Creating Evaluators - LLM-as-Judge, custom code; (2) Defining Run Functions - capture agent outputs/trajectories for evaluation; (3) Running Evaluations - locally with evaluate() or auto-run via uploaded evaluators. Python and TypeScript examples included.
Environment Variables
LANGSMITH_API_KEY=your-api-key # Alternative to `langsmith auth login`
LANGSMITH_ENDPOINT=https://api.smith.langchain.com # SDK/CLI environment
LANGSMITH_PROJECT=your-project-name # Default for trace/run queries only
LANGSMITH_WORKSPACE_ID=your-workspace-id # Optional: for org-scoped keys
OPENAI_API_KEY=your-openai-key # For locally executed OpenAI judges
Authenticate with a saved CLI profile (preferred):
langsmith auth login
langsmith auth info
Alternatively, set LANGSMITH_API_KEY. The hidden --api-key flag remains available for compatibility, but do not place keys directly in commands or logs. Use --profile or LANGSMITH_PROFILE when selecting among saved profiles.
IMPORTANT:LANGSMITH_PROJECT defaults trace and run queries; it does not choose an evaluator target. Evaluator creation and upload require an explicit --dataset or --project.
CLI and SDK authentication are separate: A CLI OAuth profile authenticates langsmith ... commands only. Python and TypeScript SDKs do not automatically consume it. Before using an SDK during evaluator CRUD, confirm that LANGSMITH_ENDPOINT, LANGSMITH_API_KEY, and, when required, LANGSMITH_WORKSPACE_ID target the same environment and workspace as langsmith auth info. Stop if the CLI and SDK target different environments.
Use a read-only SDK preflight before any SDK-assisted CRUD:
from langsmith import Client
client = Client()
client.read_dataset(dataset_name="My Dataset")
curl -fsSL https://cli.langsmith.com/install.sh | sh
langsmith self-update
JavaScript Dependencies
npm install langsmith openai
<crucial_requirement>
Golden Rule: Inspect Before You Implement
CRITICAL: Before writing ANY evaluator or extraction logic, you MUST:
Run your agent on sample inputs and capture the actual output
Inspect the output - print it, query LangSmith traces, understand the exact structure
Only then write code that processes that output
Output structures vary significantly by framework, agent type, and configuration. Never assume the shape - always verify first. Query LangSmith traces to when outputs don't contain needed data to understand how to extract from execution.
</crucial_requirement>
<evaluator_format>
Offline vs Online Evaluators
Offline Evaluators (attached to datasets):
Function signature: (run, example) - receives both run outputs and dataset example
Use case: Comparing agent outputs to expected values in a dataset
Upload with: --dataset "Dataset Name"
Online Evaluators (attached to projects):
Function signature: (run) - receives only run outputs, NO example parameter
Use case: Real-time quality checks on production runs (no reference data)
Upload with: --project "Project Name"
CRITICAL - Return Format:
Each evaluator returns ONE metric only. For multiple metrics, create multiple evaluator functions.
Do NOT return {"metric_name": value} or lists of metrics - this will error.
CRITICAL - Local vs Uploaded Differences:
Local evaluate()
Uploaded to LangSmith
Column name
Python: auto-derived from function name. TypeScript: must include key field or column is untitled
Comes from evaluator name set at upload time. Do NOT include key — it creates a duplicate column
LLM as Judge - Uses an LLM to grade outputs. Best for subjective quality (accuracy, helpfulness, relevance).
Custom Code - Deterministic logic. Best for objective checks (exact match, trajectory validation, format compliance).
</evaluator_types>
<llm_judge>
LLM as Judge Evaluators
Use langsmith evaluator create-llm to create a server-managed LLM-as-judge run rule. It requires --model-config plus exactly one target (--dataset or --project). Supply either --prompt and --schema JSON files or a Prompt Hub reference with --hub-ref.
Native CLI CRUD for LLM-as-Judge Run Rules
The native lifecycle below manages LLM-as-judge evaluators attached to a dataset or project.
Use --project instead of --dataset for an online evaluator. Use --hub-ref owner/prompt:latest instead of --prompt and --schema when the judge prompt is stored in Prompt Hub.
Model Configuration
--model-config requires a server-supported serialized model configuration. Never invent model.json from a local LangChain model constructor. Obtain it from a known-working LangSmith evaluator, the LangSmith evaluator UI, or another documented source for the target environment. Confirm that the target server allows the serialized model class before creating or replacing the evaluator.
langsmith evaluator get does not export the complete serialized model configuration. If creation fails with Deserialization ... is not allowed, the model configuration contains a class prohibited by the server allowlist. Do not retry with guessed serialized objects; obtain a supported configuration or ask the environment administrator.
Read
# List all attached evaluator rules
langsmith evaluator list --format json
# Get every rule with this exact display name
langsmith evaluator get "Accuracy Judge"
# Narrow project rules with a project session ID
langsmith evaluator get "Accuracy Judge" --session-id <project-session-id>
get is display-name based and may return multiple rules. It reports rule metadata and selected LLM fields, but does not export a complete inline prompt, schema, and model configuration.
Update / Replace
There is no separate update subcommand. Re-run create-llm with the same name and target plus --replace; the CLI prompts before PATCHing the matching rule. Supply the complete desired LLM configuration again.
# Inspect every match before deleting
langsmith evaluator get "Accuracy Judge"
langsmith evaluator delete "Accuracy Judge"
delete is name-based and deletes all workspace run rules with that display name, even across different datasets or projects. If more than one rule matches and only one should be removed, stop rather than using the native delete command; exact ID-targeted deletion is not exposed by langsmith evaluator yet.
For rapid local development or judges that require local packages, define a local evaluator and pass it to evaluate(evaluators=[...]) instead.
from typing import TypedDict, Annotated
from langchain_openai import ChatOpenAI
class Grade(TypedDict):
reasoning: Annotated[str, ..., "Explain your reasoning"]
is_accurate: Annotated[bool, ..., "True if response is accurate"]
judge = ChatOpenAI(model="gpt-4o-mini", temperature=0).with_structured_output(Grade, method="json_schema", strict=True)
async def accuracy_evaluator(run, example):
run_outputs = run.outputs if hasattr(run, "outputs") else run.get("outputs", {}) or {}
example_outputs = example.outputs if hasattr(example, "outputs") else example.get("outputs", {}) or {}
grade = await judge.ainvoke([{"role": "user", "content": f"Expected: {example_outputs}\nActual: {run_outputs}\nIs this accurate?"}])
return {"score": 1 if grade["is_accurate"] else 0, "comment": grade["reasoning"]}
Inspect your dataset to understand expected field names (see Golden Rule above)
Test your run function and verify its output structure matches the dataset schema
Query LangSmith traces to debug any mismatches
def trajectory_evaluator(run, example):
run_outputs = run.outputs if hasattr(run, "outputs") else run.get("outputs", {}) or {}
example_outputs = example.outputs if hasattr(example, "outputs") else example.get("outputs", {}) or {}
# IMPORTANT: Replace these placeholders with your actual field names
# 1. Query your LangSmith trace to see what fields exist in run outputs
# 2. Check your dataset schema for expected field names
# Note: Trajectory data may not appear in default output - verify against trace!
actual = run_outputs.get("YOUR_TRAJECTORY_FIELD", [])
expected = example_outputs.get("YOUR_EXPECTED_FIELD", [])
return {"score": 1 if actual == expected else 0, "comment": f"Expected {expected}, got {actual}"}
function trajectoryEvaluator(run, example) {
const runOutputs = run.outputs ?? {};
const exampleOutputs = example.outputs ?? {};
// IMPORTANT: Replace these placeholders with your actual field names
// 1. Query your LangSmith trace to see what fields exist in run outputs
// 2. Check your dataset schema for expected field names
const actual = runOutputs.YOUR_TRAJECTORY_FIELD ?? [];
const expected = exampleOutputs.YOUR_EXPECTED_FIELD ?? [];
const match = JSON.stringify(actual) === JSON.stringify(expected);
return { score: match ? 1 : 0, comment: `Expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}` };
}
</code_evaluators>
<run_functions>
Defining Run Functions
Run functions execute your agent and return outputs for evaluation.
CRITICAL - Test Your Run Function First:
Before writing evaluators, you MUST test your run function and inspect the actual output structure. Output shapes vary by framework, agent type, and configuration.
Debugging workflow:
Run your agent once on sample input
Query the trace to see the execution structure
Print the raw output and verify against trace to output contains the right data
Adjust the run function as needed
Verify your output matches your dataset schema
Try your hardest to match your run function output to your dataset schema. This makes evaluators simple and reusable. If matching isn't possible, your evaluator must know how to extract and compare the right fields from each side.
def run_agent(inputs: dict) -> dict:
result = your_agent.run(inputs)
# ALWAYS inspect output shape first - run this, check the print, query traces
print(f"DEBUG - type: {type(result)}, keys: {result.keys() if hasattr(result, 'keys') else 'N/A'}")
print(f"DEBUG - value: {result}")
return {"output": result} # Adjust to match your dataset schema
async function runAgent(inputs) {
const result = await yourAgent.invoke(inputs);
// ALWAYS inspect output shape first
console.log("DEBUG - type:", typeof result, "keys:", Object.keys(result));
console.log("DEBUG - value:", result);
return { output: result }; // Adjust to match your dataset schema
}
Capturing Trajectories
For trajectory evaluation, your run function must capture tool calls during execution.
CRITICAL: Run output formats vary significantly by framework and agent type. You MUST inspect before implementing:
LangGraph agents (LangChain OSS): Use stream_mode="debug" with subgraphs=True to capture nested subagent tool calls.
import uuid
def run_agent_with_trajectory(agent, inputs: dict) -> dict:
config = {"configurable": {"thread_id": f"eval-{uuid.uuid4()}"}}
trajectory = []
final_result = None
for chunk in agent.stream(inputs, config=config, stream_mode="debug", subgraphs=True):
# STEP 1: Print chunks to understand the structure
print(f"DEBUG chunk: {chunk}")
# STEP 2: Write extraction based on YOUR observed structure
# ... your extraction logic here ...
# IMPORTANT: After running, query the LangSmith trace to verify
# your trajectory data is complete. Default output may be missing
# tool calls that appear in the trace.
return {"output": final_result, "trajectory": trajectory}
Custom / Non-LangChain Agents:
Inspect output first - Run your agent and inspect the result structure. Trajectory data may already be included in the output (e.g., result.tool_calls, result.steps, etc.)
Callbacks/Hooks - If your framework supports execution callbacks, register a hook that records tool names on each invocation
Parse execution logs - As a last resort, extract tool names from structured logs or trace data
The key is to capture the tool name at execution time, not at definition time.
</run_functions>
Uploading Evaluators to LangSmith
IMPORTANT - Auto-Run Behavior:
Evaluators uploaded to a dataset automatically run when you run experiments on that dataset. You do NOT need to pass them to evaluate() - just run your agent against the dataset and the uploaded evaluators execute automatically.
IMPORTANT - Local vs Uploaded:
Uploaded evaluators run in a sandboxed environment with very limited package access. Only use built-in/standard library imports, and place all imports inside the evaluator function body. For dataset (offline) evaluators, prefer running locally with evaluate(evaluators=[...]) first — this gives you full package access.
IMPORTANT - Code vs Structured Evaluators:
Code evaluators: Upload with langsmith evaluator upload. They run in a limited environment without external packages and work well for deterministic logic.
Structured evaluators (LLM-as-Judge): Create with langsmith evaluator create-llm using a model config and either prompt/schema files or --hub-ref.
IMPORTANT - Choose the right target:
--dataset: Offline evaluator with (run, example) signature - for comparing to expected values
--project: Online evaluator with (run) signature - for real-time quality checks
You must specify one. Global evaluators are not supported.
# List all attached evaluator rules
langsmith evaluator list
# Inspect matching rules by display name
langsmith evaluator get "Trajectory Match"
# Inspect project rules by session ID (not project name)
langsmith evaluator get --session-id <project-session-id>
# Upload offline evaluator (attached to dataset)
langsmith evaluator upload \
--name "Trajectory Match" \
--function trajectory_evaluator \
--dataset "My Dataset" \
my_evaluators.py
# Upload online evaluator (attached to project)
langsmith evaluator upload \
--name "Quality Check" \
--function quality_check \
--project "Production Agent" \
my_evaluators.py
# Replace an existing rule with the same name and target (prompts first)
langsmith evaluator upload \
--name "Trajectory Match" \
--function trajectory_evaluator \
--dataset "My Dataset" \
--replace \
my_evaluators.py
# Delete by display name (prompts first)
langsmith evaluator delete "Trajectory Match"
IMPORTANT - Safety Prompts:
upload --replace and create-llm --replace patch the matching rule and prompt first
delete NAME deletes every rule in the workspace with that display name, potentially across multiple targets; run get NAME first and inspect all matches
NEVER use --yes flag unless the user explicitly requests it
CRUD Verification
Verify only the lifecycle operations the user requested:
Confirm CLI and any SDK calls target the same environment and workspace
Verify creation with list and get
Verify replacement with --replace, when requested
Test deletion only with a unique disposable name and explicit authorization
Stop if a name resolves to multiple rules and the intended target cannot be identified safely
<best_practices>
Use structured output for LLM judges - More reliable than parsing free-text
Match evaluator to dataset type
Final Response → LLM as Judge for quality
Trajectory → Custom Code for sequence
Use async for LLM judges - Enables parallel evaluation
Test evaluators independently - Validate on known good/bad examples first
Choose the right language
Python: Use for Python agents, langchain integrations
JavaScript: Use for TypeScript/Node.js agents
</best_practices>
<running_evaluations>
Running Evaluations
Uploaded evaluators auto-run when you run experiments - no code needed. Local evaluators are passed directly for development/testing.
from langsmith import evaluate
# Uploaded evaluators run automatically
results = evaluate(run_agent, data="My Dataset", experiment_prefix="eval-v1")
# Or pass local evaluators for testing
results = evaluate(run_agent, data="My Dataset", evaluators=[my_evaluator], experiment_prefix="eval-v1")
import { evaluate } from "langsmith/evaluation";
// Uploaded evaluators run automatically
const results = await evaluate(runAgent, {
data: "My Dataset",
experimentPrefix: "eval-v1",
});
// Or pass local evaluators for testing
const results = await evaluate(runAgent, {
data: "My Dataset",
evaluators: [myEvaluator],
experimentPrefix: "eval-v1",
});
</running_evaluations>
Common Issues
Output doesn't match what you expect: Query the LangSmith trace. It shows exact inputs/outputs at each step - compare what you find to what you're trying to extract.
One metric per evaluator: Return {"score": value, "comment": "..."}. For multiple metrics, create separate functions.
Field name mismatch: Your run function output must match dataset schema exactly. Inspect dataset first with client.read_example(example_id).
RunTree vs dict (Python only): Local evaluate() passes RunTree, uploaded evaluators receive dict. Handle both:
run_outputs = run.outputs if hasattr(run, "outputs") else run.get("outputs", {}) or {}
Run langsmith auth login (or set LANGSMITH_API_KEY) so evaluator commands can reach your LangSmith workspace, and confirm the CLI and any SDK calls target the same environment via langsmith auth info.
langsmith auth login
langsmith auth info
You set: LANGSMITH_API_KEY — or sign in with langsmith auth login instead
02
Optional Add an OpenAI key for LLM judges
Set OPENAI_API_KEY when the evaluator itself calls a locally-run OpenAI model to grade outputs.
You set: OPENAI_API_KEY
Listed as free
Connected services may require an account or charge fees.
Run this outside your AI tool, using Node.js 22.20.0 or newer. Skills CLI 1.7.2 skips skill selection; prompts cancel installation without an interactive terminal. If choosing Project when asked about installation scope, open your project's folder before running this.
Install checklist
Check selected tools if a picker appears; Claude Code may be unchecked under Additional agents. ↑/↓ moves, Space toggles selections, Enter confirms.
Without a tool picker, check Installing to: for your intended tool. Stop if it names a different tool.
If asked, choose Symlink (Recommended) for shared files or Copy to all agents for separate copies; review the summary before confirming installation.
Install the find-skills skill? defaults to Yes, adding another skill for all projects. Choose No if you don't want that extra installation.
Skills CLI 1.7.2 sends install data to skills.sh by default, including the source, skill names, target tools and file details; GitHub sources are reported only when GitHub confirms the repository is public, while other remote sources can also be reported. Confirmed-public GitHub sources also trigger a security-audit request. Before installing, set the environment variable DO_NOT_TRACK=1 or DISABLE_TELEMETRY=1 to disable both.
After installing for Claude Code, open it in the installation project if you chose Project; Global makes the skill available across projects on this computer. Once Claude Code loads the skill, its description helps Claude decide when to use it.
If installation created a top-level skills folder that did not exist when your Claude Code session started, run /reload-skills in that session. Run it again after later changes in that folder.
Install the whole plugin
This route installs the LangSmith Tracing & Evaluation Skills plugin package selected for your AI tool.
PLUGIN MARKETPLACE
Add the marketplace, then install the plugin
Typed inside the agent's own prompt, not in a terminal. The marketplace is called langsmith-skills, which is the part after the @.
INVOKE THIS SKILL when building, iterating on, copying, or sharing a LangSmith Custom App — a React/TypeScript UI that runs inside LangSmith and reads the LangSmith API. Covers the langsmith apps CLI, pulling an existing app's source, replicating an app into another workspace, verifying app logic without a browser, and sanitizing an app before sending it outside your org. Uses the langsmith CLI tool.Read full description
INVOKE THIS SKILL when creating evaluation datasets, uploading datasets to LangSmith, or managing existing datasets. Covers dataset types (final_response, single_step, trajectory, RAG), CLI management commands, SDK-based creation, and example management. Uses the langsmith CLI tool.Read full description
Design, test, create, and attach LangSmith online evaluators for production traces or conversation threads. Use for workspace evaluators, run or thread rules, sampling, filters, backfills, and evaluator monitoring; use eval-engineering for Harbor tasks and agent benchmarks.Read full description
INVOKE THIS SKILL when working with LangSmith tracing OR querying traces. Covers adding tracing to applications and querying/exporting trace data. Uses the langsmith CLI tool.Read full description
Official Sentry MCP server for investigating issues, error reports, traces, and performance monitoring data from AI coding agents.Read full description
MCP-PostgreSQL-Ops is a professional MCP server for PostgreSQL database operations, monitoring, and management. Supports PostgreSQL 12-17 with comprehensive database analysis, performance monitoring, and intelligent maintenance recommendations through natural language queries.Read full description