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.- Upgrade the CLI/caller environment and every rollout server environment together to
osmosis-ai>=0.3.3,<0.4, keeping the extras your project needs, then refresh their lockfiles. Built-inAgentWorkflow,Grader, and backend constructors keep their existing interfaces. - Replace
HttpRolloutDriverand callback request/response models withRolloutClient. Completion now uses leased long polling; remove completion callback URLs. Supply a uniquerollout_idfor each attempt andllm_api_keywhen the chat endpoint requires authentication.await run_rollout_async()returns an awaitableRolloutHandlewith status and phase-wait methods. - Update custom backends to
async execute(request) -> ExecutionOutcome. ReturnExecutionOutcome(workflow=workflow_result, grader=grader_result)instead of invoking completion callbacks, and publish progress throughawait rollout_ctx.set_status(RolloutStatus.GRADING)on the activeRolloutContext. Respectrequest.grade; usegrade=Falsefor ungraded runs. - Move local LLM bridge imports from
osmosis_ai.rollout.controllertoosmosis_ai.eval.local. The latter requires theevalextra;RolloutClientneeds only the base package. - 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. - Replace managed SkyPilot placement with
EnvironmentConfig(type=EnvironmentType.DAYTONA)and configureDAYTONA_API_KEY.HARBOR_SKYPILOT_CONTEXTis no longer read. See managed and self-hosted environments for credentials and Daytona inactivity cleanup.
LocalBackend Users
LocalBackend keeps the same keyword-only constructor in v0.3:
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: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: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:
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 oneRolloutSample, 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 registeredOsmosisStrandsAgent or OsmosisMemorySession inside AgentWorkflow.run(). A second registration raises ValueError.
For OpenAI Agents, the v0.3 session has no name or sample-ID argument:
5. Update Custom Sample Sources
Built-in integrations already use the v0.3 API. A custom integration must implement the singular source contract: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 andLocalBackend.
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 with0.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:
8. Migrate Per-Run Secrets
Declare secret names, never values, in the run config:--secrets-file, the process environment, or the hidden interactive prompt:
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
-
Confirm that removed APIs no longer appear in the rollout:
-
Recreate the rollout environment so its lockfile contains
osmosis-ai>=0.3.3,<0.4and the selected extras. - Run the workflow locally and confirm that each successful execution produces one sample.
- Submit an evaluation run and confirm that each graded sample has one scalar reward.
- Compare rewards and final messages with the last successful v0.2 evaluation before submitting training.
Common LocalBackend Problems
A second agent or session raises a registration error
A second agent or session raises a registration error
The workflow execution already registered its sample source. Reuse one agent or session for the conversation, or move independent candidates into separate workflow executions.
The grader has no sample
The grader has no sample
Construct the supported agent or session inside
AgentWorkflow.run(). Objects created at module import time cannot register with the active rollout context.An optional integration cannot be imported
An optional integration cannot be imported
Install the matching extra in the rollout-local environment and regenerate its lockfile.
Model calls reach the wrong rollout
Model calls reach the wrong rollout
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
Harbor users must 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.1. Upgrade the Package and Import
Install the v0.3 Harbor and server features:The
harbor extra includes Daytona dependencies. For managed rollouts, explicitly select EnvironmentType.DAYTONA and configure DAYTONA_API_KEY as described in Managed and Self-Hosted Environments.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.
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 singletask_dir, use template mode:
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:
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:
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 anAgentWorkflow, 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; a supplied bundle is used 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 and must not be used for training.6. Add Prewarming and Lifecycle Controls
Prewarm the selected task images and agent setup before the rollout server accepts traffic:max_queue_depth, POST /rollout returns 429 with Retry-After: 5 when the queue is full. v0.3 also exposes:
GET /rollout/{rollout_id}/statusPOST /rollout/cancelHarborBackend.rollout_status()HarborBackend.cancel_rollouts()
7. Verify a HarborBackend Migration
-
Confirm that the old class and constructor keywords no longer appear:
-
Confirm that
tasks_dirpoints to a valid template task or dataset root. - Build the workflow bundle and fix any package-layout or missing-dependency errors.
-
Run
await backend.prewarm()for template mode, or pass task IDs in dataset mode. - Submit one rollout and check the workflow sample, reward source, Harbor logs, and archived artifacts.
- Exercise status and cancellation if the calling controller depends on them.
- Run an evaluation and compare rewards and final messages with the last successful v0.2 run before training.
Common HarborBackend Problems
HarborBackend rejects task_dir, user_code_dir, or workflow
HarborBackend rejects task_dir, user_code_dir, or workflow
The import resolves to the v0.3 backend, but the call still uses the removed constructor. Replace all stale parameters with the table above.
The workflow project cannot be bundled
The workflow project cannot be bundled
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.A dataset-mode request cannot find its task
A dataset-mode request cannot find its task
Set
metadata["harbor_task_id"] to a directory beneath tasks_dir, or set metadata["harbor_task"] to a supported local, package, or Git reference.The trial finishes without a reward
The trial finishes without a reward
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.Rollout code expects ctx.environment
Rollout code expects ctx.environment
Remove the legacy adapter calls. The workflow now runs inside the container, so use normal filesystem, subprocess, and network APIs.