Agent Evaluation Quickstart

View as Markdown

In this quickstart you’ll evaluate an agent on two tasks, score its answers, and produce a run bundle with a browsable HTML report — all on your machine, with no platform services and no API keys. It takes about five minutes.

For the concepts behind tasks, trials, runners, and metrics, see Agent Evaluation. This page is the hands-on version.

Prerequisites

  • Python 3.11–3.14
  • The SDK:
$pip install nemo-platform[nemo-evaluator-sdk]

Everything here runs in a single local Python process. You’ll swap the stand-in agent for a real model or deployed agent once you’ve seen the flow.

1. Define a metric

A metric scores one trial. It implements three things: a type (its name), an output_spec() (the values it emits), and compute_scores() (the scoring logic). Here’s a tiny one that scores 1.0 when the agent’s answer contains an expected keyword and 0.0 otherwise. It reads the agent’s answer from input.candidate.output_text and the task’s grader-only reference from input.row.data.

1from nemo_evaluator_sdk.metrics.protocol import MetricInput, MetricOutput, MetricOutputSpec, MetricResult
2
3
4class KeywordMatchMetric:
5 """Score 1.0 when the agent's answer contains the expected keyword, else 0.0."""
6
7 @property
8 def type(self) -> str:
9 return "keyword_match"
10
11 def output_spec(self) -> list[MetricOutputSpec]:
12 return [MetricOutputSpec.continuous_score("score")]
13
14 async def compute_scores(self, input: MetricInput) -> MetricResult:
15 expected = str(input.row.data.get("reference", {}).get("expected", "")).lower()
16 answer = (input.candidate.output_text or "").lower()
17 return MetricResult(outputs=[MetricOutput(name="score", value=1.0 if expected and expected in answer else 0.0)])

2. Define your tasks

Each AgentEvalTask is one unit of work: an intent, the inputs the agent acts on (here, an instruction), a grader-only reference (held-out truth the agent never sees), and the metrics that score this task. The intent is a human-readable note about the task’s goal — metadata for whoever reads or maintains the suite. It is not passed to the agent, which only ever sees inputs. Because metrics live on the task, different tasks can use different scorers.

1from nemo_evaluator_sdk.agent_eval.tasks import AgentEvalTask
2
3
4def make_tasks() -> list[AgentEvalTask]:
5 return [
6 AgentEvalTask(
7 id="capital-france",
8 intent="Answer the geography question.",
9 inputs={"instruction": "What is the capital of France?"},
10 reference={"expected": "Paris"},
11 metrics=[KeywordMatchMetric()],
12 ),
13 AgentEvalTask(
14 id="capital-japan",
15 intent="Answer the geography question.",
16 inputs={"instruction": "What is the capital of Japan?"},
17 reference={"expected": "Tokyo"},
18 metrics=[KeywordMatchMetric()],
19 ),
20 ]

3. Provide an agent

An agent is anything that turns a task into an answer. The simplest option is an async function; the SDK provides a runner — CallableAgentTaskRunner — that wraps your function so it plugs into a run. The runner hands your function the whole task and expects an answer back (here, a canned response keyed by task id). We’ll use a stand-in so the quickstart runs with no external services; later you’ll point the evaluation at a real model or a deployed agent instead.

1async def my_agent(task: AgentEvalTask) -> str:
2 # Stand-in agent — replace with a real model or deployed agent later.
3 answers = {
4 "capital-france": "The capital of France is Paris.",
5 "capital-japan": "The capital of Japan is Tokyo.",
6 }
7 return answers[task.id]

4. Run the evaluation

AgentEvaluator.run() sends the tasks to the runner, collects the trials, scores them, and returns an AgentEvalResult. Setting output_dir also writes a run bundle to disk. (run() is async, so it lives inside an async function — see the full script below.)

1from nemo_evaluator_sdk.agent_eval.evaluator import AgentEvaluator
2from nemo_evaluator_sdk.agent_eval.runtimes.callable_runtime import CallableAgentTaskRunner
3from nemo_evaluator_sdk.agent_eval.tasks import AgentEvalRunConfig
4
5result = await AgentEvaluator().run(
6 tasks=make_tasks(),
7 target=CallableAgentTaskRunner(my_agent),
8 config=AgentEvalRunConfig(output_dir="./agent-eval-run", parallelism=2),
9)
10
11for aggregate in result.summary.scores.scores:
12 print(f"{aggregate.name}: {aggregate.mean}")

5. Read the results

run() returns an AgentEvalResult you can work with directly in Python:

  • result.summary — aggregated scores per metric output (the mean you just printed), plus coverage counts (how many trials were scored, failed, or missing an output).
  • result.scores — one entry per (task, trial, metric): the metric outputs and their status.
  • result.trials — each trial: the agent’s answer, the evidence it produced (trajectory, final state, logs), and its status (completed / partial / failed).
  • result.run_id — a stable identifier for this run.

Because you set output_dir, the same data was also written to ./agent-eval-run/ as a run bundle:

FileContents
summary.jsonaggregated scores per metric output (mean / min / max / std-dev / counts) and coverage
scores.jsonlone row per (task, trial, metric) — the metric outputs, status, and any diagnostics
trials.jsonlone row per trial — the agent’s output, its evidence, and status
tasks.jsonlthe tasks that were evaluated
run.jsonthe run manifest — the run id and a map of the artifact files
benchmark.jsonbenchmark-grouping metadata for the run
report.htmla browsable dashboard of the run — open it in a browser

The in-memory result and the on-disk bundle hold the same information: use the result object for programmatic follow-up, and the bundle (especially report.html) to inspect or share a run.

Full script

1import asyncio
2
3from nemo_evaluator_sdk.agent_eval.evaluator import AgentEvaluator
4from nemo_evaluator_sdk.agent_eval.runtimes.callable_runtime import CallableAgentTaskRunner
5from nemo_evaluator_sdk.agent_eval.tasks import AgentEvalRunConfig, AgentEvalTask
6from nemo_evaluator_sdk.metrics.protocol import MetricInput, MetricOutput, MetricOutputSpec, MetricResult
7
8
9class KeywordMatchMetric:
10 """Score 1.0 when the agent's answer contains the expected keyword, else 0.0."""
11
12 @property
13 def type(self) -> str:
14 return "keyword_match"
15
16 def output_spec(self) -> list[MetricOutputSpec]:
17 return [MetricOutputSpec.continuous_score("score")]
18
19 async def compute_scores(self, input: MetricInput) -> MetricResult:
20 expected = str(input.row.data.get("reference", {}).get("expected", "")).lower()
21 answer = (input.candidate.output_text or "").lower()
22 return MetricResult(outputs=[MetricOutput(name="score", value=1.0 if expected and expected in answer else 0.0)])
23
24
25def make_tasks() -> list[AgentEvalTask]:
26 return [
27 AgentEvalTask(
28 id="capital-france",
29 intent="Answer the geography question.",
30 inputs={"instruction": "What is the capital of France?"},
31 reference={"expected": "Paris"},
32 metrics=[KeywordMatchMetric()],
33 ),
34 AgentEvalTask(
35 id="capital-japan",
36 intent="Answer the geography question.",
37 inputs={"instruction": "What is the capital of Japan?"},
38 reference={"expected": "Tokyo"},
39 metrics=[KeywordMatchMetric()],
40 ),
41 ]
42
43
44async def my_agent(task: AgentEvalTask) -> str:
45 # Stand-in agent — replace with a real model or deployed agent later.
46 answers = {
47 "capital-france": "The capital of France is Paris.",
48 "capital-japan": "The capital of Japan is Tokyo.",
49 }
50 return answers[task.id]
51
52
53async def main() -> None:
54 result = await AgentEvaluator().run(
55 tasks=make_tasks(),
56 target=CallableAgentTaskRunner(my_agent),
57 config=AgentEvalRunConfig(output_dir="./agent-eval-run", parallelism=2),
58 )
59 for aggregate in result.summary.scores.scores:
60 print(f"{aggregate.name}: {aggregate.mean}")
61
62
63asyncio.run(main())

Run it:

$python quickstart.py

Expected output (both answers contain the expected keyword, so the mean is 1.0):

keyword_match.score: 1.0

Open ./agent-eval-run/report.html to see the run in a browser.

Next steps

  • Swap the stand-in agent for a real model or a deployed agent over HTTP.
  • Add a trajectory metric that scores how the agent worked (its tool use), not just the answer.
  • Give a task more than one metric, or combine metric outputs into a named view.