Skip to main content
Use an evaluation run to test a rollout and grader against a dataset. Evaluation configs live under configs/eval/. Run locally through the backend the rollout entrypoint constructs, LocalBackend or Harbor, for fast iteration, optionally publish the completed result, or use managed infrastructure with eval submit.
Training pre-flight still requires a managed full-size run created by osmosis eval submit. An uploaded local result is visible on the Platform but does not replace that gate.
A Harbor sandbox that cannot reach this machine’s loopback interface (OpenSandbox, Daytona, and Docker outside macOS) needs a public URL for the local model bridge. osmosis eval run detects that from the rollout server’s health report and starts a managed cloudflared quick tunnel automatically. Keep that binary on PATH, or pass --advertise-url with --listener-port for a tunnel you run yourself.

Quick Start

From inside your workspace directory:
The --dataset-file form does not require platform credentials when --upload is omitted. Selecting the platform dataset named in the config or publishing with --upload still requires authenticated Git workspace context. Local output defaults to .osmosis/evals/<run-name>/. You can publish a completed local run later by name, or by an explicit directory:
By default, the upload goes to the workspace connected to the current repository. To publish to a different workspace, pass root --workspace. The run name or directory still refers to local files:
For a managed run, push the intended revision and submit:
From another current directory, select the workspace explicitly and pass the absolute canonical config path:
Then inspect or manage platform-visible runs:

Evaluation Config

See Config Files for the full field reference.
configs/eval/my-rollout.toml
When [evaluation].limit is omitted, managed eval submit evaluates a random 10% sample of the dataset (at least one row). Local eval run evaluates every row unless --rows selects an explicit subset. Set limit to evaluate the first N rows in either mode.
Git Sync is the source of truth for your rollout code. The CLI reads config values from the local TOML file you pass, but rollout code comes from the synced workspace repository. Commit and push before submitting code changes. Set branch to use a pushed branch or commit_sha for a specific pushed revision; omit both to use the default branch.

How It Works

Local Execution and Upload

Install the local-run dependencies with python -m pip install "osmosis-ai[eval]>=0.3.10,<0.4". Every local run requires a valid local workspace and canonical eval config. A run with --dataset-file PATH and no --upload does not initialize platform credentials; selecting the platform dataset or uploading does. Provider and workflow credentials resolve from the process environment or --secrets-file. --secrets-file values take precedence for this run only, and the CLI restores the original environment when the run exits. The CLI replaces non-empty configured [secrets] values in logs.txt with [REDACTED]. It also redacts values of at least 8 characters from a known set of provider and platform environment variables, including OPENAI_API_KEY and OSMOSIS_TOKEN. Shorter values from those ambient variables are left unchanged unless they are configured secrets. The same known values are also replaced with [REDACTED] in everything the CLI prints, for every command and output format. This covers success output, warnings, error messages and details, and OSMOSIS_DEBUG traces. The CLI also matches whitespace-trimmed, JSON-escaped, and Python-quoted forms of each value. Redaction applies only to values the CLI knows. It does not sanitize your dataset content, trajectories, or artifacts. osmosis eval run executes local workspace files through the backend the rollout entrypoint constructs, LocalBackend or Harbor. Add --upload to publish only after a complete terminal run under the same run lock. Failed and skipped samples are terminal and uploadable; pending and cancelled runs are not. The live pass rate excludes skipped samples, matching the final metrics. A rollout that returns no sample releases its worker slot without waiting for a trajectory file. osmosis eval upload <run-name> publishes an already-completed compatible local run and has no confirmation prompt. A bare run name resolves under the workspace’s .osmosis/evals/, while an explicit relative or absolute directory is used as given. That directory must contain compatible manifest.json, index.jsonl, progress.json, and metrics.json files, and the command requires authenticated workspace context. Upload is idempotent and server-authoritative. Re-running the same command after an interruption resumes the same platform run: uploads the platform already has are skipped, an interrupted archive streams again from its start, and a failed extraction restarts. That covers an unfinished upload. Publishing a different set of results for a local run that already finished importing is a separate case that needs --replace. See Retrying Failed Samples. The payload contains index.jsonl, progress.json, the combined logs.txt when present, dataset_rows.jsonl when present, and only referenced canonical trajectory*.json files and safe artifacts for selected rollout IDs. The uploaded logs.txt appears in the run’s Logs tab on the platform. Before hashing the log, eval upload re-applies redaction using known provider and platform key values of at least 8 characters from the current process environment. This does not detect arbitrary secrets or old credentials no longer present in that environment; review older logs before publishing. The CLI never uploads the local manifest.json bytes, events.jsonl, metrics.json, summary or projection copies, control files, per-trial logs, or superseded attempts. Manifest digest, schema versions, and allowlisted redacted Git provenance are metadata. The server strictly validates files, recomputes metrics, and never launches hosted or Temporal evaluation work for an upload. SDK 0.3.10 and later send these files as two uploads: a files.jsonl listing of each file’s path, size, and SHA-256, and a run.zip archive. The CLI streams the archive one part at a time without writing it to disk, so no extra local disk space is needed to store the complete archive. The platform then extracts the archive, and the CLI finalizes the run only after extraction succeeds. Uploading requires a platform with archive import support; there is no per-file fallback. The Evaluation Samples tab uses dataset_rows.jsonl to search samples by prompt and ground truth and to sort by ground truth, the same as managed evaluations. A run created by an older CLI version uploads without the file, so you can search it only by sample ID and error. Runs created with 0.3.8 or earlier cannot be resumed under 0.3.9 just to add this file. Keep or upload completed results as they are, or start a new run; see Source Digest Upgrades. Uploaded results appear in eval list, eval info, and Platform viewers with a Local badge. A dirty source tree produces a provenance warning. Local output uses the same metrics.json, summary.jsonl, trajectories/, and artifacts/ shape as eval download, plus a durable journal, local manifest, secrets-redacted logs, and the canonical rollout_trials/<rollout-id>/ store under .osmosis/evals/<run-name>/. eval run also writes dataset_rows.jsonl before it dispatches any work. The file holds one JSON line per selected row, in dataset order:
  • row_index is the row’s position among the selected rows, the same index index.jsonl uses. It matches the dataset-file offset unless you pass --rows.
  • prompt is the row’s non-system message text, cut at 2,000 characters. A row without a prompt uses its metadata as sorted JSON instead.
  • label is the row’s ground truth, cut at 500 characters. Rows without ground truth omit it.
The file depends only on the selected rows. Resuming, --retry-failed, and re-running a finished run rewrite identical bytes. Each index.jsonl line records token usage for its rollout:
  • tokens is the total over every model call in the rollout.
  • max_context_tokens is the largest single model call, counting its prompt plus completion tokens. Use it to size a model’s context window for training. Total tokens overstate the window you need, and per-call averages understate it.
eval run reads both values from the model bridge’s per-call usage and saves them in the journal, so a resumed run keeps them. If the bridge saw no usage, the values come from the rollout’s trajectory metrics instead. A field is omitted when neither source reports usage. eval upload sends index.jsonl unchanged, and the platform shows max_context_tokens as the run’s Context Length column and Context Length Distribution. Omitting --name creates an adjective-animal-number name. Pass that name back to resume only work without a durable terminal result. A named run is locked to its resolved model, dataset, selected rows, evaluation settings, entrypoint, and rollout source; changed inputs refuse resume. Use --fresh to archive the old run before restarting, or --retry-failed without a code change to retry failures while keeping successes; see Retrying Failed Samples. If a named run is already complete, an interactive invocation offers a new generated-name run; non-interactive modes leave it untouched and print next steps. The rollout server runs through uv in an environment resolved from rollouts/<name>/pyproject.toml, so declare Harbor and other rollout-side dependencies there. The first run syncs that environment and later runs reuse it. Use osmosis-ai>=0.3.10,<0.4 in both environments: local eval uses the long-polling protocol introduced in 0.3.3, and the earlier callback protocol is incompatible. A ROLLOUT_SDK_VERSION_MISMATCH warning reports different installed versions; it is not a compatibility guarantee. eval run supports LocalBackend and every Harbor environment, using the entrypoint’s environment_config. Sandboxes that cannot reach host loopback use the tunnel described above. See Managed and Self-Hosted Environments for environment selection. To develop a rollout against a local SDK checkout, point that same file at it:
Only the sandbox’s OpenAI-compatible chat traffic crosses the tunnel; rollout results are collected by long polling over loopback. The model bridge requires a fresh bearer token for each run and supplies provider credentials upstream. Tunnel mode also keeps a slow non-streaming model call alive past the proxy’s idle-read timeout. See eval run for those mechanics and for Cloudflare’s quick-tunnel creation rate limit. Resume is journal-backed: terminal results returned by long polling are written and fsync-ed before they count as completed local work. After interruption, work without a durable terminal record remains pending and can run again. SDK 0.3.3 records rollout protocol 0.4 in the resume inputs, so local runs from the earlier callback protocol cannot resume. Use a new name or --fresh, which moves the previous directory to .osmosis/evals/<run-name>.archive-<utc-timestamp>/ rather than deleting it. See the 0.3.3 migration guide.

Source Digest Upgrades

SDK 0.3.9 and later compute the rollout source digest in a new format. The source digest is the fingerprint of your rollout files that a named run is locked to. The fingerprint changes after you upgrade, even when your rollout files are unchanged. A named run created with 0.3.8 or earlier therefore refuses both resume and --retry-failed with Changed: rollout. Before you upgrade, finish interrupted runs with the SDK version that created them. After you upgrade, start again in one of these ways:
  • Choose a new run name.
  • Pass --fresh to archive the previous directory under the same name and start a new run.
A refused resume does not rewrite the old manifest or results. Completed results from the old run remain available for inspection and for osmosis eval upload. Do not edit the source digest in manifest.json by hand, because the manifest bytes also bind the platform import identity. The Harbor bundle cache rebuilds once after the upgrade. Press Ctrl-C once to cancel in-flight work and allow workflow and sandbox cleanup. A second Ctrl-C skips the long cleanup waits and gives the rollout server five seconds to exit before force-stopping it. The CLI still stops its tunnel and listener, but sandbox cleanup may be incomplete. Re-run with the same --name to resume work without a durable terminal result.

Managed Execution

1

Resolve workspace and config

Normally the CLI reads the evaluation TOML and resolves the workspace from the current Git origin. With root --workspace and an absolute config path, it instead locates the config’s containing Osmosis Git workspace and verifies the selected platform workspace is connected to that same repository. In both cases it validates canonical config paths and imports the configured rollout entrypoint so its backend can validate itself. That import is best effort: it is skipped with a warning when the local environment cannot satisfy the rollout’s declared dependencies, and the platform validates the entrypoint after installing them. It does not scan the module namespace to discover workflow or grader classes. See Files in a Rollout for the SDK entrypoint contract and the local-execution warning.
2

Submit to the platform

The CLI submits the evaluation run request. The platform resolves the selected branch or commit_sha once, clones that commit from the connected workspace repository, and prepares the evaluation environment.
3

Validate the model

Before evaluating any rows, the platform runs a pre-flight check that confirms [experiment].model_path is reachable with your configured credentials. If the model is unreachable (wrong name, missing or invalid API key, or provider rate limiting), the run fails early instead of consuming evaluation resources. Provide the model’s provider API key by registering it with osmosis secret set and listing it under [secrets].required (see Configuration Files).
4

Run the rollout server-side

The platform starts your rollout and drives AgentWorkflow.run(ctx) for each selected dataset row using [experiment].model_path as the evaluation policy. The row’s ground_truth is exposed to Grader.grade(ctx) as ctx.label, while optional row metadata is exposed as ctx.metadata. The grader runs when either a label or metadata is present and can use either or both.
5

Aggregate results

The platform aggregates rewards, pass rates, and per-row results. Use osmosis eval info <name> (or osmosis --json eval info <name>) to inspect them.

Inference Parameters

Your rollout can send provider-specific inference options through the local model bridge during osmosis eval run. Examples include OpenRouter reasoning and provider settings or Anthropic thinking. The rules below describe local evaluation; for managed runs, support also depends on the deployed model endpoint.
  • Custom inference fields are forwarded. No inference-parameter allowlist applies; bridge controls remain blocked as described below. Set fields at the top level of the chat request or in the client’s extra_body; extra_body values win on conflicts. The OpenAI Python client merges extra_body into the top level of the request shallowly, so a nested object such as metadata in extra_body replaces the top-level object instead of merging with it.
  • OpenRouter and OpenAI-compatible endpoints receive fields as request JSON. They are forwarded whether or not LiteLLM’s model catalog lists them.
  • Native providers use LiteLLM translation without dropping parameters. An unsupported standard parameter raises an error instead of being silently removed. Translation follows LiteLLM and provider semantics, so it is not a byte-for-byte passthrough. For example, Anthropic metadata accepts only user_id, and native providers other than OpenAI, Azure, and Anthropic reject metadata.
  • Provider rejections surface as errors. A provider 4xx response returns to your rollout with sanitized details. The bridge does not strip parameters and retry.
For example, when [experiment].model_path is an OpenRouter model, an OpenAI-compatible client in your rollout can request low reasoning effort and latency-sorted routing:
To set the same options with an agent framework, see Strands or OpenAI Agents. The configured evaluation model is authoritative; the client’s model name is a placeholder. The bridge also owns the endpoint, credentials, and upstream transport. Requests containing transport or runtime controls are rejected with an error naming the blocked fields. Blocked fields include LiteLLM routing, authentication, timeout, and retry settings, base_url, extra_headers, callbacks, mock controls, fields that replace the configured model, usage accounting, or prompt (such as OpenRouter models, preset, and usage, or system and prompt), and fields with reserved prefixes such as _, litellm_, aws_, azure_, and vertex_. The bridge serves one completion per request, so n must be omitted or 1.
The CLI and each rollout environment install the SDK separately. Use osmosis-ai>=0.3.10,<0.4 with the appropriate extras in both your CLI environment and rollouts/<name>/pyproject.toml to get these fixes end to end.

Commands

See the Command Reference for the full flag list.

Retrying Failed Samples

Hosted eval retry and --replace for local uploads require CLI version 0.3.4 or later. Each attempt classifies a sample as success, failed, or skipped. The meaning of skipped depends on origin: a managed run records it when the attempt timed out with no grade, while a local run records it when the grader succeeded and set remove_sample to exclude the row. A retry re-runs the skipped and failed rows and carries every success forward. It produces one set of results rather than two runs to reconcile, and only the re-run samples consume compute. A graded sample is never re-run, even when its reward was below the pass threshold.
Because --retry-failed re-dispatches local skipped rows, a sample the grader deliberately removed runs again. If the grader does not remove it on the second attempt, it becomes a graded sample the original run did not have, changing the sample set the score is computed over.
Managed runs retry in place:
The run keeps its ID, URL, and configuration, and re-executes against the same model, dataset, and commit it was submitted with. If it recorded no samples, retry starts the whole run from the beginning. The run must be finished, failed, or stopped. A retry bills like a new submission, metered as its own attempt. The Retry run button on the run’s detail page does the same thing. If the original run supplied secret values itself, Osmosis never stored them, so a retry has to collect them again. The platform answers with the names it needs. The CLI resolves them from --secrets-file, the environment, or an interactive prompt, and the detail page asks for them in the Retry dialog. Local runs retry on the machine that produced them, then republish:
The run’s detail page shows this command with the config path filled in. The CLI records that path in the run’s provenance at upload. osmosis eval retry on a local run prints the same command rather than retrying, because a local retry needs the workspace the run came from. With root --workspace, as in osmosis --workspace <workspace-name> eval retry <run-name>, the CLI prints two commands instead. The first reruns the failed samples locally. Only after it succeeds does the second publish the results to the selected workspace, even if the source repository is connected to a different workspace:
--retry-failed re-dispatches the journal’s failed and skipped work items while keeping successes, and --upload replaces that run’s published results in place. The platform run keeps its ID and URL; its manifest digest must still match, which is what proves both attempts evaluated the same resolved inputs. To publish a retried run in a later, separate command, use osmosis eval upload <run-name> --replace.

From Evaluation Run to Training Run

1

Run a local evaluation

Run osmosis eval run configs/eval/my-rollout.toml for smoke testing and iteration. Add --upload only if the completed result should appear on the Platform.
2

Iterate on rollout code

Iterate against local files, then push the settled revision to the workspace repository. Use branch for a feature branch or commit_sha to pin the managed evaluation.
3

Pass the managed evaluation gate

Run osmosis eval submit configs/eval/my-rollout.toml for the full-size managed evaluation, then use osmosis eval list and osmosis eval info <name> to track progress and inspect results.
4

Submit a training run

Once evaluation run results look healthy, run osmosis train submit configs/training/my-rollout.toml. See Training.

Download Run Outputs

Once a run has data, use osmosis eval download to pull metrics, trajectories, artifacts, and logs to your local disk instead of clicking through the web UI.
Files land under a fixed layout so re-running the command resumes cleanly:
The CLI skips local files whose size matches the platform manifest unless you pass --overwrite, and downloads over 100 MiB require confirmation unless you pass --yes. The CLI retries failed files automatically and lists anything still missing so a second run picks it up. See the Command Reference for the full flag list.
osmosis eval info -o now points at the same run output root, and rich-mode metrics exports save to .osmosis/evals/<name>/metrics.json. The CLI leaves existing files under .osmosis/metrics/ untouched.

Local Rubric Scoring

osmosis eval rubric is a local utility for scoring an existing JSONL conversation file with an LLM judge. It does not require a workspace directory or platform authentication, and it does not run a rollout. “Local” describes where the command runs. For each record, the CLI sends the rubric, the scored assistant message, and any original_input, ground_truth, or metadata fields on that record to the provider behind --model. Review that provider’s privacy and retention terms before scoring sensitive data.
See the Command Reference for the full flag list.

Next Steps

Config Files

Full reference for evaluation and training configuration files.

Git Sync

Push and sync rollout code before managed evaluation runs or training runs.

Training

Submit and manage a training run after the managed full-size evaluation gate passes.
Last modified on November 6, 2026