Metrics Dictionary
This reference defines each metric that the NeMo Labs Voice Agent evaluation harness writes. The producers
are nemo_voice_agent/evaluation/runner.py for per-scenario scoring and run aggregation,
nemo_voice_agent/evaluation/bridge.py for turns, latency, and token counters, and
nemo_voice_agent/evaluation/utils.py for the large language model (LLM) judge. For metric concepts, refer
to Scoring. For artifact locations, refer to
Reading Results.
Value Conventions
Use these conventions to distinguish an absent signal from an applicable signal without evidence.
metrics.json — Always Present
The harness writes one metrics.json file in each scenario directory. These keys are present for every
scenario that completes a bridge run.
The latency_stats object contains count (int), plus mean_ms, p50_ms, p95_ms, min_ms, and max_ms
(floats). All values are zero when count is 0. One latency is recorded per user-to-agent handoff: the
wall-clock gap from the user bot’s last audio frame to the agent’s first subsequent audio frame. The value
therefore includes automatic speech recognition (ASR), LLM, and text-to-speech (TTS) time-to-first-byte, not
only LLM latency.
metrics.json — Conditional
The harness writes the following keys only when the corresponding scenario signal or run feature applies.
Each db_state_assertion_verdicts entry contains func_name (registered predicate name) and side
("agent" or "user", which selects the pulled database). It also contains passed (bool), expected
(the assertion’s assert_value), actual (the predicate result, or null on error), and message
(optional upstream label). The error field is null or contains the failure reason. If the predicate is
missing, raises an exception, or cannot access the required database, passed is false.
success_breakdown Buckets
Names inside each bucket are the SuccessSignal string values: is_action_match, db_state_match,
db_state_assertion, nl_assertion, judge_passed, clean_exit.
is_task_successful is derived from this object: it is true when failed contains nothing other than
clean_exit.
Stalled Scenarios
When --min-agent-turns N is set (default 3), the runner counts the agent’s LLM calls — preferring
token_usage.agent.n_calls, falling back to the message count in bot_logs_agent/llm_context.json.
Below the floor, the scenario is forced to is_successful: false and is_task_successful: false,
gets insufficient_agent_turns: true, and is skipped in every per-signal bucket. It is a counted
failure in the composite rate, not an exclusion. Token usage still rolls up, so cost accounting remains
accurate. Refer to Resuming a Run to retry them.
judge_result.json
The harness writes judge_result.json once per scenario when a judge is configured.
Each nl_assertion_verdicts entry has index (1-based, matching the numbered assertion the judge was
shown), assertion (the assertion text, inlined so the file is self-describing), passed (bool), and
reason (string). The list is normalized to exactly one entry per assertion: missing, out-of-range,
or non-boolean verdicts are filled as passed: false with an explanatory reason.
all_summary.txt Run-Level Aggregates
The runner renders these rates as text without serializing them to JSON. The first column contains internal variable names, and the second contains the labels in the file. A rate is omitted when its bucket is empty.
The two assertion rates use assertions rather than scenarios as the denominator so that they remain comparable across domains where scenarios carry different assertion counts.
Also in the file:
Overall Latency Statistics—overall_latency_stats, pooled over every latency measurement in the run:count,mean_ms,p50_ms,p95_ms,min_ms,max_ms. Each is-1when nothing was measured.Token Usage— per side,n_calls,prompt,completion, and their sum, plus aRun totalacross both sides. The entire block is suppressed when no token events were received.- Stall warning —
WARNING: N scenario(s) had fewer than N agent turn(s) ... and were counted as failures.followed by the scenario names and the suggested resume command.
Per-Domain Breakdowns
The runner prints per-domain breakdowns only when the run spans more than one domain bucket. Each breakdown
uses the scenario-name prefix before __ as its key. Breakdowns are available for success rate, task success
rate (excluding clean exit), DB-state match rate, NL-assertion pass rate, and DB-state-assertion pass rate.
Judge score, judge pass, action match, and clean exit have no per-domain block.
Aggregation on Resume
Scenarios skipped by --resume do not re-run. Their metrics.json is loaded from disk and folded into
the same buckets using RunAggregator.add_scenario. Each signal is appended only when its key is present
and well-typed, so an older metrics.json missing a field simply contributes nothing to that bucket.
NL-assertion verdicts are re-read from judge_result.json on this path, because only the pass rate
lives in metrics.json. The resulting all_summary.txt is identical whether a scenario ran live or
was loaded from a prior session.
Related
Use these pages to connect the field definitions to scoring behavior, result inspection, and domain-specific use.
- Scoring — how each of the six signals is derived and combined.
- Reading Results — the full artifact layout and triage recipes.
- Eval CLI Reference — the flags that switch these fields on.
- tau2-telecom — the domain that exercises
db_state_assertionsand dual-side DB pulls.