Skip to main content
Osmosis SDK v0.3 changes the rollout contract, optional-feature imports and extras, workflow return values, Harbor execution, dataset schemas, and run-secret submission. Upgrade across these areas together even if your rollout uses only a subset of them.
Upgrade the package requirement, workflow, grader, integrations, and backend entrypoint together. Mixing v0.2 rollout code with a v0.3 backend usually fails at runtime.
Use the section that matches your backend: Before changing code:
  • Keep the last successful v0.2 evaluation run for comparison.
  • Use Python 3.12 or later.
  • Recreate the rollout environment and lockfile after changing the SDK requirement.
  • Search for removed APIs before and after the migration.

Upgrading to 0.3.3

If you already use 0.3.0–0.3.2, apply this section before the backend-specific guidance below. Version 0.3.3 changes the rollout protocol and custom backend contract even though it remains in the 0.3 release line.
  1. Upgrade the CLI/caller environment and every rollout server environment together to osmosis-ai>=0.3.10,<0.4, keeping the extras your project needs, then refresh their lockfiles. Built-in AgentWorkflow, Grader, and backend constructors keep their existing interfaces.
  2. Replace HttpRolloutDriver and callback request/response models with RolloutClient. Completion now uses leased long polling; remove completion callback URLs. Supply a unique rollout_id for each attempt and llm_api_key when the chat endpoint requires authentication. await run_rollout_async() returns an awaitable RolloutHandle with status and phase-wait methods.
  3. Update custom backends to async execute(request) -> ExecutionOutcome. Return ExecutionOutcome(workflow=workflow_result, grader=grader_result) instead of invoking completion callbacks, and publish progress through await rollout_ctx.set_status(RolloutStatus.GRADING) on the active RolloutContext. Respect request.grade; use grade=False for ungraded runs.
  4. Move local LLM bridge imports from osmosis_ai.rollout.controller to osmosis_ai.eval.local. The latter requires the eval extra; RolloutClient needs only the base package.
  5. Start local eval with a new run name if an existing run was recorded with the older protocol. The local eval protocol fingerprint is now 0.4; those older runs cannot resume under 0.3.3. Use the previous SDK to resume them.
  6. Replace managed SkyPilot placement with a supported Harbor environment. Select OpenSandbox for prebuilt task images or Daytona for Dockerfile-based tasks. HARBOR_SKYPILOT_CONTEXT is no longer read. See managed and self-hosted environments for configuration and credentials.

Upgrading from 0.3.3–0.3.6 to 0.3.7

  1. Upgrade the CLI, rollout callers, and each rollout’s pyproject.toml dependency to osmosis-ai>=0.3.7,<0.4 with the same extras. Refresh their lockfiles and rebuild affected runtime images to pick up the dependency security fixes. Updating the CLI alone does not update rollout or sandbox packages. Rollouts scaffolded by osmosis rollout init declare osmosis-ai[server]>=0.3.0,<0.4, so raise that floor as well.
  2. Remove RolloutClient.drain(), POST /drain, and the drain request/response models introduced in 0.3.5 and removed in 0.3.6. Use health() and wait_idle(process_id=...) to observe work, and SIGTERM for shutdown. wait_idle() does not prevent new admissions or verify external uploads.
  3. Give the host enough time for backend shutdown and Harbor sandbox cleanup; see Harbor server shutdown. Custom backends that own resources can implement ExecutionBackend.shutdown().
  4. Add timeout_keep_alive=2160 to existing Uvicorn entrypoints, as in the installation example. New 0.3.7 scaffolds already include it; upgrading the package does not rewrite existing entrypoints.
  5. For Harbor, review version compatibility and OpenSandbox setup. Existing subclasses keep their build_trial_config, build_agent_config, and harness_agent_config signatures; do not add a preview_path argument to those hooks. Bundled workflows need an updated SDK inside the sandbox to support live previews. Since 0.3.5, Harbor rollout IDs cannot contain colons or control characters; send portable IDs.
  6. Remove scripts that invoke the public osmosis dev server or osmosis images commands, or their dedicated OsmosisClient methods; these were removed in 0.3.5. See the changelog for release details.

Upgrading from 0.3.7 to 0.3.8

  1. Raise the CLI, rollout, and sandbox dependencies to osmosis-ai>=0.3.8,<0.4, keeping the same extras. Update conflicting pins, refresh every lockfile, and rebuild affected runtime images. Upgrading the CLI alone does not update packages or CA bundles inside existing images.
  2. Remove reads of RolloutInfo.is_active, the is_active constructor argument, and the is_active key in osmosis rollout list --json. This always-true field was removed. The newly exposed description and last_synced_at fields are metadata, not activity indicators.
  3. Add --overwrite when osmosis train info --output <path> should replace an existing file. Without it, the command keeps the file and reports a save warning. See train info.
  4. Review Harbor prewarm modes. Dataset mode can discover tasks without explicit IDs, isolated prewarm failures can leave individual tasks unavailable, and the Harbor extra now accepts Harbor >=0.20.0,<0.25.
The updated dependency floors apply to these installations: The full extra includes these requirements. See the 0.3.8 changelog for the complete release notes.

Upgrading from 0.3.8 to 0.3.9

  1. Finish interrupted named local eval runs with the SDK version that created them before upgrading. The new source digest changes even when rollout files are unchanged. As a result, 0.3.9 refuses resume and --retry-failed for runs created with 0.3.8 or earlier and reports Changed: rollout.
  2. Upgrade the CLI, callers, and rollout dependencies to osmosis-ai>=0.3.9,<0.4 with the same extras. Resolve conflicting pins, refresh lockfiles, and rebuild affected runtime images. The applicable extras now require LiteLLM >=1.103.1,<2.0.0 excluding 1.104.0rc1, filelock >=4.2.1, Strands Agents >=1.48.0,<2.0.0, and OpenTelemetry API >=1.45.1,<2.0.0; see the changelog for which extras own each requirement.
  3. After upgrading, use a new run name or --fresh to archive the previous directory and start over. A rejected resume preserves the old manifest and results, and completed old results can still be uploaded. Do not manually change the digest in manifest.json; it also binds the platform import identity. See Source Digest Upgrades.
New local runs write and upload dataset_rows.jsonl for prompt and ground-truth search. Older completed runs remain uploadable without this file; upgrading does not add it to those results. The Harbor bundle cache rebuilds once after the digest upgrade. Rollout results add agent_started_at. Update the server as well as the caller before using None to identify setup failures; older servers omit the field. Built-in OpenSandbox environments also support an OPENSANDBOX_REQUEST_TIMEOUT_SEC default.

Upgrading from 0.3.9 to 0.3.10

  1. Confirm that your Osmosis platform supports archive imports before you upgrade the CLI. In 0.3.10, osmosis eval upload and osmosis eval run --upload send a completed run as a single streamed archive. There is no per-file upload fallback.
  2. Upgrade the CLI, callers, and rollout dependencies to osmosis-ai>=0.3.10,<0.4 with the same extras, then refresh lockfiles. Strands rollouts need the update in rollouts/<name>/pyproject.toml to keep earlier assistant reasoning in follow-up requests and trajectories.
  3. If you call OsmosisClient.start_eval_run_import() directly instead of using the CLI, pass archive= instead of files=. Upload files.jsonl and run.zip to the returned slots. Then call start_eval_run_import_extraction() and poll get_eval_run_import_extraction() until extraction reaches ready before finalizing the import.
  4. Update code that constructs or reads eval-import results. upload_mode is now required, archive imports list their upload slots in files, and a slot’s sha256 can be None.
Existing completed local runs need no changes and upload with the new archive format. See local execution and upload.

LocalBackend Users

LocalBackend keeps the same keyword-only constructor in v0.3:
The migration work is in the workflow, grader, integrations, and any custom protocol code around the backend.

1. Upgrade the Package and Select Features

The base distribution contains the CLI and framework-neutral rollout core. Add only the extras your rollout imports:
Combine extras when needed. For example, a server entrypoint using Strands should declare:
Other extras include openai-agents, harbor, rubric, and parquet. Replace the former platform extra with parquet when validating Parquet datasets. For a source checkout, use the repository’s dev dependency group instead of a published dev extra.

2. Update Public Imports and Workflow Returns

The rollout package root now exposes only framework-neutral core types. Import each optional feature from its public submodule:
Import HarborBackend from osmosis_ai.rollout.backend.harbor as shown in HarborBackend Users. Do not rely on from osmosis_ai import * or optional names formerly re-exported by osmosis_ai.rollout. AgentWorkflow.run() now returns one message history, not a mapping of samples. Return an AgentWorkflowOutput, return a bare message list that the SDK wraps as messages, or return None to use the sample collected from the active RolloutContext:
Every value in metrics must be finite; NaN and positive or negative infinity are rejected. Use None only when an integration or custom source registered the ambient sample for that execution.

3. Move from Many Samples to One Sample

Each workflow execution now produces at most one RolloutSample, and its grader assigns one scalar reward. Update graders from a loop over samples to one explicit sample check:
set_reward() raises ValueError when the workflow produced no sample. Raising an explicit error before scoring generally gives a clearer evaluation failure.

4. Register One Agent or Session per Execution

Construct exactly one registered OsmosisStrandsAgent or OsmosisMemorySession inside AgentWorkflow.run(). A second registration raises ValueError. For OpenAI Agents, the v0.3 session has no name or sample-ID argument:
Handoffs and tool calls can remain inside that one agent run. If you need several candidate answers for one prompt, configure evaluation or training to execute the workflow several times.

5. Update Custom Sample Sources

Built-in integrations already use the v0.3 API. A custom integration must implement the singular source contract:
Do not set an id on RolloutSample. To control the normalized ATIF transcript, set trajectory_messages; setting it to None disables trajectory persistence for that sample.

6. Update Custom Routing and Backend Adapters

Skip this step if you only use the built-in integrations and LocalBackend. Treat the chat-completions URL supplied for an execution as an opaque, rollout-scoped endpoint. Completion callback URLs were removed in 0.3.3. Do not append a rollout ID or attach the removed x-sample-id and x-rollout-id routing headers. Custom backends return an ExecutionOutcome containing workflow and optional grader ExecutionResult values, each with at most one sample. If you read the container exchange files directly, update readers to the singular file names and payloads:
sample.json
reward.json

7. Migrate Dataset Schemas

Starting with 0.3.0rc3, the presence of a metadata column selects one uniform schema mode for the entire dataset: Do not mix prompt-mode and metadata-mode rows. JSONL rows must use a consistent field set, and metadata values must remain valid and type-consistent across the file. Validate JSONL, CSV, or Parquet locally before upload or submission:
The validator scans every JSONL and CSV row and every Parquet metadata value, so fix every reported row rather than only the first example.

8. Migrate Per-Run Secrets

Declare secret names, never values, in the run config:
Stored secret names are sent to the platform and resolved server-side. To provide a value only for the current run, use --secrets-file, the process environment, or the hidden interactive prompt:
Locally provided values are sent in the TLS-protected submit request but are not added to the platform secret store or persistent run config, and the CLI and platform response do not echo them. Supply them again for each run. The same behavior applies to osmosis train submit and osmosis benchmark submit. For benchmark runs, only names in [secrets].required can receive per-run values; model, harness, judge, and verifier secret references must already exist in the platform secret store.

9. Verify a LocalBackend Migration

  1. Confirm that removed APIs no longer appear in the rollout:
  2. Recreate the rollout environment so its lockfile contains osmosis-ai>=0.3.10,<0.4 and the selected extras.
  3. Run the workflow locally and confirm that each successful execution produces one sample.
  4. Submit an evaluation run and confirm that each graded sample has one scalar reward.
  5. Compare rewards and final messages with the last successful v0.2 evaluation before submitting training.

Common LocalBackend Problems

The workflow execution already registered its sample source. Reuse one agent or session for the conversation, or move independent candidates into separate workflow executions.
Construct the supported agent or session inside AgentWorkflow.run(). Objects created at module import time cannot register with the active rollout context.
Install the matching extra in the rollout-local environment and regenerate its lockfile.
Pass the supplied chat-completions URL directly to the integration. Remove code that reconstructs the URL, adds a rollout path segment, or attaches legacy routing headers.

HarborBackend Users

If you use Harbor, first apply the shared dependency, import, workflow, grader, sample-source, routing, dataset, and secret changes in LocalBackend Users. Then migrate the Harbor class and constructor.
The name HarborBackend still imports in v0.3, but it now refers to the implementation previously called HarborBackendV2. A pre-v0.3 call using task_dir, user_code_dir, or workflow raises TypeError; there is no legacy compatibility mode.

1. Upgrade the Package and Import

Install the v0.3 Harbor and server features:
The harbor extra includes Daytona and OpenSandbox dependencies. Choose the environment in the entrypoint: OpenSandbox uses prebuilt task images, while Daytona can build the task Dockerfile. See Managed and Self-Hosted Environments for configuration and credentials.
Use the Harbor submodule import:
If you already use HarborBackendV2, change only the class name and keep its v2 constructor arguments:
HarborBackendV2 is not retained as an alias.

2. Replace the Pre-v0.3 Constructor

The old backend mounted your source tree and SDK into a task environment. The v0.3 backend packages the workflow project into a wheel and installs it inside the task container.
Migrate every old constructor parameter with this table: Remove the private _sdk_source_dir argument if your harness used it. The v0.3 constructor also adds these controls:

3. Choose a Task Mode

For the closest replacement of the old single task_dir, use template mode:
The request prompt replaces instruction.md in a per-rollout copy of that task. This keeps the same prompt ownership as LocalBackend while adding a Harbor trial environment. Use dataset mode when tasks_dir contains one directory per task:
Each request must set metadata["harbor_task_id"]; the selected task keeps its own instruction.md. Use this mode to preserve authored Harbor tasks or a local Harbor dataset that already runs task-by-task. For either mode, metadata["harbor_task"] can select a per-rollout local path, Harbor registry package such as "org/name@ref", or Git task. Git tasks also set metadata["git_url"] and should pin metadata["git_commit_id"]. If the old backend used custom_tests_dir, move those tests into each task:
The task-native verifier remains authoritative even if grader= is also configured; the backend generates an Osmosis grader verifier only when tests/test.sh is absent. Pass grader=None to make the task-native reward path explicit.

4. Package Workflow Code Instead of Mounting It

For an AgentWorkflow, the backend builds a wheel from code_dir and installs it in the container at trial start. The directory must contain pyproject.toml and one importable top-level Python package. When code_dir is omitted, the backend tries to locate the project containing the workflow class. Use bundle= when your build system creates the Osmosis bundle wheel ahead of time. Do not pass both paths expecting them to be merged; the backend uses a supplied bundle directly. The old HarborAgentWorkflowContext.environment adapter is gone. The workflow itself now runs inside the task container, receives a standard AgentWorkflowContext, and accesses files or processes through normal Python APIs:
OsmosisInstalledAgent is also removed. Do not instantiate or subclass it; pass an AgentWorkflow through agent=, or select a registered native Harbor agent name.

5. Choose an Agent and Reward Source

agent= accepts an AgentWorkflow class/import path or one of the registered native names: "terminus-2", "mini-swe-agent", and "oracle".
"oracle" runs a reference solution to validate a dataset or verifier. It does not emit a model trajectory, so do not use it for training.
Choose one reward path:

6. Add Prewarming and Lifecycle Controls

Prewarm the selected task images and agent setup before the rollout server accepts traffic:
From 0.3.8, dataset mode discovers tasks under tasks_dir when IDs are omitted. To prewarm a subset, pass its IDs:
If you set max_queue_depth, POST /rollout returns 429 with Retry-After: 5 when the queue is full. v0.3 also exposes:
  • GET /rollout/{rollout_id}/status
  • POST /rollout/cancel
  • HarborBackend.rollout_status()
  • HarborBackend.cancel_rollouts()

7. Verify a HarborBackend Migration

  1. Confirm that the old class and constructor keywords no longer appear:
  2. Confirm that tasks_dir points to a valid template task or dataset root.
  3. Build the workflow bundle and fix any package-layout or missing-dependency errors.
  4. Run await backend.prewarm() to prewarm the template or discover dataset tasks. Pass task IDs to prewarm a dataset subset, or when using SDK versions before 0.3.8.
  5. Submit one rollout and check the workflow sample, reward source, Harbor logs, and archived artifacts.
  6. Exercise status and cancellation if the calling controller depends on them.
  7. Run an evaluation and compare rewards and final messages with the last successful v0.2 run before training.

Common HarborBackend Problems

The import resolves to the v0.3 backend, but the call still uses the removed constructor. Replace all stale parameters with the table above.
Point code_dir at the directory containing pyproject.toml and one importable package. Ensure the workflow and grader can be addressed as import paths from that package.
Set metadata["harbor_task_id"] to a directory beneath tasks_dir, or set metadata["harbor_task"] to a supported local, package, or Git reference.
If the task contains tests/test.sh, fix that verifier and make sure it emits Harbor’s reward channel; an Osmosis grader does not override it. If the task has no verifier, pass an Osmosis grader instead.
Remove the legacy adapter calls. The workflow now runs inside the container, so use normal filesystem, subprocess, and network APIs.
Last modified on November 2, 2026