Module 14 · Part III · Practice

The tools landscape

There are dozens of eval tools, and their marketing pages all sound the same. Underneath, they fall into five families that answer different questions. Once you see the families, and see that every tool is the same four boxes with different names, picking one becomes a short decision rather than a week of reading.

Intermediate~50 minPrerequisites: 02, 03, 13Facts checked 2026-09-29

By the end of this module you can

  • Place red-teaming scanners (garak, PyRIT), transcript analysis (Docent), shared eval collections (Inspect Evals) and third-party measurement (Artificial Analysis, OpenRouter) next to the core eval tools, and say what each can and cannot tell you.
  • Sort any eval tool into one of five families and place it on a two-axis map (offline vs online, library vs hosted platform).
  • Explain what each major tool (Inspect, promptfoo, DeepEval, Braintrust, LangSmith, Langfuse, Phoenix, Weave, Opik, MLflow, Ragas, TruLens, lm-eval-harness, HELM and the cloud services) is best at, and where it is weak.
  • Read and write the same small eval in five different tools, and translate vocabulary between them.
  • Choose a tool (or a stack of tools) for a given team, and argue the trade-offs on licensing, lock-in and data privacy.
This field moves fast: dated facts

Everything factual on this page was checked against official docs and repositories on 2026-09-29. Four changes you may not know about: OpenAI is shutting down its hosted Evals platform and graders (read-only from 2026-10-31, shut down 2026-11-30) and recommends promptfoo, which OpenAI acquired (announced 2026-03-09). Langfuse became part of ClickHouse (January 2026). Inspect is now co-developed by the UK AI Security Institute and the non-profit Meridian Labs. And Google renamed Vertex AI to Gemini Enterprise Agent Platform (April 2026). Where a detail could not be verified from a primary source, this page leaves it out rather than guess.

A mental model: five families of tools

Every tool in this module implements the pipeline from Module 01: a dataset of inputs, a system under test that produces outputs, a grader that scores them, and a metric that aggregates scores so you can compare runs. What differs is who the tool was built for and therefore which question it answers best. That gives five families.

Research harnesses "How capable or safe is this model?" Developer test and CI tools "Did my prompt or model change break it?" Observability + eval platforms "What is happening in prod, and is v2 better?" Metric and judge libraries "How do I score this kind of output?" Cloud vendor services "Can I eval where my models already run?" Inspect lm-eval-harness HELM Lighteval OpenBench Harbor Petri, Bloom legacy: simple-evals, OpenAI Evals repo promptfoo DeepEval Pydantic Evals Google ADK eval also: LangSmith and Opik pytest hooks Braintrust LangSmith Langfuse Arize Phoenix W&B Weave Opik MLflow GenAI Ragas TruLens autoevals openevals phoenix-evals Patronus AI (judge models) OpenAI Evals API shuts down 2026-11-30 Google Gen AI evaluation Microsoft Foundry evaluation Anthropic Console Evaluate tool used most by: labs, AI safety institutes, researchers product and platform teams
Five families, five questions. Tools in the same column compete with each other; tools in different columns usually complement each other. Many real teams use one tool from two or three columns at once (see "How tools compose" below).

In one sentence each:

  • Research harnesses run standardized tasks against models, often in sandboxes, with a strong focus on reproducibility. Their user is a researcher comparing models, not a product team comparing prompts.
  • Developer test and CI tools feel like a test runner. You write cases in a config file or as test functions, run a command, and get pass or fail. They plug into GitHub Actions or pytest.
  • Observability plus eval platforms start from tracing: recording every model call, tool call and step of your live application as a tree of spans (a span is one timed unit of work, such as "call the search tool"; a trace is the whole tree for one request). They add datasets, experiments and LLM judges on top, usually with a web UI for the team.
  • Metric and judge libraries give you scoring functions (faithfulness, factuality, helpfulness) and nothing else. You call them from whichever harness or platform you use.
  • Cloud vendor services are evaluation features inside a model provider's or cloud's console, convenient if you are already committed to that vendor.
Analogy: the kitchen

A research harness is a food-science lab: precise, reproducible, slow to set up. A developer test tool is the chef tasting every dish before it leaves the pass. An observability platform is the CCTV and the customer comment cards in the dining room. A metric library is the thermometer and the scales: you use them in all the other places. Cloud services are the kitchen that came pre-fitted with the building you rented.

The landscape map

Families are useful, but tools blur the edges. A second way to see the market is a map with two axes:

  • Horizontal: offline and research ↔ online and production. Offline means you run a fixed dataset before release. Online means you score real traffic after release (see Module 15).
  • Vertical: code-first library ↔ hosted platform. A library is something you pip install and run on your own machine or CI. A hosted platform has a server, a database and a team UI (run by a vendor, or by you if it is self-hostable).
offline, research, pre-release ←→ online, production traffic code-first library ←→ hosted platform hosted, pre-release production platforms research libraries self-hostable, open source lm-eval-harness Lighteval, OpenBench simple-evals (frozen) OpenAI Evals repo HELM Inspect Harbor promptfoo DeepEval Pydantic Evals ADK eval Ragas TruLens MLflow Phoenix Opik Langfuse W&B Weave LangSmith Braintrust Patronus AI Anthropic Console OpenAI Evals API † Google Gen AI eval MS Foundry eval research harness dev test / CI observability + eval metric / judge cloud service († shutting down)
The eval tools landscape (qualitative positioning, not measured data). Positions are the author's judgment of each tool's center of gravity from its docs; most tools stretch across regions. For example, Braintrust and LangSmith both run offline experiments too, and DeepEval can send results to the hosted Confident AI platform.

Read the map diagonally. The bottom-left is where frontier labs, safety institutes and academics live: free, code-first, reproducible, no production concept at all. The top-right is where product teams live once they have real users: hosted UIs, traces from production, judges running on sampled traffic. The bottom-middle is the developer's inner loop: a CLI or pytest in CI. The top-left is vendor consoles: easy, point-and-click, tied to one provider.

Key idea

The most common beginner mistake is to compare tools from different regions as if they were rivals. "Inspect or Langfuse?" is like "microscope or security camera?". The right question is usually "which harness for offline evals and which platform for production traces?".

Tool by tool

Each card gives the maker, license, language, core abstractions (the nouns you will type), what it is best at, and how it handles agents, multimodal inputs and LLM judges (Module 13). Snippets are copied from each tool's official docs or README (trimmed where marked). If a feature is not listed, it is because it could not be verified from a primary source, not necessarily because it is missing.

Research harnesses

Inspect (inspect_ai)

Maker: UK AI Security Institute and Meridian Labs (a 501(c)(3) non-profit). License: MIT. Language: Python (log viewer in TypeScript/React). Used by the UK AISI, US CAISI, EU AI Office, and the Japanese and Korean AISIs.

  • Core abstractions: a Task combines a Dataset (samples with input and target), a Solver (anything from a single generate() call to a full agent) and a Scorer (text match, model grading, or custom).
  • Best at: rigorous, reproducible research and safety evals of models and agents. Ships with 200+ pre-built evals in inspect_evals.
  • Agents and tools: the strongest here. Built-in react() agent; custom and MCP tools; built-in bash, python, text editor, web search, web browsing and computer tools; sandboxes in Docker, Kubernetes, Modal, Proxmox and Vagrant. "Agent Bridge" plugs in external agent frameworks, and Inspect SWE runs Claude Code or Codex CLI as the agent under test.
  • Multimodal: image, audio and video inputs. Judge: model_graded_qa() and other model-graded scorers. Viewing: Inspect View (web log viewer) and Inspect Scout for scanning transcripts.
from inspect_ai import Task, task
from inspect_ai.dataset import FieldSpec, hf_dataset
from inspect_ai.scorer import model_graded_qa
from inspect_ai.solver import generate

@task
def simpleqa():
    return Task(
        dataset=hf_dataset(
            "codelion/SimpleQA-Verified",
            split="train",
            sample_fields=FieldSpec(input="problem", target="answer"),
        ),
        solver=generate(),          # swap for an agent, e.g. react() with tools
        scorer=model_graded_qa(),   # an LLM judge compares output to target
    )
@task → Task(dataset, solver, scorer) Dataset Sample(input, target) Solver system under test model set at run time Scorer model_graded_qa() or match, custom input output target (the expected answer) eval log every message, score Inspect View generate() one model call: a QA eval react(tools=[bash()]) + Docker sandbox: an agent eval swap one line
Inspect in one picture. A Task wires a Dataset, a Solver and a Scorer together. The Solver is the only part that changes when you move from a single-turn question to a full agent with tools in a sandbox, which is why the same scorer and data can be reused.

Inspect Evals (the inspect_evals collection)

Maker: the UK AI Security Institute with community contributors (repository UKGovernmentBEIS/inspect_evals). What it is: not a new tool but a library of ready-made evals written for Inspect: 200+ public benchmarks, from knowledge and reasoning sets such as GPQA to agentic and coding benchmarks such as SWE-bench, each packaged as an Inspect task you can run with one command.

  • Why it matters: re-implementing a benchmark yourself is where many silent differences creep in (prompt wording, answer parsing, scorer details). Using a shared implementation makes your number comparable with other people who used the same one.
  • The catch: a shared implementation is still an implementation. It may differ from the original paper's prompt or scorer. Report "GPQA Diamond as implemented by inspect_evals, version X, 3 epochs", not just "GPQA" (Module 18).
pip install inspect-evals
# run a ready-made benchmark against any model Inspect supports
inspect eval inspect_evals/gpqa_diamond --model <provider/model> --epochs 3 --limit 50
inspect view                       # browse the logs

EleutherAI lm-evaluation-harness

Maker: EleutherAI. License: MIT. Language: Python, with tasks defined in YAML plus Jinja2 prompt templates.

  • Best at: few-shot academic benchmarks on open-weight models (60+ benchmarks, hundreds of subtasks). It is the backend of the Hugging Face Open LLM Leaderboard. Backends include Hugging Face transformers, vLLM and API models.
  • Agents: not a focus. Multimodal: prototype only (hf-multimodal, vllm-vlm), with a pointer to the lmms-eval fork.
  • Recent: CLI subcommands (lm-eval run, lm-eval ls, lm-eval validate) and a plugin system.
lm_eval --model hf \
    --model_args pretrained=EleutherAI/gpt-j-6B \
    --tasks hellaswag \
    --device cuda:0 \
    --batch_size 8

HELM (Stanford CRFM)

Maker: Stanford Center for Research on Foundation Models. License: Apache-2.0. Language: Python.

  • Best at: "holistic, reproducible and transparent evaluation of foundation models": standardized scenarios, metrics beyond accuracy, and public leaderboards (HELM Capabilities, HELM Safety, VHELM for vision-language, and domain boards).
  • Multimodal: yes, via VHELM. Agents: not its focus.
helm-run --run-entries mmlu:subject=philosophy,model=openai/gpt2 --suite my-suite --max-eval-instances 10
helm-summarize --suite my-suite
helm-server --suite my-suite   # browse results at http://localhost:8000/

Harbor (Terminal-Bench harness)

Maker: the creators of Terminal-Bench (Laude Institute). License: Apache-2.0.

  • Best at: containerised end-to-end agent evals where the agent under test is a full CLI agent (Claude Code, OpenHands, Codex CLI and more) and grading is by outcome tests inside the container. Official harness for Terminal-Bench 2.0; runs in parallel on cloud sandboxes (Daytona, Modal and others) and can generate RL rollouts. Anthropic's agent-eval post cites it.
export ANTHROPIC_API_KEY=<YOUR-KEY>
harbor run --dataset terminal-bench@2.0 \
   --agent claude-code \
   --model anthropic/claude-opus-5-5 \
   --n-concurrent 4

Smaller and legacy research tools

  • Lighteval (Hugging Face, MIT): 1000+ tasks; inspect-ai is its preferred backend. Example: lighteval eval "hf-inference-providers/openai/gpt-oss-20b" gpqa:diamond.
  • OpenBench (Groq, MIT): 95+ benchmarks built on inspect-ai. Example: bench eval mmlu --model groq/openai/gpt-oss-120b --limit 10.
  • Petri and Bloom (both started at Anthropic, both MIT, now developed by Meridian Labs): Petri is an automated auditing agent (auditor, target, judge) for alignment behaviors; Bloom auto-generates behavioral evals for one target behavior in four stages (Understanding, Ideation, Rollout, Judgment). See Module 17.
  • OpenAI simple-evals (MIT): reference implementations of MMLU, GPQA, MATH, HumanEval, SimpleQA, BrowseComp, HealthBench and others. "As of July 2025, simple-evals will no longer be updated for new models or benchmark results"; HealthBench, BrowseComp and SimpleQA are still maintained as reference code.
  • OpenAI Evals repo (openai/evals, MIT): a registry of evals defined in YAML plus JSONL data; not accepting evals with custom code. Treat it as a historical reference.

Developer test and CI tools

promptfoo

Maker: Promptfoo, now part of OpenAI (acquisition announced 2026-03-09): "Promptfoo remains open source and MIT licensed." License: MIT. Language: TypeScript/Node CLI; you write config in YAML.

  • Core abstractions: prompts × providers (models) × tests (each with vars and assert). Assertion types include equals, contains, contains-json, javascript, similar and llm-rubric.
  • Best at: declarative regression matrices (every prompt against every model against every test) and red teaming (automated vulnerability scanning). OpenAI's recommended replacement for its Evals platform.
  • Judge: the llm-rubric assertion. CI: the GitHub Action promptfoo/promptfoo-action@v1 posts eval diffs on pull requests. Agents: agent and RAG testing are listed features.
prompts:
  - file://prompt1.txt
  - file://prompt2.txt
providers:
  - openai:gpt-6-luna
  - id: vertex:gemini-3.5-flash
    config:
      region: global
tests:
  - vars:
      language: French
      input: Hello world
    assert:
      - type: llm-rubric
        value: does not describe self as an AI, model, or chatbot

DeepEval (Confident AI)

Maker: Confident AI. License: Apache-2.0. Language: Python. Optional hosted platform (Confident AI, commercial).

  • Core abstractions: LLMTestCase (input, actual output, expected output, context), metrics such as GEval, and assert_test(), run by pytest or deepeval test run.
  • Best at: "unit tests for LLMs": pytest-style assertions with a large catalog of metrics.
  • Agents: metrics TaskCompletion, ToolCorrectness, GoalAccuracy, StepEfficiency, PlanAdherence; trajectory evaluation via @observe() tracing. Multimodal: multimodal metrics (for example image generation and editing quality). Judge: G-Eval, and most metrics are judge-based.
from deepeval import assert_test
from deepeval.metrics import GEval
from deepeval.test_case import LLMTestCase, SingleTurnParams  # older docs: LLMTestCaseParams

def test_case():
    correctness = GEval(
        name="Correctness",
        criteria="Determine if the 'actual output' is correct based on the 'expected output'.",
        evaluation_params=[SingleTurnParams.ACTUAL_OUTPUT, SingleTurnParams.EXPECTED_OUTPUT],
        threshold=0.5,
    )
    tc = LLMTestCase(input="What if these shoes don't fit?",
                     actual_output="You have 30 days to get a full refund at no extra cost.",
                     expected_output="We offer a 30-day full refund at no extra costs.")
    assert_test(tc, [correctness])

Pydantic Evals and Google ADK eval

  • Pydantic Evals (Pydantic): code-first Case, Dataset, Evaluator and LLMJudge, with span-based evaluation of agent internals over OpenTelemetry and a Logfire UI.
  • Google ADK eval: for agents built with Google's Agent Development Kit. .test.json unit files and .evalset.json multi-turn sets; criteria such as tool_trajectory_avg_score (exact tool-call sequence match), response_match_score (ROUGE-1), final_response_match_v2 (LLM-judged), hallucinations_v1 and multi_turn_task_success_v1; run with adk eval or pytest's AgentEvaluator. More in Module 06.
from pydantic_evals import Case, Dataset

dataset = Dataset(name='capital_quiz', cases=[Case(name='simple_case',
          inputs='What is the capital of France?', expected_output='Paris')])

async def guess_city(question: str) -> str:
    return 'Paris'

dataset.evaluate_sync(guess_city).print()

Giskard and Strands Evals

  • Giskard (Giskard AI, a French company): an open-source Python testing library (the repository is now Giskard-AI/giskard-oss, described as an evaluation and testing library for LLM agents) plus a commercial hub. It is best known for two things. The scan automatically probes an LLM app for weaknesses such as prompt injection, harmful content, sensitive-information disclosure, hallucination and lack of robustness, then turns what it finds into a reusable test suite. RAGET generates a question-and-answer test set from your own knowledge base to evaluate a RAG pipeline (Module 06). The library has been reorganized more than once, so copy code from its current docs rather than from older blog posts.
  • Strands Evals: AWS's open-source Strands Agents SDK has a companion evaluation package for agents built with it, with checks on the final output and on the agent's trajectory (the sequence of tool calls), including LLM-judged ones. It is young, its API is still moving, and its details could not be re-checked against a primary source for this page; if you build on Strands, start from the evaluation section of the Strands documentation. If you do not, it is one more example of the pattern this module keeps showing: every agent framework now ships its own eval harness, and all of them share the dataset, task, scorer shape.

Observability plus eval platforms

One trace = one request time → 0 s 4.2 s ▾ request "refund #4471" ▸ llm: plan ▸ tool: lookup_order ▸ llm: draft reply ▸ tool: issue_refund Each row is a span; the whole tree is the trace. Click a span to see its exact input and output. Scores attached to the trace judge: over-promise?FAIL user feedbackthumbs down latency4.2 s cost$0.012 tools called2 + add to dataset
What an observability platform stores. Every step of a request is recorded as a timed span inside one trace, and scores from judges, users and code are attached to it. The key eval feature is the button at the bottom right: a failing production trace becomes a regression test in one click. Values are illustrative.

Braintrust

Maker: Braintrust (commercial SaaS). Its scorer library autoevals is MIT-licensed, in Python and TypeScript. No open-source platform repository was found.

  • Core abstractions: Eval(name, data, task, scores); Experiments ("a permanent record of how your task performed on the dataset"), Datasets, Scorers; braintrust.auto_instrument() for tracing; online scoring of production logs; "Loop", an in-UI assistant.
  • Best at: a tight eval → experiment → compare loop plus production logging in one UI, with Python and TypeScript parity.
  • Judge: autoevals LLM-as-judge scorers (Factuality, ClosedQA, Battle, Summarization, SQL, Translation and more) plus RAG, embedding and heuristic scorers. CI: run evals in GitHub Actions to catch regressions.
from braintrust import Eval
from autoevals import ExactMatch

Eval(
    "Evaluation quickstart",
    experiment_name="Movie matcher (Python)",
    data=[{"input": "A detective investigates a series of murders based on the seven deadly sins.",
           "expected": "Se7en"}],
    task=task,          # def task(input): -> str (calls the model)
    scores=[ExactMatch],
)

LangSmith

Maker: LangChain. License: SDK MIT (Python and JS/TS); the hosted platform is commercial.

  • Core abstractions: Dataset, Target function, Evaluators, Experiments. LLM judges via the openevals package (create_llm_as_judge). Tracing is the core product (for example wrappers.wrap_openai).
  • Best at: teams on LangChain or LangGraph who want tracing, datasets, experiments and annotation in one place; it also works without LangChain via wrappers.
  • CI: pytest (Python) and jest/vitest (JS) integrations.
from langsmith import Client
from openevals.llm import create_llm_as_judge
from openevals.prompts import CORRECTNESS_PROMPT

def correctness_evaluator(inputs, outputs, reference_outputs):
    judge = create_llm_as_judge(prompt=CORRECTNESS_PROMPT, model="openai:o3-mini",
                                feedback_key="correctness")
    return judge(inputs=inputs, outputs=outputs, reference_outputs=reference_outputs)

Client().evaluate(target, data="Sample dataset", evaluators=[correctness_evaluator],
                  experiment_prefix="first-eval-in-langsmith", max_concurrency=2)

Langfuse

Maker: Langfuse, "now part of ClickHouse" (January 2026). License: "MIT licensed, except for the ee folders" (an open-core model: the core is open source, some enterprise features are not). Self-host via Docker Compose, Helm or Terraform, or use the cloud.

  • Core abstractions: traces and observations, Datasets, Experiments (run_experiment(data, task, evaluators)), Scores / Evaluation, prompt management.
  • Best at: open-source, self-hostable observability plus evals, for example when data must stay in your region. Anthropic's agent-eval post mentions it as a self-hosted alternative.
  • Judge: LLM-as-judge, code evaluators, user feedback and manual labeling. Tracing: OpenTelemetry, LangChain, OpenAI SDK and LiteLLM integrations.
from langfuse import get_client, Evaluation
langfuse = get_client()

def accuracy_evaluator(*, input, output, expected_output, metadata, **kwargs):
    ok = expected_output and expected_output.lower() in output.lower()
    return Evaluation(name="accuracy", value=1.0 if ok else 0.0)

result = langfuse.run_experiment(name="Geography Quiz", data=local_data,
                                 task=my_task, evaluators=[accuracy_evaluator])
print(result.format())

Arize Phoenix

Maker: Arize AI. License: Elastic License 2.0 (ELv2), which is source-available, not OSI open source: you can read, run and self-host the code, but the license restricts offering it as a managed service. arize-phoenix-evals is also ELv2. Language: Python and TypeScript.

  • Core abstractions: OpenTelemetry / OpenInference traces, evaluators (LLM classifiers), datasets and experiments, prompt management, a playground.
  • Agents: integrations include the Claude Agent SDK, OpenAI Agents, LangGraph and CrewAI; a remote MCP server lets coding agents query your traces.
  • Judge: create_classifier with an LLM.
from phoenix.evals import create_classifier
from phoenix.evals.llm import LLM

llm = LLM(provider="openai", model="gpt-4o")
evaluator = create_classifier(
    name="helpfulness",
    prompt_template="Rate the response to the user query as helpful or not:\n\nQuery: {input}\nResponse: {output}",
    llm=llm,
    choices={"helpful": 1.0, "not_helpful": 0.0},
)
scores = evaluator.evaluate({"input": "How do I reset?", "output": "Go to settings > reset."})

W&B Weave

Maker: Weights & Biases. License: Apache-2.0. SDKs: Python and TypeScript.

  • Core abstractions: @weave.op (a traced function: inputs and outputs are captured automatically), Model, Evaluation(dataset, scorers), evaluation.evaluate(model), and EvaluationLogger for logging evals imperatively from your own loop.
  • Best at: teams already using W&B for ML experiments who want LLM traces and evals in the same place.
import weave, asyncio
from weave import Evaluation, Model

weave.init('intro-example')

@weave.op()
def match_score1(expected: str, output: dict) -> dict:
    return {'match': expected == output['generated_text']}

class MyModel(Model):
    prompt: str
    @weave.op()
    def predict(self, question: str):
        return {'generated_text': 'Hello, ' + question + self.prompt}

evaluation = Evaluation(dataset=examples, scorers=[match_score1])
asyncio.run(evaluation.evaluate(MyModel(prompt='World')))

Opik (Comet)

Maker: Comet. License: Apache-2.0, full platform self-hostable. SDKs: Python, TypeScript (Ruby via OpenTelemetry).

  • Features: tracing for multi-step agents, LLM-as-judge metrics (Hallucination, Moderation, AnswerRelevance, ContextPrecision), datasets and experiments, an Agent Optimizer SDK, guardrails, and "a PyTest integration to test LLM pipelines on every commit".
from opik import track

@track                       # traces this function
def my_function(input: str) -> str:
    return input

# the evaluate() call as shown in Opik's docs:
evaluation = evaluate(dataset=dataset, task=evaluation_task, scoring_metrics=[Hallucination()])

MLflow GenAI evaluation (MLflow 3)

Maker: open-source project originally from Databricks. License: Apache-2.0. Python plus TS/JS and Java SDKs; self-host, or managed on Databricks, SageMaker or Azure ML.

  • Core abstractions: mlflow.genai.evaluate(data, predict_fn, scorers); data rows with inputs and expectations; built-in LLM judges (Correctness, Guidelines) and custom @scorer functions. OpenTelemetry-based tracing, 50+ built-in metrics, prompt registry, AI gateway.
  • Agents: evaluation of "LLM applications and AI agents", plus production monitoring and human feedback.
import mlflow
from mlflow.genai import scorer
from mlflow.genai.scorers import Correctness, Guidelines

@scorer
def is_concise(outputs: str) -> bool:
    return len(outputs.split()) <= 5

eval_dataset = [{"inputs": {"question": "What is the capital of France?"},
                 "expectations": {"expected_response": "Paris"}}]

results = mlflow.genai.evaluate(
    data=eval_dataset,
    predict_fn=qa_predict_fn,     # def qa_predict_fn(question: str) -> str
    scorers=[Correctness(), Guidelines(name="is_english", guidelines="The answer must be in English"), is_concise],
)

Galileo

Maker: Galileo (commercial SaaS, with enterprise deployment options). What it is: an evaluation and observability platform for LLM apps and agents: tracing, experiments, metrics dashboards and real-time checks on production traffic.

  • Distinctive idea: Luna, which Galileo calls "evaluation foundation models": small models trained to act as evaluators, pitched as a cheaper and faster alternative to running a large LLM judge on every trace, and fast enough to use as an inline guardrail (Module 15 explains why that latency matters).
  • Agents: Galileo has marketed an agent reliability offering (including a free tier announced in 2025) aimed at tracing and scoring multi-step agents.
  • How to judge it: like any vendor judge, a Luna score is someone else's grader. Before you gate on it, measure its agreement with your own human labels on your own traces (Module 13). Its SDK syntax could not be verified from a primary source for this page, so no snippet is shown.

Metric and judge libraries

Ragas

Maker: VibrantLabs (formerly Exploding Gradients; the repo is still explodinggradients/ragas). License: Apache-2.0. Language: Python.

  • Core abstractions: metrics (LLM-based and traditional, for example DiscreteMetric), SingleTurnSample, EvaluationDataset, experiments, and test-set generation.
  • Best at: RAG metrics (faithfulness, context precision and recall; see Module 06) and generating synthetic test sets.
from openai import AsyncOpenAI
from ragas.metrics import DiscreteMetric
from ragas.llms import llm_factory

llm = llm_factory("gpt-4o", client=AsyncOpenAI())
metric = DiscreteMetric(
    name="summary_accuracy",
    allowed_values=["accurate", "inaccurate"],
    prompt="Evaluate if the summary is accurate and captures key information.\nResponse: {response}\nAnswer with only 'accurate' or 'inaccurate'.",
)
score = await metric.ascore(llm=llm, response="The summary of the text is...")
print(score.value, score.reason)

TruLens

Maker: TruEra, now part of Snowflake. License: MIT. Language: Python.

  • Core abstractions: TruSession, feedback functions / Metric (judges backed by a model provider), a TruApp wrapper, @instrument span types, and a leaderboard. Known for the RAG Triad: groundedness, context relevance, answer relevance.
  • Agents: evaluators LogicalConsistency, ExecutionEfficiency, PlanAdherence, PlanQuality, ToolSelection, ToolCalling, ToolQuality; MCP tool calls are captured as spans. Tracing: OpenTelemetry-native, exportable to Jaeger, Grafana Tempo or Datadog.
from trulens.core import TruSession, Metric
from trulens.providers.openai import OpenAI
from trulens.apps.app import TruApp

session = TruSession()
provider = OpenAI(model_engine="gpt-4-turbo")
f_groundedness = Metric(
    implementation=provider.groundedness_measure_with_cot_reasons_consider_answerability,
    name="Groundedness")
tru_rag = TruApp(rag, app_name="RAG", feedbacks=[f_groundedness])
with tru_rag as recording:
    rag.query("What is ...?")
session.get_leaderboard()

Other scorer packages and judge models

  • autoevals (Braintrust, MIT), openevals (LangChain) and arize-phoenix-evals (ELv2) are standalone scorer libraries you can call from any harness, not only their parent platform.
  • Patronus AI (commercial) sells judge models rather than a harness: Glider ("3B evaluator LLM that can score any text input on user-defined criteria"), Lynx (hallucination detection), and Percival ("evaluation copilot for agentic systems built to detect 20+ failure modes in agentic traces"), plus experiments, logging and multimodal (image-to-text) judging. Its SDK syntax could not be verified, so no snippet is shown.

Cloud vendor services

OpenAI Evals API and graders (being shut down)

Status: "OpenAI is deprecating the Evals platform... Evals will become read-only for existing users on October 31, 2026, and the platform is scheduled to shut down on November 30, 2026." Graders are being deprecated too. Announced 2026-06-03, with an official migration guide to promptfoo.

  • Core abstractions (still worth learning, because they are clean): an Eval holds a data_source_config (a JSON-schema item_schema describing each row) and testing_criteria (a list of graders). A Run executes that eval against data plus a model and prompt. Templates reference {{ item.* }} (the dataset row) and {{ sample.output_text }} (the model's output).
  • Grader types: string_check, text_similarity (fuzzy match, BLEU, ROUGE…), score_model, label_model, python, multi. The same graders were used for reinforcement fine-tuning.
eval_obj = client.evals.create(
    name="IT Ticket Categorization",
    data_source_config={"type": "custom", "item_schema": {...}, "include_sample_schema": True},
    testing_criteria=[{
        "type": "string_check", "name": "Match output to human label",
        "input": "{{ sample.output_text }}", "operation": "eq",
        "reference": "{{ item.correct_label }}",
    }],
)

Agent evals and trace grading. OpenAI's docs also describe evaluating whole agent workflows, not just single responses. Trace grading attaches graders to the trace of an agent run (the record of model calls, tool calls, handoffs and guardrail checks that the Agents SDK captures), so you can score where in a workflow things went wrong, not only whether the final answer was right. The AgentKit launch (October 2025) bundled Agent Builder, a visual workflow editor, with eval features such as datasets, trace grading and automated prompt optimization. These sit on the same hosted evals and graders stack whose deprecation is described above, so check their status on OpenAI's deprecations page before building on them. The idea outlives the product: grade the trajectory, not just the answer (Module 05). Module 16 covers OpenAI's agent-eval approach in depth.

Google, Microsoft and Anthropic

  • Google Gen AI evaluation service (in Gemini Enterprise Agent Platform, formerly Vertex AI): two paths, the GenAI Client in the Agent Platform SDK (client.evals) and the older EvalTask module. Metric types: rubric-based (managed and adaptive rubrics), computation-based, and custom functions; judge model configuration; AutoSxS pairwise comparison; dedicated agent-evaluation docs.
  • Microsoft Foundry evaluation: the azure-ai-evaluation SDK with quality, RAG, safety and agent evaluators (tool call accuracy, task completion) and OpenTelemetry tracing.
  • Anthropic Console Evaluate tool (announced 2024-07-09): generate prompts and test cases, run them, compare prompt versions side by side, and let subject-matter experts grade on a 5-point scale. Its current feature set could not be re-verified in 2026. Anthropic's bigger contribution to tooling is guidance (the "Demystifying evals for AI agents" post and the "develop tests" docs) and the open-source Petri and Bloom.
# Google GenAI Client (from the python-aiplatform README; model id may be dated)
inference_results = client.evals.run_inference(model="gemini-2.5-flash-preview-05-20", src=prompts_df)
eval_result = client.evals.evaluate(
    dataset=inference_results,
    metrics=[types.Metric(name='exact_match'), types.Metric(name='rouge_l_sum'), types.RubricMetric.TEXT_QUALITY],
)

Beyond the five families: red teaming, transcripts, public numbers

Three more kinds of tool sit next to the five families. They are not rivals to your harness or platform; each answers a question the others do not. Red-teaming scanners ask "how can this be broken?". Transcript analysis tools ask "what is actually happening across thousands of runs?". Third-party measurement asks "what do independent runs say about models I have not tested yet?". The map at the end of this section places them next to the tools you already know.

Red-teaming scanners

The tools above mostly run datasets you wrote. Red-teaming scanners bring the dataset with them: large, curated families of attacks (jailbreaks, prompt injection, encoding tricks, data-leak bait), a way to send them to your model or app, and a detector that decides whether each attack got through. Think of them as an eval tool with an adversarial test generator built in. The concepts behind them (attack success rate, injection, jailbreak robustness) are in Module 17 and Module 25; here is how the two best-known open-source scanners are built.

garak: sweep many known attacks, like a network scanner Probes attack prompts by family Generator the model or app Detectors flag failed responses Report failure rate per probe PyRIT: orchestrate adaptive, multi-turn attacks Orchestrator single or multi-turn attack Converters encode, translate, rephrase Target model, app or endpoint Scorers judge or classifier score feeds back: an attacker LLM adapts its next turn (for example Crescendo) every exchange is stored, so a human can review and reuse successful attacks
Two shapes of automated red teaming. garak is breadth-first: many fixed attack families, one pass, a report of which ones got through. PyRIT is depth-first: it composes transformations and runs adaptive conversations where an attacker model reacts to each reply. Either way, the detector or scorer decides what counts as a "hit", so it needs validating like any judge.

garak

Maker: NVIDIA (open source; repository NVIDIA/garak, tagline "the LLM vulnerability scanner"). Language: Python CLI.

  • Core abstractions: probes (families of attack prompts: jailbreaks, prompt injection, encoding tricks, data leakage, toxicity, malware generation and more), generators (connectors to the model or app under test), detectors (decide whether a response shows the failure), and a report with the failure rate per probe. Its README compares it to network tools such as nmap and Metasploit, but for LLMs.
  • Best at: a broad, repeatable sweep of known weaknesses before launch and after every model swap.
python -m pip install -U garak
export OPENAI_API_KEY="..."
# run the encoding-based prompt-injection probes against one hosted model
python -m garak --model_type openai --model_name gpt-4o-mini --probes encoding
# flag names change between releases (newer ones also accept --target_type and
# --target_name); check `python -m garak --help` for your installed version

PyRIT

Maker: Microsoft (its AI Red Team). "The Python Risk Identification Tool for generative AI", open source (repository microsoft/PyRIT). Language: Python library, usually driven from notebooks.

  • Core abstractions: targets (the model, app or endpoint), converters (transform a prompt: encodings, translation, rephrasing, and other modalities), scorers (LLM judges or classifiers that decide whether an attack succeeded), memory (every exchange stored for later analysis), and orchestrators or attack strategies that run single-turn batches or multi-turn attacks such as Crescendo, where an attacker model escalates step by step. Recent releases have reorganized these names, so follow the current docs.
  • Best at: helping a human red team scale up: automating the boring parts, composing attacks, and keeping a searchable record. Multi-turn attacks matter for agents, which are usually broken over several turns, not one.
A scanner finds failures; it does not give you a safety score

Attack success rates from different scanners are not comparable: they use different attack sets, different detectors and different definitions of "success". Use a scanner as a discovery tool. The failures it finds become cases in your own regression suite (run by Inspect, promptfoo or DeepEval), graded by a detector you have checked against human labels. promptfoo's red-team mode and Giskard's scan, covered above, play the same role inside tools you may already use.

Transcript analysis

Once agent evals produce thousands of long transcripts, reading them all is impossible and reading ten at random misses rare problems. A new kind of tool helps a human search and summarize transcripts at scale. This is error analysis (Module 12) with power tools.

Docent (Transluce)

Maker: Transluce, a non-profit AI research lab. What it is: a tool for analyzing large collections of agent transcripts, as described on its site: you load the runs from an eval, then ask questions in plain language ("find runs where the agent edited the tests", "which runs gave up after a tool error?"), cluster similar behaviors, and jump to the exact moments that match.

  • Best at: finding what the score hides: broken tasks, environment bugs, reward hacking, agents that found an answer key, or a failure mode that only appears in 2% of runs. These are exactly the problems that make a benchmark number lie (Module 18).
  • How it fits: it complements your eval harness rather than replacing it. Inspect Scout (in the Inspect card above) and Patronus Percival (judge libraries, above) aim at related problems. Whatever the tool, an LLM that searches transcripts can miss or invent matches, so open and read the transcripts it points you to before you believe a pattern.

Third-party measurement

Finally, some sources are not tools you run at all: they are organizations that run evals and publish the numbers. They are useful for a shortlist and dangerous as a final answer.

Artificial Analysis

An independent company that runs its own evaluations of models and of the API endpoints that serve them. It publishes a composite Intelligence Index (built from about ten evals across agentic tasks, coding, scientific reasoning and general knowledge, with weights and versions documented on its methodology page), and it measures output speed, latency and price per provider. Good for "which three models should I test?". Remember that a composite index reflects its authors' choice of evals and weights, that the index version changes over time, and that its harness is not yours.

OpenRouter

An API router: one endpoint and one bill for many models from many providers. Its public rankings show which models and apps consume the most tokens through OpenRouter. That is a usage signal (popularity, price-performance as judged by real buyers), not a quality score, and it covers only OpenRouter's own traffic. A second lesson it makes visible: the same open-weights model can be served by several providers, and endpoints can differ (for example in quantization, context limits or tool-call handling), so evaluate the exact endpoint you will use.

offline, pre-release ←→ online, production code-first library ←→ hosted platform Inspect OpenAI Evals API (ending) promptfoo DeepEval Langfuse LangSmith Braintrust Inspect Evals garak PyRIT Strands Evals Giskard scan + RAGET; hub is hosted Docent transcripts from both sides Galileo Luna evaluators Outside the map numbers others publish; you read, not run Artificial Analysis index, speed, price OpenRouter usage rankings related: public leaderboards (Module 18) already on the map eval collection red-team scanner dev test platform / analysis public measurement
The landscape map, extended (qualitative positioning, not measured data). Same axes as the first map. Most new arrivals sit in the offline, code-first half, because red teaming and benchmark collections run before release. Docent sits on the crossing point because transcripts come from both offline runs and production. Artificial Analysis and OpenRouter are drawn outside the map on purpose: they are sources of numbers, not tools in your pipeline.

What changed recently

Tool choice is partly a bet on who will still maintain the tool in two years. The last two years saw acquisitions, handovers and one shutdown.

202420252026 Jul 2024Anthropic ConsoleEvaluate tool Jul 2025simple-evals frozen(no new models) Oct 2025Petri releasedlater to Meridian Labs Dec 2025Bloom releasedlater to Meridian Labs Jan 2026Langfuse becomespart of ClickHouse 9 Mar 2026OpenAI to acquirepromptfoo Apr 2026Vertex AI renamed GeminiEnterprise Agent Platform 3 Jun 2026OpenAI Evalsdeprecation announced 31 Oct 2026OpenAI Evalsbecomes read-only 30 Nov 2026OpenAI Evalsshuts down new tool absorbed by a bigger company handed to a neutral maintainer frozen or renamed shut down
Two years of churn (dates from vendor announcements). July 2024 to November 2026. Notice the pattern: independent tools get absorbed (promptfoo into OpenAI, Langfuse into ClickHouse, TruLens into Snowflake earlier), and lab-built tools move to neutral maintainers (Petri and Bloom to Meridian Labs).

The comparison matrix

Legend: Y first-class, P partial or via integration, – not a focus, ? not verified from a primary source (treat as unknown, not as "no"). Sources are the per-tool cards above and the list at the end.

ToolLicenseLangPrimary useAgents / toolsMultimodalLLM judgeTracingCI hookUI
InspectMITPyResearch and safety evals of models and agentsY react, sandboxes, MCP, bridgeYYLog viewer + ScoutCLILocal viewer
lm-eval-harnessMITPyFew-shot academic benchmarks–P prototype––CLI–
HELMApache-2.0PyHolistic standardized leaderboards–Y VHELM?–CLIStatic leaderboard
HarborApache-2.0?Containerised CLI-agent benchmarksY–?–CLI–
simple-evalsMITPyReference benchmark code (frozen)P BrowseComp–?–––
promptfooMIT (OpenAI-owned)TS / YAMLRegression matrices + red teamingP?Y llm-rubric?Y GH ActionLocal viewer
DeepEvalApache-2.0PyPytest-style metric testsY ToolCorrectness etc.YY G-EvalY @observeY pytestConfident AI SaaS
BraintrustClosed; autoevals MITPy / TSExperiments + production loggingP?Y autoevalsYY GH ActionsSaaS
LangSmithSDK MIT; platform closedPy / TSTracing + datasets + experimentsP?Y openevalsYY pytest, vitest, jestSaaS
LangfuseMIT except eePy / TSOSS observability + evalsP?YY OTel?Self-host or cloud
Arize PhoenixELv2 (source-available)Py / TSOTel tracing + evalsY integrations?YY OpenInference?Self-host
W&B WeaveApache-2.0Py / TSTracing + Evaluation objectsP??Y @weave.op?SaaS
OpikApache-2.0Py / TSOSS tracing + evals + optimizerP?YYY pytestSelf-host or cloud
MLflow GenAIApache-2.0Py (+TS, Java)Eval + tracing + monitoringY?Y built-in judgesY OTel?Self-host or managed
RagasApache-2.0PyRAG metrics, test-set generation??Y–?–
TruLensMITPyRAG triad + agent evaluatorsY?YY OTel?Local dashboard
Patronus AIClosed?Judge models, agent trace debuggingY PercivalY image-to-textYY?SaaS
OpenAI Evals APIClosed, ends 2026-11-30APIHosted evals + RFT gradersP?Y score / label model–APIDashboard
Google Gen AI eval / ADKClosed servicePyRubric + agent trajectory evalsY trajectory metrics?Y rubrics?Y pytest AgentEvaluatorCloud console
Inspect EvalsOpen sourcePy200+ ready-made benchmark implementations for InspectY agentic benchmarks?P via Inspect scorersInspect logsCLIInspect View
GiskardOpen-source library; hub commercialPyVulnerability scan, RAG test-set generationP?Y??Hub
Strands EvalsOpen sourcePyEvals for agents built on StrandsY trajectory checks?????
GalileoClosed?Observability + evals, Luna evaluator modelsP?Y LunaY?SaaS
garakOpen source (NVIDIA)PyLLM vulnerability scanning??P detectors–CLIReport files
PyRITOpen source (Microsoft)PyRed-team orchestration, multi-turn attacksY multi-turnP convertersY scorersMemory store?Notebooks
Docent??Searching and clustering agent transcriptsY transcripts?P LLM-powered searchIngests runs–Web UI
Anthropic ConsoleClosedUITest-case generation + side-by-side–?Human 5-point grading––Console
How to read a "?"

A question mark means the feature was not confirmed on the tool's own docs or README when this page was written. Several of these tools very likely do support multimodal inputs or CI in some form. Before you rule a tool in or out on one of those cells, check its current docs yourself: vendors ship monthly.

Same eval, five tools

The fastest way to understand a tool is to write the same tiny eval in it. Here is the spec, in plain English:

  • Dataset: two questions, "What is the capital of France?" (expected: Paris) and "What is the capital of Australia?" (expected: Canberra). Australia is a classic trap: models sometimes say Sydney.
  • System under test: a model answering the question.
  • Grader: an LLM judge that decides whether the answer is correct compared with the expected answer (a model-graded rubric, see Module 13). Where cheap, also a code check that the expected word appears.
  • Metric: fraction of samples passing.
You write You run Results land in Inspect capitals.py (@task) inspect eval log file → Inspect View promptfoo promptfooconfig.yaml promptfoo evalor the GitHub Action prompt × model grid inlocal viewer / PR comment DeepEval test_capitals.py deepeval test run(or plain pytest) pass / fail per test, withscore and judge's reason Braintrust capitals_eval.py Eval(...) run the file; SDKuploads every row an Experiment in the web UI,diffed against the last one OpenAIEvals API client.evals.create evals.runs.create Eval + Run objects on OpenAIservers (ends 2026-11-30)
The shape of each tool. Same eval, different center of gravity: Inspect and DeepEval are code you run locally, promptfoo is a config file, Braintrust is code that reports to a server, and the OpenAI Evals API is configuration that lives on someone else's server.

1. Inspect

A Python function decorated with @task returns a Task. The dataset can be a plain list of Sample objects. model_graded_qa() asks a judge model whether the output answers the question correctly given the target.

from inspect_ai import Task, task
from inspect_ai.dataset import Sample
from inspect_ai.scorer import model_graded_qa
from inspect_ai.solver import generate

@task
def capitals():
    return Task(
        dataset=[
            Sample(input="What is the capital of France?", target="Paris"),
            Sample(input="What is the capital of Australia?", target="Canberra"),
        ],
        solver=generate(),         # the system under test: one model call
        scorer=model_graded_qa(),  # LLM judge: is the answer correct vs target?
    )

# Run from a shell (the model is chosen at run time, not in the file):
#   inspect eval capitals.py --model openai/gpt-4o
# then open the log in Inspect View:  inspect view

Notice what is not in the file: the model. Inspect treats the model as a run-time parameter, because its users mostly compare many models on the same task. To turn this into an agent eval you would change one line, the solver, to an agent such as react() with tools and a sandbox.

2. promptfoo

No code at all. The YAML file declares prompts, providers (models) and tests. Every test is run against every prompt × provider combination.

# promptfooconfig.yaml
prompts:
  - "Answer in one short sentence: {{question}}"
providers:
  - openai:gpt-4o
tests:
  - vars:
      question: What is the capital of France?
    assert:
      - type: contains          # cheap code check first
        value: Paris
      - type: llm-rubric        # LLM judge with a plain-English rubric
        value: Correctly states that Paris is the capital of France, with no false claims
  - vars:
      question: What is the capital of Australia?
    assert:
      - type: contains
        value: Canberra
      - type: llm-rubric
        value: Correctly states Canberra, and does not claim Sydney is the capital

# Run:  npx promptfoo eval     (then:  npx promptfoo view)

The grid is the point: add a second prompt and a second provider and you get a 2 × 2 × 2 comparison for free. This is why promptfoo is popular for "which model should we switch to?" questions and for CI diffs on pull requests.

prompts P1: terse P2: friendly × providers model A model B × tests (+ asserts) France → Paris Australia → Canberra = 2 × 2 × 2 = 8 cells, 8 model calls test \ prompt · model P1 · model A P1 · model B P2 · model A P2 · model B France PASS PASS PASS PASS Australia FAILsaid "Sydney" PASS PASS PASS ↑ the grid points at one combination Illustrative results. Each cell runs every assert for its test: contains "Canberra", then the llm-rubric judge.
The promptfoo grid. Inputs multiply: every prompt runs on every provider for every test. A red cell tells you exactly which prompt and model combination broke on which test, which is what makes promptfoo good at "should we switch models?" questions and at CI diffs.

3. DeepEval

Each sample becomes a pytest test. The judge is a GEval metric (G-Eval: the judge writes evaluation steps from your criteria, then scores). A test fails when the score is below threshold.

# test_capitals.py
import pytest
from deepeval import assert_test
from deepeval.metrics import GEval
from deepeval.test_case import LLMTestCase, SingleTurnParams

from my_app import answer   # your system under test: str -> str

correctness = GEval(
    name="Correctness",
    criteria="Determine if the 'actual output' is correct based on the 'expected output'.",
    evaluation_params=[SingleTurnParams.ACTUAL_OUTPUT, SingleTurnParams.EXPECTED_OUTPUT],
    threshold=0.5,
)

@pytest.mark.parametrize("question,expected", [
    ("What is the capital of France?", "Paris"),
    ("What is the capital of Australia?", "Canberra"),
])
def test_capital(question, expected):
    tc = LLMTestCase(input=question, actual_output=answer(question), expected_output=expected)
    assert_test(tc, [correctness])

# Run:  deepeval test run test_capitals.py

If your team already lives in pytest, this feels native. The trade-off: pytest thinks in pass/fail per test, while evals think in rates across a dataset (Module 04). One flaky judge call fails the build, so thresholds and repeats need care.

4. Braintrust

One call to Eval() with data, task and scores. The result is uploaded as an Experiment that the UI compares with previous experiments row by row.

# capitals_eval.py
from braintrust import Eval
from autoevals import Factuality     # an LLM-as-judge scorer from autoevals

from my_app import answer

def task(input):
    return answer(input)             # the system under test

Eval(
    "Capitals",                      # project name
    data=[
        {"input": "What is the capital of France?", "expected": "Paris"},
        {"input": "What is the capital of Australia?", "expected": "Canberra"},
    ],
    task=task,
    scores=[Factuality],             # judge compares output with expected
)

Langfuse (run_experiment(data, task, evaluators)), LangSmith (evaluate(target, data, evaluators)), MLflow (genai.evaluate(data, predict_fn, scorers)), Weave (Evaluation(dataset, scorers).evaluate(model)) and Opik (evaluate(dataset, task, scoring_metrics)) all have this same three-argument shape. Learn one and you can read the others.

5. OpenAI Evals API (for migration and reading old code)

Do not start new work here

The hosted Evals platform becomes read-only on 2026-10-31 and shuts down on 2026-11-30. OpenAI's own migration guide moves users to promptfoo. The code is shown because its split between schema, graders and runs is a clean design, and because you may inherit it.

from openai import OpenAI
client = OpenAI()

# 1) The Eval: what a row looks like + how to grade. No data, no model yet.
eval_obj = client.evals.create(
    name="Capitals",
    data_source_config={
        "type": "custom",
        "item_schema": {
            "type": "object",
            "properties": {"question": {"type": "string"}, "answer": {"type": "string"}},
            "required": ["question", "answer"],
        },
        "include_sample_schema": True,
    },
    testing_criteria=[{
        "type": "score_model",                  # LLM judge that returns a number
        "name": "correct_capital",
        "model": "o4-mini-2025-04-16",
        "input": [
            {"role": "system", "content": "You are an expert grader. Score 1 if the model answer names the reference city as the capital, else 0."},
            {"role": "user", "content": "Reference: {{ item.answer }}. Model answer: {{ sample.output_text }}"},
        ],
        "range": [0, 1],
        "pass_threshold": 0.5,
    }],
)

# 2) The Run: this data + this model + this prompt, graded by the Eval above.
run = client.evals.runs.create(
    eval_obj.id,
    name="gpt-4o baseline",
    data_source={
        "type": "responses",
        "model": "gpt-4o",
        "input_messages": {"type": "template", "template": [
            {"role": "user", "content": "{{ item.question }}"},
        ]},
        "source": {"type": "file_id", "id": "YOUR_FILE_ID"},   # uploaded JSONL of items
    },
)

What the five shapes teach

ToolWhere the model is chosenWhere the judge prompt livesNatural unit of result
InspectCommand line at run timeInside the scorer (default template, overridable)An eval log per task × model
promptfooproviders list in YAMLThe llm-rubric valueA grid of prompt × provider × test
DeepEvalInside your app codecriteria of the GEval metricPass or fail per pytest test
BraintrustInside your taskThe autoevals scorerAn Experiment, compared with earlier ones
OpenAI Evals APIThe Run's data_sourceThe score_model grader's messagesA Run on the server

Rosetta stone: the same concepts, different names

Every tool has the same five or six concepts under different names. This table is worth bookmarking; it lets you read any tool's docs in minutes.

1. One rowinput + expected 2. Systemproduces the output 3. Graderscores the output 4. Run recordstored, compared InspectSampleSolverScorereval log promptfootest varsprompt × providerasserteval DeepEvalLLMTestCaseyour appmetric (GEval)test run Braintrustdata rowtaskscorerExperiment LangSmithexampletarget functionevaluatorexperiment MLflowinputs/expectationspredict_fnscorerevaluation run OpenAI Evalsitemmodel + prompttesting_criteriaRun Read down a column: same idea, different word. The full table below adds more tools and the trace column.
The four boxes behind every tool. Whatever the vocabulary, each tool takes a row of data, runs a system on it, grades the output and stores the run so you can compare it with the next one. Once you can map a new tool's nouns onto these four columns, you can read its docs quickly.
ToolOne row of dataThe eval definitionSystem under testGraderOne executionRecorded steps
This coursesampletask / evalsystem (model + scaffold)graderrun / trialtranscript / trace
Anthropic (agent-eval post)taskevaluation suiteagent in a harnessgradertrialtranscript
InspectSample in a DatasetTaskSolver (e.g. react())Scorereval log (epochs = repeats)transcript in Inspect View
promptfootest (vars)config fileprompt × providerassertevalresult row
DeepEvalLLMTestCasetest fileyour appmetric (e.g. GEval)test run@observe trace
Braintrustrow / Dataset recordEval(...)taskscorerExperimenttrace / span
LangSmithexample in a Datasetevaluate(...)target functionevaluatorexperimentrun tree / trace
Langfusedataset itemrun_experiment(...)taskevaluator → Evaluation (score)experimenttrace / observation
Phoenixdataset exampleexperimenttaskevaluatorexperimentspan (OpenInference)
Weavedataset rowEvaluationModel.predictscorer (@weave.op)evaluation runcall (@weave.op)
MLflowrow with inputs / expectationsgenai.evaluate(...)predict_fnscorer / judgeevaluation runtrace
Pydantic EvalsCaseDatasettask functionEvaluator / LLMJudgereportspans (OTel)
OpenAI Evals APIitem (item_schema)Evalmodel + prompt in the Rungrader (testing_criteria)Run–
Expert nuance: "experiment" is overloaded

In Braintrust, LangSmith, Langfuse and Phoenix, an experiment is one execution of a dataset through a version of your system, stored so you can diff it against another. In science, an experiment is the whole comparison. When someone says "run an experiment", ask whether they mean one run, or a controlled comparison of two runs with a significance test (Module 04). Most platforms show you the diff but leave the statistics to you.

Which tool should I use?

Start from the question you need answered, not from a feature list. The tree below covers most real situations.

What are you evaluating? Standard benchmarks on open-weight models? Need production traces and a team UI? a model my app Must self-host or stay open source? What shape of test do you want? yes no lm-eval-harnessor Lighteval, HELM Inspect(Harbor for CLI agents) Langfuse, Phoenixor Opik, MLflow (self-host) Braintrust, LangSmithor W&B Weave (hosted) promptfooYAML matrix, CI diffs, red team DeepEval, Pydantic Evalstests as Python code Ragas, TruLensRAG metrics (inside a harness) Your cloud's eval serviceGoogle ADK / Gen AI eval, Foundry yes no: agents, safety, custom yes no
Which tool should I use? A starting point, not a law. The leaves on the right are families of good answers; within a leaf, pick by language, existing stack and who needs to see results. Most teams end up with one leaf from the top half of the app branch plus one from the bottom half.

The same tree, as rules of thumb

Research on frontier models or safety

Inspect. It is what government AI safety institutes use, it has sandboxes and agent tooling built in, and 200+ ready-made evals. Add Harbor if your agent is a full CLI agent on Terminal-Bench style tasks. See Module 16.

Classic benchmarks on open weights

lm-evaluation-harness (the Open LLM Leaderboard backend), Lighteval, or HELM if you want its holistic metrics and leaderboards.

CLI + CI + red teaming

promptfoo. Config in YAML, a GitHub Action that comments diffs on pull requests, and a strong red-teaming feature set. Also the migration path off the OpenAI Evals API.

Pytest-style unit tests

DeepEval (large metric catalog including agent metrics) or Pydantic Evals (lightweight, OpenTelemetry span-based). LangSmith and Opik also offer pytest integrations.

Production tracing + experiments UI

Hosted and polished: Braintrust or LangSmith (especially on LangChain/LangGraph), or Weave if you already use W&B. Self-hosted or open: Langfuse, Phoenix, Opik, MLflow.

RAG quality

Ragas or TruLens metrics (faithfulness, context relevance, the RAG triad), called from whatever harness you already run.

Single-vendor stack

On Google: ADK eval and the Gen AI evaluation service. On Azure: Foundry evaluation. OpenAI-only: the hosted Evals API is ending, so use promptfoo (now OpenAI-owned) instead.

Red teaming and security scans

garak for a broad sweep of known attack families; PyRIT for orchestrated, multi-turn and human-in-the-loop red teaming; promptfoo or Giskard if you want scans inside the tool that already runs your tests. Turn every finding into a regression case (Module 25).

Too many transcripts to read

Docent or Inspect Scout to search and cluster agent runs; your trace platform's filters for production. Then read the transcripts they surface yourself (Module 12).

Caveats

No tool fixes a bad dataset or an unvalidated judge. Most of the value comes from error analysis and judge calibration, which you can do in any of these tools, or in a spreadsheet.

A useful tie-breaker: who needs to look at the results?

If only engineers read results, a CLI and CI output are enough. If product managers, domain experts or annotators need to read transcripts and label them, you want a platform with a UI and annotation queues. Hamel-style error analysis (Module 12) depends on people actually reading traces, so the viewing experience matters more than the metric catalog.

How tools compose

In a mature team the families click together into a loop. Production traces become datasets; datasets feed offline evals; offline evals gate deploys in CI; online judges score live traffic; failing traces become new dataset rows. Each box can be a different tool.

Agent + tracing OTel, @observe, @weave.op, @track Trace store Langfuse, Phoenix, Braintrust, LangSmith Curated dataset failing traces + human labels Offline eval harness Inspect, promptfoo, DeepEval, Braintrust Eval() + Ragas… CI gate GitHub Action, pytest: block merge on regression Deploy new prompt, model or tool version Online judges score a sample of live traffic export curate run on scores vs baseline pass traffic write scores users hit the new version; the agent keeps emitting traces
A composed eval stack. The top row is the offline path (before shipping), the bottom row the online path (after shipping). A single platform can cover several boxes (Braintrust, LangSmith and Langfuse cover trace store, datasets, experiments and online judges), but the harness and CI box is often a separate tool.

Three concrete, common stacks:

  • Lean open-source stack: OpenTelemetry tracing into self-hosted Langfuse or Phoenix; datasets exported from failing traces; promptfoo or DeepEval in GitHub Actions as the gate; Ragas metrics if retrieval matters.
  • All-in-one hosted: Braintrust or LangSmith for tracing, datasets, experiments, CI evals and online scoring, with autoevals or openevals judges.
  • Research lab style: Inspect tasks with sandboxes for capability and safety evals, Inspect Scout to scan transcripts for anomalies, and Harbor for Terminal-Bench style CLI-agent runs. No production tracing at all, because the "product" is a model.
Expert nuance: OpenTelemetry is the glue

Phoenix (OpenInference), Langfuse, MLflow, TruLens, Pydantic Evals, Opik and Microsoft Foundry all speak OpenTelemetry (OTel), the open standard for traces and spans. If your application emits OTel spans, you can switch trace stores, or send the same spans to two of them, without rewriting instrumentation. Vendor-specific decorators are convenient but are the first place lock-in creeps in. Standard naming for GenAI spans is still settling, so check exactly which attributes each tool reads.

Open source vs hosted: licenses, lock-in, privacy

Licenses are a spectrum, not a switch

more control, more ops work less ops work, more dependence Permissive OSS MIT or Apache-2.0 Inspect, promptfoo, DeepEval, Ragas, TruLens, Opik, MLflow, lm-eval, HELM, Harbor run anywhere, fork if the vendor changes direction Open core / source-available Langfuse MIT except ee folders Arize Phoenix Elastic License 2.0 self-host freely; some features or uses are restricted Open SDK, hosted platform Braintrust autoevals MIT LangSmith SDK MIT W&B Weave code is portable; your history lives with them Closed service console or API OpenAI Evals API Google Gen AI eval Anthropic Console Patronus AI zero setup; can be changed or shut down by the vendor
The license spectrum. Licenses as stated in each project's repository on 2026-09-29. "Open source" in the strict (OSI) sense means the permissive column; Elastic License 2.0 is source-available, not OSI-approved. The OpenAI Evals shutdown is the textbook example of right-hand-side risk.

Where your data goes

Eval data is often your most sensitive data: real user conversations, internal documents retrieved by RAG, customer records seen by tools. Before choosing, trace the path each byte takes.

Local library your laptop / CI runner dataset, outputs, logs stored data never leaves Inspect, promptfoo, DeepEval (without cloud) Self-hosted platform your app (traces) your VPC trace DB stays in your account; you run upgrades, backups Langfuse, Phoenix, Opik, MLflow SaaS platform your app (traces) vendor cloud vendor stores traces: check DPA, region, retention Braintrust, LangSmith, Weave LLM judge's model API receives the input, output and reference for every graded sample judge calls
Where eval data travels. The deployment model decides where traces are stored. But every model-graded metric sends the graded text to whichever model provider runs the judge, in all three set-ups, unless you point the judge at a model you host yourself. Privacy reviews often miss this second path.

Open source / self-host wins when

  • Data residency or regulation forbids sending traces to a third party.
  • You want to read and patch the scorer code (reproducibility for research).
  • You fear vendor churn: an MIT project can be forked if its owner changes course.
  • Scale makes per-trace SaaS pricing expensive.

Hosted wins when

  • You have no one to run a database, upgrades and backups.
  • Non-engineers need a polished UI for review and annotation today.
  • You value integrated features (online scoring, playgrounds, in-app assistants) over control.
  • Your security team has already approved the vendor.

Lock-in: what actually traps you

Switching tools is usually cheap for code and expensive for history. Rank the lock-in risks:

  1. Your datasets and labels. Months of curated failure cases and human annotations are the real asset. Make sure you can export them (JSONL or CSV) and keep a copy in your own repo or bucket.
  2. Experiment history. Baselines you compare against. If you switch, re-run your current best system on the new tool to create a new baseline; do not compare scores across tools, because graders and prompts differ.
  3. Instrumentation. Vendor decorators across your codebase. Prefer OpenTelemetry where offered.
  4. Judge prompts. A built-in "Factuality" or "Correctness" judge is someone else's prompt, and it may change between versions. For anything you gate a release on, own the judge prompt and version it (Module 13).
  5. Eval code shape. The least sticky: as the Rosetta table shows, the data, task, scorers shape ports in an afternoon.
Case study: the OpenAI Evals shutdown

Teams that defined evals on OpenAI's hosted platform in 2025 now have until 2026-11-30 to migrate, with OpenAI's cookbook guide pointing to promptfoo. Their eval logic (schemas, grader prompts) ports; their run history on the platform does not come along automatically. The lesson is not "never use hosted tools". It is: keep datasets and grader definitions in version control you own, whatever tool runs them.

Key takeaways

  1. Eval tools fall into five families (research harnesses, developer test and CI tools, observability plus eval platforms, metric and judge libraries, cloud services), and each answers a different question.
  2. Every tool is the same four boxes with different names: a row of data, a system under test, a grader, and a stored run. Learn the mapping and any tool's docs become readable.
  3. Tools from different families usually complement each other. A common stack is one offline harness in CI plus one platform for production traces.
  4. Pick by the question you need answered and by who reads the results, not by the length of the metric catalog.
  5. Licenses are a spectrum: permissive open source, open core or source-available (Langfuse, Phoenix), open SDK with a hosted platform, and fully closed services.
  6. An LLM judge sends graded text to its model provider even when the eval library runs locally. Privacy reviews must cover that path.
  7. The real lock-in is your datasets, labels and judge prompts. Keep them in version control you own; the OpenAI Evals shutdown shows why.
  8. Next to the five families sit red-teaming scanners (garak, PyRIT), transcript analysis (Docent, Inspect Scout) and third-party measurement (Artificial Analysis, OpenRouter rankings). Scanners discover failures, analysis tools find patterns, public numbers build a shortlist; none of them replaces your own eval.
  9. A score from a shared implementation or a public index is "benchmark as implemented by X, version Y". Pin and report the version, and do not compare attack success rates across different scanners.

Check yourself

1. A startup with a customer-support agent in production wants to see real conversations, have a PM label bad ones, and turn them into a regression set. Which family should they look at first?

They need traces from production, a UI for a non-engineer to label, and datasets built from traces: that is exactly the observability plus eval family. A harness like promptfoo or DeepEval can then run the regression set in CI.

2. In Inspect, which component would you change to turn a single-turn QA eval into an agent eval with bash access in a Docker sandbox?

The Solver is "the system under test" in Inspect: from a single generate() to a full react() agent with tools. The dataset and scorer can stay the same.

3. What is the license status of Arize Phoenix?

Phoenix and phoenix-evals are under ELv2. You can self-host, but ELv2 restricts some uses (such as offering it as a managed service), so it is not open source in the OSI sense.

4. Your company runs its evals on OpenAI's hosted Evals API. What is the situation as of late 2026?

OpenAI announced the deprecation on 2026-06-03 and published a migration guide to promptfoo, which it acquired earlier in 2026. The renaming in option 3 is Google's Vertex AI.

5. You use a fully local, open-source eval library with an LLM-as-judge metric that calls a hosted model API. Does sensitive data leave your machine?

Where traces are stored and where graded text is sent are two separate questions. Any model-graded metric sends the text to whoever runs the judge model, unless you self-host that model.

6. Braintrust calls it an Experiment, LangSmith an experiment, Inspect an eval log, OpenAI a Run. What are they all?

They are all "one run" records. A proper comparison (with confidence intervals) compares two of them, which most tools display but leave the statistics to you.

7. Before launch, you want to throw hundreds of known jailbreak, encoding and prompt-injection attacks at your agent and see which get through. Which tool is built for that?

Scanners bring the attack dataset and a detector with them. Treat their output as discovery: the failures become regression cases, and the detector needs checking against human labels before you trust its hit rate.

8. A model tops OpenRouter's rankings this month. What does that tell you?

Rankings reflect what OpenRouter's customers use, which mixes price, speed, habit and quality. Use it, and indexes such as Artificial Analysis, to build a shortlist, then run your own eval on the exact endpoint you will deploy.
Interview questions on eval tooling (with model answers)

Q: Why would a frontier-safety team use Inspect rather than an observability platform?
Their system under test is a model, not a deployed app, so there is no production traffic to trace. They need sandboxed agent environments (Docker, Kubernetes), reproducible logs, many models per task, and a shared library of evals that other institutes also run. Inspect is built for exactly that; observability platforms are built around production traces and team dashboards.

Q: You are asked to migrate 40 evals off the OpenAI Evals API. What is your plan?
Export the item schemas, data files and grader definitions. Map each grader type: string_check becomes a code assertion, score_model or label_model becomes an llm-rubric or custom judge with the same prompt. Re-run the current production system on the new tool to set a fresh baseline before comparing anything, because judge templates differ. Store datasets and grader prompts in your repo so the next migration is cheaper.

Q: Two tools report different faithfulness scores for the same outputs. Which is right?
Possibly neither. Same-named metrics in different libraries use different judge prompts, models and aggregation. Validate each against a small human-labeled set (agreement, false positive and negative rates; Module 13) and trust the one that agrees with your humans on your data.

Q: What is the main lock-in risk with an eval platform, and how do you mitigate it?
Datasets, labels and history, not code. Keep canonical datasets and judge prompts in version control, export regularly, and use OpenTelemetry instrumentation so traces can be redirected.

Sources and further reading