Resuming Long Runs
A full benchmark domain contains 50–114 scenarios that run end to end over live WebSocket audio. An
out-of-memory error, interrupted process, or unresponsive large language model (LLM) server can stop a run
before completion.
run_evaluation.py --resume continues the existing session instead of starting over.
Resumed sessions preserve existing database (DB)-state evidence for completed scenarios.
Prerequisites
Keep the original session directory under eval_results/, and restart the simulated-user and agent bot
servers before reconnecting the bridge.
Resume a Run
Both bot servers must be up again before you resume. The bridge reconnects to them per scenario.
--resume takes only the timestamp, not a path. The session directory is resolved as
<--output-dir>/eval_<TIMESTAMP> (default --output-dir is ./eval_results), and the run aborts with an
error if that directory does not exist. Pass the same scenario selection (--domain / --scenarios) you used
originally — resume does not remember which scenarios were queued.
The Three Per-Scenario States
Before running anything, the runner classifies every queued scenario’s subdirectory using
classify_scenario_resume_state in nemo_voice_agent/evaluation/resume.py. The same pass runs on a fresh run
too, where it is a no-op because no subdirectory exists yet.
The runner does not delete killed backups. They accumulate under the session directory across repeated resumes, so delete them after you no longer need the partial logs.
At the end of a resumed session, all_metrics.json, all_summary.txt, and all_latencies.csv are rewritten
from scratch covering every scenario, both freshly run and loaded from disk. evaluation_log.txt is opened in
append mode and gets a === RESUMING run eval_<TIMESTAMP> === banner rather than being truncated.
run_args.json and the Consistency Soft-Check
Every invocation appends a record to run_args.json at <session_dir>/run_args.json, shaped as
{"invocations": [...]}. Each record holds the wall-clock start time, raw argv, the fully parsed argument
namespace, and the resolved scenario count and names. judge_api_key is replaced with "<redacted>" before
the file is written. Resume records also carry resumed_from_invocation, the index of the invocation they
continued.
On resume, the runner diffs the new invocation against the most recent prior one across the scoring-relevant fields below and logs a warning listing every mismatch. It is a soft check — it never blocks the run.
Output directory and WebSocket URLs are recorded but not diffed. If you do change a scored field mid-session,
the aggregate mixes scenarios graded under different settings. Re-run from scratch (omit --resume) when you
need a clean comparison.
—min-agent-turns
Default: 3. Fewer than N LLM responses usually indicate stalled infrastructure rather than a task failure. For example, the agent can greet the user before the LLM server stops answering. The runner handles these scenarios separately to keep them from distorting the per-signal rates.
The turn count comes from count_agent_responses. It first uses the bridge’s live
token_usage.agent.n_calls from metrics.json. For older runs without that field, it counts assistant
messages in bot_logs_agent/llm_context.json. When neither signal is available, the check is skipped.
Effects of falling below the threshold:
That last row is the point — one resume command both retries the stalled scenarios and cleans the aggregate.
Pass --min-agent-turns 0 to disable the filter entirely and score every scenario on its own merits.
Preview with check_resume.py
check_resume.py at evaluation/check_resume.py reports what a resume would do without renaming or writing
anything. It takes a
path to the session directory, not a timestamp.
It prints counts for completed, would-rerun, and fresh scenarios. It then lists each scenario that would be
rerun and its reason. Reasons include no metrics.json (in-flight), 0 turns (bot crashed before audio),
and 1 agent LLM response(s) < 3 (TIMEOUT).
Two things to know:
- Its
--min-agent-turnsdefaults to0, unlikerun_evaluation.py’s3. Always pass the value you intend to resume with, or the preview under-reports the re-run set. - It walks only the subdirectories already on disk, skipping
.killed.backups and anything without ametrics.json,bridge_log.txt, orscenario_config/. Queued scenarios that were never started have no subdirectory at all, so they do not appear in the preview — the fresh bucket stays empty in practice.
Tips for Long Runs
Use these practices to control scenario duration, preserve evidence, and avoid unnecessary reruns.
--durationis unset by default, in which case each scenario’s ownmax_durationapplies. Setting it overrides every scenario and is one of the diffed consistency fields.- Resume in the same shell environment.
--output-diris relative to the CWD, so running from a different directory silently creates a new session instead of finding the old one. - Check
all_summary.txtfor the stalled-scenario warning after every long run — that block tells you whether the numbers are final or whether a resume is still owed. - If multiple scenarios stall together, fix the backend first by using Troubleshooting. Resume after the backend is healthy to avoid repeated failures.
Next Steps
Use the quickstart for a fresh run, the results guide for artifact triage, and the command-line interface (CLI) reference for every resume option.
- Evaluation Quickstart — first end-to-end run
- Scoring — the six success signals and how the composite is computed
- Reading Results — the artifacts inside each scenario directory
- Evaluation CLI — every flag, with defaults