Skip to main content
HarborBackend runs an Osmosis AgentWorkflow or a registered native Harbor agent inside a Harbor trial. Every rollout gets a copied task directory, a task-defined environment, and Harbor-managed agent and verifier phases.
SDK v0.3 removed the pre-v0.3 HarborBackend and renamed HarborBackendV2 to HarborBackend. The current class has a different constructor and no compatibility alias. Follow the v0.3 migration guide before upgrading an existing harness.

Install and Import

Install the Harbor and rollout-server features:
In v0.3.0 and later, the Harbor extra installs a compatible uv builder and the backend prefers the executable installed with the active Python interpreter. A separate global uv installation is not required. Import the backend from its Harbor submodule:
HarborBackend is not re-exported from osmosis_ai.rollout or osmosis_ai.rollout.backend. The extra installs Harbor together with its Daytona environment dependencies, so a rollout that selects Harbor’s Daytona environment needs no additional packages.

Choose a Task Mode

task_mode determines who owns the instruction, how the default task is selected, and whether the request prompt reaches the task. Both modes use Harbor trials and provide the same isolation. Mode selection changes task semantics, not the sandbox technology.

Template Mode

Template mode starts every rollout from one task directory. When the request contains a prompt, the backend copies the task and replaces instruction.md with the serialized message list before Harbor starts the trial.
An instruction.md file is optional for the configured template when every rollout supplies a prompt. Add a placeholder instruction if you also want the directory to pass Harbor’s standalone task validation. A tests/test.sh is optional when the backend supplies an Osmosis Grader.
Template mode is the Harbor path most similar to LocalBackend: one workflow handles changing dataset prompts. Choose it when those prompts need the same isolated operating system, tools, services, or filesystem setup on every rollout.
In template mode, metadata["harbor_task"] can select a different task for one request, but the request prompt still replaces that task’s instruction. The backend logs a warning when it overwrites an instruction from a dynamically selected task.

Dataset Mode

Dataset mode treats each Harbor task as the complete unit of work. The task retains its own instruction.md, environment, configuration, and verifier.
Configure the root directory and a native Harbor agent or Osmosis workflow:
Each Osmosis metadata-mode dataset row selects the Harbor task by directory name:
The backend deliberately removes any request prompt in dataset mode. Harbor passes the selected task’s instruction to the native agent or bundled AgentWorkflow. The task’s verifier normally computes the reward; if tests/test.sh is absent, a configured Osmosis Grader supplies the verifier instead.

Integrate an Existing Harbor Dataset

If a local dataset already works with harbor run, its task directories are the reusable boundary:
1

Keep the task directories

Point tasks_dir at the local dataset root. Each child must be a Harbor task with task.toml, instruction.md, an environment/, and the verifier files required by that task.
2

Choose a supported agent track

Use agent="terminus-2", "mini-swe-agent", "opencode", or "oracle" when that registered native agent fits. Otherwise package your agent behavior as an Osmosis AgentWorkflow and pass its class or import path.
3

Create the selector dataset

Upload an Osmosis metadata-mode dataset whose harbor_task_id values match the task directory names. The Platform dataset selects trials; the Harbor task directories remain with the rollout code.
4

Run evaluation before training

Confirm that the native verifier emits the reward channel and that trainable agents produce a usable trajectory before starting training.
This path reuses task content, not the complete Harbor job definition. HarborBackend does not read Harbor JobConfig, dataset filters, attempt counts, arbitrary agent configs, or harbor run CLI flags. Osmosis supplies request scheduling, the model endpoint, result polling, and rollout identity.

Dynamic Task Sources

In either mode, a request can set metadata["harbor_task"] instead of using the configured default selection: Pin package references and Git commits for reproducibility. Instruction ownership still follows task_mode: template mode replaces the fetched task’s instruction, while dataset mode keeps it.
Treat these fields as trusted control-plane input, not as untrusted dataset content. The rollout server resolves, downloads, and stages the referenced task outside the trial sandbox, and a task’s Dockerfile and verifier scripts are executable content. Accept harbor_task, git_url, and git_commit_id values only from task sources you control.

Agent Tracks

agent selects one of two execution tracks: An AgentWorkflow project must contain pyproject.toml and an importable Python package, and the task image must support Python. Pass code_dir when the project cannot be inferred, or pass a prebuilt bundle wheel. Keep the task Dockerfile focused on task dependencies; the backend installs the rollout bundle and can preinstall its declared dependencies into the copied image. Registered native names: Use workflow_config with an AgentWorkflow. Use native_agent_kwargs only with a registered native agent. model_name defaults to openai/osmosis-rollout; per-request metadata can override it with harbor_model.
A custom agent name that works in a separate Harbor installation is not automatically available through HarborBackend. The backend accepts only the registered native names above or an Osmosis AgentWorkflow.

Native OpenCode

Starting with 0.3.4, use agent="opencode" to run existing Harbor tasks. The SDK connects OpenCode to the active rollout model endpoint and disables automatic compaction and pruning to preserve the training trajectory.
Pass this backend to create_rollout_server() as in the dataset-mode example above, and supply the Daytona credentials described below for managed runs. To pin OpenCode, pass native_agent_kwargs={"version": "1.18.27"}; the pin applies during execution and prewarm. Pass additional OpenCode configuration through native_agent_kwargs["opencode_config"]; the SDK controls endpoint, authentication, and compaction settings. model_name must use the non-empty provider/model form; the default openai/osmosis-rollout already satisfies this. Override it per request with metadata["harbor_model"]; null, empty, and non-string values are rejected.

Reward Source and Precedence

Harbor always treats a task-provided verifier as authoritative: There is no custom_tests_dir in v0.3. Keep native verifier files under each task’s tests/ directory. A native verifier must write Harbor’s reward channel, normally through /logs/verifier/reward.txt or reward.json with a reward key; the backend does not guess another channel.

Constructor Reference

Prewarming, Capacity, and Cancellation

prewarm() builds task images and runs agent setup before the server accepts traffic. Template mode prewarms its configured task; dataset mode requires the task IDs you want to prewarm. TrialQueue(n_concurrent=<n>) controls Harbor trial concurrency. max_queue_depth limits waiting rollouts so the server can return HTTP 429 instead of growing an unbounded queue. rollout_status() reports queued, running, grading, or recently finished state; cancel_rollouts() cancels queued or running work by ID, prefix, or all. rollout_status() remains available for backend-local diagnostics, but server result polling reads progress from the active RolloutContext. Custom backends must await RolloutContext.set_status() to publish status; callers can use RolloutClient to observe progress and cancel one rollout. Keep TrialQueue at its default RetryConfig(max_retries=0). Queue-level attempt retries are not supported by the backend’s terminal-event contract; resubmit with a new rollout ID instead.

Managed and Self-Hosted Environments

For Osmosis Platform Harbor rollouts, explicitly set environment_config=HarborEnvironmentConfig(type=EnvironmentType.DAYTONA). Omitting environment_config keeps Harbor’s Docker default; it does not select Daytona automatically. Harbor builds the selected task’s Dockerfile for Daytona; you do not manually build or push an image, configure registry credentials, or select a cluster. Add DAYTONA_API_KEY to [secrets].required in both the evaluation and training configs, keeping any other required names. Store the credential for managed runs with:
For local osmosis eval run, supply DAYTONA_API_KEY through the process environment or --secrets-file; a Platform secret record alone does not make it available locally. Never put secret values in the TOML config. osmosis eval run accepts every Harbor environment for local eval and keeps the entrypoint’s usual environment_config. When the resolved sandbox cannot reach the developer machine’s loopback interface — Daytona or Docker outside macOS — the CLI starts a managed cloudflared tunnel automatically so the sandbox can reach the local model bridge, or uses the tunnel you point at with --advertise-url. See eval run. EnvironmentType.DOCKER also remains useful in a self-hosted SDK harness with a Docker daemon, but the managed rollout server does not provide that daemon. A self-hosted harness can select EnvironmentType.DAYTONA as well; the harbor extra already carries its dependencies, so only Daytona credentials are additionally required.

Daytona Sandbox Lifecycle Defaults

In 0.3.3, built-in Daytona environments (type="daytona", import_path=None, and delete=True) default to auto_stop_interval_mins=60 and auto_delete_interval_mins=0. Daytona stops a sandbox after 60 minutes of provider-observed inactivity and deletes it immediately after stopping. This is a cleanup backstop for a crashed rollout server; normal trial teardown and agent or grader timeouts still apply. Activity means interactions recognized by Daytona, not CPU work inside the sandbox. Harbor command polling normally refreshes activity while the server drives a command. The policy does not check server health, and other clients’ activity can keep a sandbox alive after a crash. For trials with longer periods without Daytona-visible activity, pass a larger interval in environment_config.kwargs, or set it to 0 to disable auto-stop:
Pass this config to HarborBackend(environment_config=environment_config, ...). The SDK preserves explicit lifecycle values and adds no defaults for delete=False, a custom import_path, or other providers. Disabling auto-stop leaves cleanup to normal teardown or your own cleanup policy.
Harbor 0.22 forces immediate deletion for snapshot-backed Daytona sandboxes even with a nonzero deletion interval, and rejects nonzero deletion intervals for GPU tasks. The default of 0 works with both paths.

Next Steps

Execution Backend Overview

Compare LocalBackend, Harbor template mode, and Harbor dataset mode.

v0.3 Migration

Replace the legacy Harbor constructor and execution model.
Last modified on September 14, 2026