Experiments
NeMo Experiments is the comparison layer for agent optimization tasks, such as evaluating the impact of changes to a harness, infrastructure, tools, or agent code. It provides one place to visualize and compare evaluation results from Harbor, the NeMo Optimizer, NeMo Evaluator, or your own runner. You can rank these results by cost, latency, evaluator scores, and other metrics.
Those metrics are derived from NeMo Intake observability data, the same traces and evaluator results your runs already produce, so any runner that lands telemetry in Intake feeds the same comparison.
Before You Start
Who This Is For
NeMo Experiments is for anyone running evaluations on their agent who needs a way to compare, analyze, and promote the results. For example: engineers iterating on prompts, models, tools, or routing; teams benchmarking many models or configurations at once; and reviewers who need a shared leaderboard to decide what to promote.
Requirements
- A NeMo Platform environment with the
intakeservice running. - The platform entity store (Postgres).
- A reachable ClickHouse database.
- A producer that creates Evaluations and sends their telemetry: the NeMo Optimizer, a benchmark or evaluation framework such as Harbor, or a direct application programming interface (API) integration.
- Recommended: NeMo Studio for the complete web user interface (UI),
including trace comparison views, a customizable leaderboard, and Pareto charts. The API provides
the same data. The Experiments UI is gated by the
VITE_FF_EXPERIMENTfeature flag, which is off by default.
How It Works
What It Does
Experiments computes comparable, always-current metrics for your evaluation runs. For each run it rolls up cost, latency, tokens, and per-evaluator scores from the underlying telemetry in ClickHouse and returns them as ranked rows. Rollups are computed at read time, so a leaderboard always reflects current telemetry, with no denormalized score table to maintain.
You can group runs by an insight to investigate, a model comparison, a benchmark leaderboard, or promoted runs from several groups. A single run can belong to more than one group. Sorting, filtering, and pinning within a group surface the relevant runs.
When to Use It
Use Experiments when you need to:
- Compare candidates from the optimizer, a prompt or model change, or a routing strategy against a baseline.
- Run a benchmark leaderboard: import many runs into one Experiment and rank them by the metric that matters.
- Track iteration over time: keep one Experiment per project so successive attempts stay side by side.
- Standardize comparison across a team: everyone reads the same metrics, in the same place, with the same vocabulary.
Experiments are most useful after real evaluation telemetry exists. A new group can start empty and fill in as runs land.
Core Concepts and Data Model
Experiments sit on top of Intake’s telemetry hierarchy (span → trace → session):
- An Experiment is a named container of Evaluations. It holds durable metadata (
description,summary, free-formmetadata, optionalinsight_id) and view configuration: adefault_sortand apareto(default X/Y metrics for the Pareto view). - An Evaluation is one run and one leaderboard row. It records producer-supplied fields
(
dataset_name,dataset_version,source_link,metadata,description,status,root_cause), theexperiment_idsit belongs to (at least one; an Evaluation can live in more than one Experiment), and an optionalparent_evaluation_idlinking a variant back to the run it was derived from. - A Session is one test-case execution within an Evaluation, a single ingested run made of spans. Sessions carry per-case status, latency, token and cost totals, and evaluator scores.
At read time, each Evaluation is enriched with rollups derived from its sessions in ClickHouse:
Metric aggregates expose these statistics: sum, mean, median, p90, p95, p99, count. A
metric path is therefore test_case_count, cost_usd.<stat>, latency_ms.<stat>,
tokens.<stat>, or evaluators.<name>.<stat>. Sorting and filtering use the same grammar.
Two things about evaluator rollups specifically:
- Response shape.
evaluators.<name>.<stat>is the sort/filter query grammar. The Evaluation JSON response returns the same scores underaggregate_scores, a map keyed by evaluator name. Each value contains the statistics above, and anevaluator_nameslist appears alongside it. There is noevaluatorsfield in the response;evaluators.<name>.<stat>(query) readsaggregate_scores[<name>].<stat>(response). - Missing-value semantics. Evaluator rollups are test-case-weighted: each stat is computed over
test_case_count, the full set of test cases, with a test case that did not report a given evaluator counted as0rather than dropped.
Two Experiment-level behaviors are worth knowing:
- Default sort. An Experiment stores a
default_sort(a sort-param string such as-evaluators.solved.mean) so its leaderboard opens ordered by the metric the team cares about. It defaults to-created_at(newest first). - Pinning. Any Evaluation can be pinned to the top of its Experiment, such as the current baseline. Pins are workspace-shared: everyone with access sees the same pinned set, regardless of the active sort.
Get Started
Setup
Experiments are part of the intake service, so any running NeMo Platform already serves them. Point
at whatever you have, whether a deployed platform or a local one from nemo setup or
nemo quickstart up:
Set NMP_STUDIO_URL explicitly if Studio uses a different origin or path.
The examples use bearer-token authentication and stop on HTTP errors. For a local development
deployment with authentication disabled, omit the Authorization header and the
NMP_ACCESS_TOKEN command.
ClickHouse must be reachable either way, since the leaderboard rollups are computed from it at read time.
Running from source (local development)
If you are bringing the pieces up yourself from a repository checkout, make sure Docker Desktop or
the Docker daemon is running. Intake automatically provisions and reuses a local ClickHouse
container for the resolved NeMo data directory unless NMP_INTAKE_CLICKHOUSE_URL explicitly points
to an external instance.
-
Backend services:
intakeplus itsauthandentitiesdependencies.--portdefaults to8080; omituv runif you installed thenemocommand-line interface (CLI): -
Studio (optional, for the leaderboard and drill-down UI). From the
web/workspace, with the Experiments feature flag on and intake enabled for trace drill-down:
Confirm that the entity read path and ClickHouse rollups are reachable:
The first request checks the entity store and can return 200 while ClickHouse is unavailable. The
second request explicitly sorts by a rollup metric. A 200 response from both requests is healthy.
A 503 response from the second request means that Intake cannot compute ClickHouse rollups.
First Workflow
Create an Experiment, add an Evaluation, send it telemetry, then see it in Studio and through the API.
1. Create the Experiment (the leaderboard container):
Capture its id for the next step:
2. Add an Evaluation to it. experiment_ids is a list, so an Evaluation belongs to one or more
existing Experiments:
An Evaluation is a durable record. Its leaderboard metrics appear after its evaluation telemetry lands in Intake.
3. Send it telemetry. Send the run’s telemetry to Intake in the same way as other agent runs, whether it comes from the optimizer, a benchmark framework like Harbor, or your own code. Tag each session with the Evaluation’s identity:
- For Agent Trajectory Interchange Format (ATIF) and chat-completions, add a top-level
evaluation_contextobject to the ingest payload carryingevaluation_nameandtest_case_name. - For OpenTelemetry Protocol (OTLP), set
nemo.evaluation.nameandnemo.test_case.nameon each trace’s root span.
The per-evaluator scores on the leaderboard come from evaluator results captured on those
sessions. Intake can derive them from ATIF verifier rewards. OTLP traces carry session telemetry, so
the framework or caller must publish their scores through the evaluator-results endpoint. Refer to
Capture Evaluator Results for both
paths, and Observe Agents for the ingestion paths themselves.
The nemo-experiments-upload skill walks this through end to end.
test_case_name is required for a populated leaderboard. A session tagged with only evaluation_name
still ingests and appears in the Evaluation’s session list, but it does not count toward
test_case_count or any rollup. The row therefore reads as all zeros, with tokens, model, and agent
blank too. Always send test_case_name alongside evaluation_name.
Confirm It Worked
List the Experiment’s Evaluations and confirm the new row is present:
Then open $NMP_STUDIO_URL/workspaces/$WORKSPACE/experiment, then open
reranker-prompt-iteration.
A successful result opens the Experiment in Studio and shows your Evaluation as a row. After
its sessions are ingested the row shows non-zero test_case_count, cost, latency, tokens, and
evaluator scores. Sorting by a metric reorders the table, and opening the Evaluation lists its
individual test cases.
Common Workflows
Add an Evaluation to an Existing Experiment
This is the everyday operation: an Experiment already exists and you want to record another run in it.
Create the Evaluation with the Experiment’s id in experiment_ids:
Associate an Evaluation with Another Experiment
An Evaluation can belong to several Experiments simultaneously, which is useful when the same run should appear on both a per-project board and a cross-project benchmark. To demonstrate adding a second membership, first create the second Experiment and capture its ID:
Then PATCH the existing Evaluation’s experiment_ids with both IDs. The list must stay non-empty:
Update an Evaluation
Use PATCH for partial updates: only the fields you send change. name, dataset_name, and
dataset_version are immutable:
PUT does a full replacement of the mutable fields. Omitted fields reset, so prefer PATCH for individual
edits.
Rank an Experiment by the Metric That Matters
List an Experiment’s Evaluations sorted by a metric. Prefix the field with - for descending:
You can sort by an entity column (name, created_at) or any rollup metric (test_case_count,
cost_usd.<stat>, latency_ms.<stat>, tokens.<stat>, evaluators.<name>.<stat>). In Studio, click
a column header. If the Experiment has a default_sort, the leaderboard opens already ordered that
way.
Filter to the Evaluations You Care About
Filter by a metric range to narrow the leaderboard. For example, select only Evaluations whose average cost is under $0.50:
Metric filters use the same grammar as sort, such as filter[test_case_count][\$gte]=5 or
filter[evaluators.groundedness.mean][\$gte]=0.8. You can also filter by
filter[metadata.<key>]=<value>, filter[status]=<value>, filter[is_pinned]=true, and
created_at/updated_at ranges. In Studio, use the column filters on cost, latency, test-case count,
and evaluator columns.
Set an Experiment’s Default Sort
Store the ordering the team should see first so no one has to re-sort each visit:
In Studio, set it from the Experiment’s Edit dialog.
Pin a Baseline to the Top
Keep the current baseline, or any reference run, at the top of the Experiment for everyone:
Pinned Evaluations float to the top of the leaderboard regardless of the active sort. List only the
pinned set with filter[is_pinned]=true.
Drill into an Evaluation’s Test Cases
Open one Evaluation’s sessions to see per-test-case behavior: status, latency, cost, and evaluator scores:
Use this to move from “this candidate scores lower” to “these specific cases regressed.” In Studio, open the Evaluation row to reach its sessions, then follow a session into its trace in Intake.
Configure the Pareto View
Each Experiment stores a pareto configuration: the default X/Y metrics for its Pareto chart in
Studio, defaulting to cost vs. latency. The axes are x_metric and y_metric, and each takes a base
metric ID: cost_usd, latency_ms, or evaluators.<name>, with no .<stat> suffix. Set it on
create or update:
Delete an Experiment or Evaluation
Deleting an Experiment soft-deletes it. An Evaluation that belongs only to that Experiment is also
soft-deleted. A shared Evaluation remains active, and the deleted Experiment is removed from its
experiment_ids membership. Deleting an Evaluation directly soft-deletes only that Evaluation.
Soft deletion renames the stored record. A GET request that uses the original name does not return
the deleted record. To audit deleted records, use filter[is_deleted]=true on a list operation:
Where Evaluations Come From
You typically do not create Evaluations manually. Common producers include:
- Optimizer: records each run as an Experiment and its candidates as Evaluations, so results land automatically. Refer to Optimize Agents.
- Evaluation framework: a framework like Harbor sends trajectories through Intake’s ATIF or OTLP ingest, publishes its scores as evaluator results, and records each run as an Evaluation. Refer to Observe Agents.
- Direct API: create the Experiment and Evaluations, then ingest their sessions, for a custom evaluation pipeline.
Do It with an Agent
If you are working with a coding agent, the nemo-experiments-upload skill automates this whole path:
create an Experiment, add an Evaluation, log traces and scores to an ingest endpoint, and verify the
rollups. It ships with reference guides for the ATIF/Harbor, chat-completions, and OTLP ingest formats
and a troubleshooting matrix. Invoke it when you want to upload, log, ingest, or publish evaluation
runs to NeMo Experiments.
Operations
Limits
- An Experiment is sorted and filtered in memory over the full set of its Evaluations, bounded to
1,000 Evaluations per Experiment. A request that would select more is rejected with
413rather than returned partially sorted. Narrow it with filters. - Page size is capped at 1,000 records.
- Metric sorting and filtering require rollups. If ClickHouse is unavailable, a metric sort or filter
returns
503rather than a silently unsorted result. Sorting and filtering by entity columns (name,created_at) still works.
Security and Access Control
All Experiments endpoints are workspace-scoped under /apis/intake/v2/workspaces/{workspace}/, and
the service checks workspace access before reading or writing.
Evaluation metadata, source_link, and related fields are producer-supplied and surfaced to
reviewers, so treat them like any other telemetry payload. Do not store secrets, credentials, or
regulated data unless your deployment’s policy permits it.
Retention and Storage
Experiment and Evaluation metadata lives in the platform entity store and persists until you delete it. This metadata does not expire with telemetry. Span and trace-index records in ClickHouse expire after 90 days. Evaluator-result rows do not use that 90-day time-to-live (TTL) setting.
All leaderboard rollups depend on the retained trace index. Evaluator score rollups join the retained trace index to evaluator-result rows at read time. After a trace-index entry expires, its evaluator scores no longer appear on the leaderboard even if the evaluator-result rows remain. Cost, latency, token, test-case count, and evaluator score rollups therefore reflect the retained 90-day trace window.
Troubleshooting
Related Topics
- Observe Agents: the telemetry these leaderboards are computed from, and how to ingest it.
- Agent Evaluation: the task-driven evaluation model that produces these runs.
- Optimize Agents: the optimizer that creates Experiments and Evaluations automatically.