跳转到主要内容
HarborBackend 会在 Harbor trial 中运行 Osmosis AgentWorkflow 或已注册的原生 Harbor agent。每个 rollout 都会获得复制的 task directory、task-defined environment,以及 Harbor-managed agent 和 verifier phases。
SDK v0.3 移除了 pre-v0.3 HarborBackend,并把 HarborBackendV2 改名为 HarborBackend。当前 class 使用不同的 constructor,且不提供 compatibility alias。升级已有 harness 前,请先阅读 v0.3 迁移指南。

安装与 Import

安装 Harbor 和 rollout-server features:
在 v0.3.0 及更高版本中,Harbor extra 会安装兼容的 uv builder,backend 会优先使用 active Python interpreter 对应的 executable,无需再单独全局安装 uv。 从 Harbor submodule import backend:
HarborBackend 不会从 osmosis_ai.rollout 或 osmosis_ai.rollout.backend re-export。从 0.3.7 起,harbor extra 会同时安装 Harbor 及其 Daytona 和 OpenSandbox environment dependencies,使用这两个 provider 均无需额外安装包。

Harbor 版本兼容性

从 0.3.8 起,harbor extra 支持 Harbor >=0.20.0,<0.25。单独升级 Harbor 不会改变 SDK 已发布的 harbor-v1 source-image identities,也无需重建这些 image。 将现有 task 或原生 agent 配置迁移到 Harbor 0.23 时:
  • 移除不受支持的 native_agent_kwargs;带有 options schema 的 agent 会拒绝未知 key 和无效类型。
  • 使用可移植且忽略大小写后仍唯一的 step name,并确保 Git task 路径相对于 repository 且不超出 repository 范围。
  • 原生 verifier 的 reward.json 中每个值都必须是有限 JSON 数值,例如 {"reward": 1};带引号的数字和非数值字段会导致解析失败。SDK grader 已写入数值 reward。
  • 允许 Mini-SWE setup 下载其托管的 Python 3.12 toolchain。
读取原生 trajectory 文件的工具必须支持已安装 Harbor 版本的 schema。例如,Harbor 0.23 的 Terminus 写入 ATIF v1.8;SDK 会将这份原生 evidence 与自己的 canonical trajectory 分开保留。

选择 Task Mode

task_mode 决定谁拥有 instruction、如何选择默认 task,以及 request prompt 是否进入 task。 两种 mode 都使用 Harbor trials,并提供相同 isolation。Mode selection 改变 task semantics,不改变 sandbox technology。

Template Mode

Template mode 会让每个 rollout 从一个 task directory 开始。Request 包含 prompt 时,backend 会复制 task,并在 Harbor 启动 trial 前用该 prompt 替换 instruction.md。AgentWorkflow 从 ctx.prompt 读取原始 messages;native agent 读取的内容见Native Agent 如何接收 Prompt。
如果每个 rollout 都提供 prompt,则配置好的 template 可以不含 instruction.md。如果还希望该目录通过 Harbor 独立 task validation,请添加 placeholder instruction。Backend 提供 Osmosis Grader 时,tests/test.sh 可选。
本页示例都在 OpenSandbox 中运行 trial。OpenSandbox 会从 task.toml 中 docker_image 指定的预构建 image 启动每个 trial。该要求以及 Daytona 的用法见Managed 与 Self-Hosted Environments。 Template mode 是最接近 LocalBackend 的 Harbor 路径:一个 workflow 处理变化的 dataset prompts。当这些 prompts 每次都需要同一套隔离 operating system、tools、services 或 filesystem setup 时,请选择它。
在 template mode 中,metadata["harbor_task"] 可以为某个 request 选择另一个 task,但 request prompt 仍会替换该 task 的 instruction。动态选择的 task 自带 instruction 被覆盖时,backend 会记录 warning。

Native Agent 如何接收 Prompt

Native Harbor agent 接收的是一段 task 字符串,而不是 message list。Agent 会把这段字符串作为用户任务放进自己的 prompt,并保留自己的 system prompt:Terminus 2 把它放在 Task Description: 下面,mini-swe-agent 通过 --task 传入,OpenCode 把它作为 opencode run 的消息发送。 当每条 message 都是 system 或 user role、content 为字符串且没有其他字段时,backend 会按顺序把 message 内容写入 instruction.md,以空行分隔,不加 role 标签。因此 dataset 的 system_prompt 会成为 task 文本的开头,而不是 agent 的 system prompt。 包含其他 roles、非字符串 content(例如图片)或额外 message fields 的 prompt 会保留 JSON 形式,以免丢失结构化信息。这个 fallback 不是 conversation replay,也不是原生 multimodal input。Dataset mode 始终保留 task 自带的 instruction。 例如,下面这行 dataset row:
会生成这个 instruction.md:
Rows 在 native agents 上运行时,请把 system_prompt 写成任务说明,而不是 assistant persona。Agent 已经有自己的 persona,像 “You are a helpful multiplier” 这样的句子会在 task 中形成第二个身份。请给 worked examples 加标签或与真实输入分开,因为 user content 会紧接在 system content 之后。

Dataset Mode

Dataset mode 会把每个 Harbor task 当作完整工作单元。Task 保留自己的 instruction.md、environment、configuration 和 verifier。
配置 root directory 和一个原生 Harbor agent 或 Osmosis workflow:
从 0.3.8 起,prewarm_lifespan() 可以省略 task ID,自动发现 tasks_dir 下的 task。若只需预热部分 task 或需要兼容旧版 SDK,请显式传入 ID。 每个 Osmosis metadata-mode dataset row 都通过 directory name 选择 Harbor task:
Backend 会在 dataset mode 中主动移除所有 request prompt。Harbor 会把选中 task 的 instruction 传给原生 agent 或打包后的 AgentWorkflow。通常由 task verifier 计算 reward;如果缺少 tests/test.sh,则由配置好的 Osmosis Grader 提供 verifier。

集成已有 Harbor Dataset

如果本地 dataset 已经可以通过 harbor run 运行,可复用的边界是其 task directories:
1

保留 task directories

把 tasks_dir 指向本地 dataset root。每个 child 都必须是 Harbor task,包含 task.toml、instruction.md、environment/,以及该 task 所需的 verifier files。
2

选择受支持的 agent track

如果符合需求,请使用 agent="terminus-2"、"mini-swe-agent"、"opencode"、"pi" 或 "oracle"。否则请把 agent behavior 打包为 Osmosis AgentWorkflow,并传入其 class 或 import path。
3

创建 selector dataset

上传 Osmosis metadata-mode dataset,其中 harbor_task_id values 与 task directory names 对应。Platform dataset 负责选择 trials;Harbor task directories 仍与 rollout code 放在一起。
4

训练前先运行 evaluation

开始 training 前,确认原生 verifier 会输出 reward channel,并且 trainable agent 会生成可用 trajectory。
这条路径会复用 task content,而不是完整 Harbor job definition。HarborBackend 不会读取 Harbor JobConfig、dataset filters、attempt counts、任意 agent configs 或 harbor run CLI flags。Osmosis 会提供 request scheduling、model endpoint、结果轮询和 rollout identity。

动态 Task Sources

在任一 mode 中,request 都可以设置 metadata["harbor_task"],替代配置好的默认选择: 为保证可复现性,请固定 package references 和 Git commits。Instruction ownership 仍由 task_mode 决定:template mode 会替换 fetched task 的 instruction,dataset mode 则保留它。
请把这些字段视为受信任的 control-plane 输入,而不是不受信任的 dataset 内容。Rollout server 会在 trial sandbox 之外解析、下载并暂存被引用的 task,而 task 的 Dockerfile 和 verifier scripts 都是可执行内容。只接受来自你可控 task sources 的 harbor_task、git_url 和 git_commit_id。

Agent 执行轨道

agent 会选择两种 execution track 之一: AgentWorkflow project 必须包含 pyproject.toml 和可导入 Python package,task image 也必须支持 Python。无法推断 project 时请传入 code_dir,也可以传入预构建 bundle wheel。Task image(其 docker_image 或 Dockerfile)应专注于 task dependencies;backend 会安装 rollout bundle,并可把其声明的 dependencies 预装到复制后的 image。 已注册 native names: AgentWorkflow 使用 workflow_config。native_agent_kwargs 只能用于已注册原生 agent。model_name 默认为 openai/osmosis-rollout;每个 request 的 metadata 可以通过 harbor_model 覆盖它。 对于 agent="mini-swe-agent",通过 native_agent_kwargs={"reasoning_effort": "high"} 设置 reasoning effort,同时保留 rollout 的 Chat Completions endpoint。顶层 effort 优先于内联 config 或 YAML config_file 中的 effort,其他设置保持不变。config 和 config_file 不能同时使用。
在单独 Harbor installation 中可用的 custom agent name,不会自动在 HarborBackend 中可用。Backend 只接受上面已注册的 native names 或 Osmosis AgentWorkflow。

原生 OpenCode

从 0.3.4 起,可用 agent="opencode" 运行现有 Harbor task。SDK 会将 OpenCode 连接到当前 rollout 的模型 endpoint,并禁用自动 compaction 和 pruning,以保留训练 trajectory。
按上方 dataset mode 的示例将 backend 传给 create_rollout_server();托管运行的 sandbox 凭据由 Platform 提供,详见下文。可通过 native_agent_kwargs={"version": "1.18.27"} 固定 OpenCode 版本,该选项同时用于执行和 prewarm。通过 native_agent_kwargs["opencode_config"] 传入额外的 OpenCode 配置,但 endpoint、认证和 compaction 设置由 SDK 管理。 从 0.3.8 起,只要 stdbuf 可用,OpenCode 就会复用预装在 /opt/osmosis-agent/bin 下的可用运行时。如果固定了版本,已安装版本必须匹配。否则 setup 会回退到安装 OpenCode。执行和 prewarm 都采用此行为。 model_name 必须采用非空的 provider/model 格式,默认值 openai/osmosis-rollout 已满足要求。每个 request 可通过 metadata["harbor_model"] 覆盖它;空值、空字符串及非字符串会被拒绝。

原生 Pi

使用 agent="pi" 可通过 Pi 编码 agent 运行现有 Harbor task。SDK 会将 Pi 连接到当前 rollout 的 chat-completions endpoint,并禁用 Pi 的自动上下文 compaction,使训练 trajectory 保持只追加。
SDK 还会安装 Pi 的 subagent extension 以及两个 subagent 定义:general 和 worker。Pi 可调用其 subagent tool 委派工作,例如用 {"agent": "general", "task": "<child prompt>"} 启动单个子 agent,或用 {"tasks": [...]} 并行启动多个子 agent。每个 subagent 都继承 rollout model,因此子 Pi 进程与父进程调用同一个 endpoint。SDK 会将 Pi 的 session log 转换为 rollout trajectory,其中包含 subagent 运行报告的 token 用量。 与 OpenCode 相同,model_name 必须采用非空的 provider/model 格式。

Reward Source 与优先级

Harbor 始终把 task-provided verifier 作为权威来源: v0.3 不再提供 custom_tests_dir。请把原生 verifier files 放在每个 task 的 tests/ directory 中。原生 verifier 必须写入 Harbor 的 reward channel,通常通过 /logs/verifier/reward.txt,或包含数值 reward key 的 reward.json(Harbor 0.23 要求该文件中的每个值都是有限数值);backend 不会猜测其他 channel。

Constructor 参考

Prewarming、Capacity 与 Cancellation

prewarm_lifespan() 会在 server 接收流量前执行 prewarm。也可以直接调用 await backend.prewarm()。是否构建 Dockerfile 取决于选中的 environment;OpenSandbox 使用预构建 image。Template mode 会预热配置好的 task。从 0.3.8 起,dataset mode 在省略 task_ids 时会自动发现 tasks_dir 下的 task;传入 ID 则只预热选中的 task。 通过 constructor 的 prewarm 参数选择模式,或使用 prewarm(..., prewarm="full")、prewarm_lifespan(..., prewarm="full") 覆盖单次调用的模式: 进度日志会记录每个已完成的 task、耗时及失败阶段。个别 task 失败时,server 仍可启动,但这些 task 不可用;选择它们的 rollout 会返回已记录的失败原因。大范围失败或重复出现的认证、代理、配额错误会中止启动。可通过 backend.prewarm_summary 和 backend.failed_prewarm_tasks 查看结果。 使用 OpenSandbox 时,正整数 OPENSANDBOX_MAX_SANDBOXES 将 prewarm 并发数限制为该值的一半,向下取整且至少为一。Platform 可以为托管运行提供此限制。预热使用 Harbor queue,其并发与 rollout trial limit 分开控制。未显式传入 queue 时,即使 rollout 上限更低,queue 容量也至少为 8。

Trial Limit

Trial limit 是单个 rollout server 同时运行的 Harbor trials 数量。从 SDK 0.3.11 开始,orchestrator 为可选参数,HarborBackend 按以下规则确定该限制: 省略 orchestrator,让 Platform 运行使用各自的限制。如果传入的 TrialQueue 的 n_concurrent 更低,rollout server 运行的 trials 会少于调用方发送的数量,server 会在启动时记录一条警告。限制小于 1 时 server 无法启动。 启动时,rollout server 会记录一行日志,说明 trial limit 及其来源,例如 Trial limit: 32 at once (set by the platform for this run).。Server 的 /health 响应以 concurrency.max_concurrent 报告该限制。本地 osmosis eval run 会将 in-flight rollouts 限制为该值与 max_queue_depth 中的较小值。

Queue Depth 与 Cancellation

max_queue_depth 限制等待中的 rollouts,让 server 可以返回 HTTP 429,而不是无限扩展 queue。rollout_status() 报告 queued、running、grading 或最近完成的 state;cancel_rollouts() 可以按 ID、prefix 或全部取消 queued 或 running work。 rollout_status() 仍可用于 backend 本地诊断,但 server 的结果轮询从活跃的 RolloutContext 读取进度。自定义 backend 必须 await RolloutContext.set_status() 发布状态;调用方可使用 RolloutClient 观察进度和取消单个 rollout。 如果传入 TrialQueue,请保持其默认 RetryConfig(max_retries=0)。Backend 的 terminal-event contract 不支持 queue-level attempt retries;如需重试,请使用新的 rollout ID 重新提交。

Server 关闭

从 0.3.6 起,通过 SIGTERM 停止 rollout server 会自动调用 backend 清理:
  1. Server 停止接收新 rollout,给进行中的任务 10 秒完成。
  2. Server 请求取消任务并等待最多 120 秒完成清理,随后直接取消剩余 rollout task,再等待最多 10 秒。
  3. HarborBackend.shutdown() 取消剩余 trial,并额外等待最多 180 秒完成清理,包括 artifact 归档。
Harbor 在取消 trial 时根据 environment 的 delete 设置清理 sandbox。如果清理超时,backend 会向 stdout 输出未完成的 rollout 数量。这不是剩余 sandbox 数量,也不表示已确认删除成功。 为这些 SDK 清理阶段预留最多 320 秒,另加 Uvicorn 在应用停机前等待进行中的 HTTP 请求结束的时间,以及进程关闭的额外开销。Host 的 termination grace period 应覆盖这些时间总和;320 秒不是整个停机过程的上限。强制终止可能中断清理;启用 Daytona 的自动停止策略时,该策略仍作为独立的清理保障。

Managed 与 Self-Hosted Environments

通过 environment_config 显式选择 Harbor environment。上面的示例使用 OpenSandbox,它会如下方所述从预构建 image 启动每个 trial。需要 Harbor 从 Dockerfile 构建的 task 请选择 Daytona。省略 environment_config 会保留 Harbor 默认的 Docker 环境,不会自动选择托管 sandbox。 托管的 evaluation、training 和 dev server 运行会获得 Platform 托管的 OpenSandbox 与 Daytona 凭据,因此选择其中任一 environment 的 rollout 都不需要 sandbox secret。托管 OpenSandbox 凭据按运行签发:它只能访问该运行自己创建的 sandbox,并在运行结束时失效。 Harbor 会为 Daytona 构建选中 task 的 Dockerfile;您不需要手动构建或推送 image、配置 registry credentials 或选择 cluster。 若要在托管运行中使用自己的 Daytona account,请在 evaluation 和 training configs 的 [secrets].required 中添加 DAYTONA_API_KEY,并保留其他必需的名称。使用以下命令保存凭据:
对于本地 osmosis eval run,请通过进程环境变量或 --secrets-file 提供 DAYTONA_API_KEY;仅创建 Platform secret record 不会让该凭据在本地可用。不要将 secret 值写入 TOML config。 osmosis eval run 在 local eval 中支持所有 Harbor environment,并保留 entrypoint 原有的 environment_config。当解析出的 sandbox 无法访问开发者机器的 loopback interface(OpenSandbox、Daytona,或 macOS 之外的 Docker)时,CLI 会自动启动托管的 cloudflared tunnel,让 sandbox 能够访问本地 model bridge;也可以使用 --advertise-url 指向您自行运行的 tunnel。参见 eval run。 EnvironmentType.DOCKER 也仍适用于有 Docker daemon 的自托管 SDK harness,但 managed rollout server 不提供该 daemon。自托管 harness 同样可以选择 EnvironmentType.DAYTONA;harbor extra 已包含其 dependencies,因此只需额外提供 Daytona credentials。

OpenSandbox 路由与预构建 Image

使用以下配置选择 OpenSandbox:
对于内置 OpenSandbox environment(import_path=None),SDK 0.3.7 会应用以下默认值: SDK 0.3.9 会设置 request_timeout_sec:当 OPENSANDBOX_REQUEST_TIMEOUT_SEC 为正整数秒数时使用该值,否则保留 Harbor 的默认值。 显式 kwargs 优先,SDK 不会修改传入的 config object。自定义 import_path environment 不会获得这些路由默认值。已配置托管 OpenSandbox 的 Platform 运行会自动收到 sandbox 凭据;请勿将这些托管凭据添加到 [secrets].required。本地 evaluation 或自托管 server 需要在进程环境变量中导出 OpenSandbox server 的 OPENSANDBOX_DOMAIN 和 OPENSANDBOX_API_KEY。CLI 对 logs.txt 中环境凭据的脱敏不包括 OPENSANDBOX_API_KEY,因此上传本地 run 前请检查日志。 OpenSandbox 要求每个 task 的 task.toml 在 [environment] 下指定预构建 docker_image。它不会构建 environment/Dockerfile,也不支持 Docker Compose task。例如,仅使用 Python 的 task 可从以下 image 开始:
使用包含 task dependencies 的 image,并通过 digest 固定版本以保证可复现性。SDK 的 Dockerfile patching 不会改变预构建 image。从 0.3.7 起,没有 Dockerfile 的 task 会自动跳过 patching;显式设置 patch_dockerfile_with_sdk=True 时,每个 task 只会记录一次警告,不会失败。 如果未预装 SDK environment,打包的 workflow 或 Osmosis grader 会将 wheel 及其 dependencies 安装到 image 的 system Python。Image 需要 Python 3.12 或更高版本,以及可用的 uv 或 python3 -m pip。若要预装 dependencies,请在 image 中将静态 uv 放到 /opt/osmosis/uv,在 /opt/osmosis/venv 创建 Python 3.12 virtual environment,并安装 bundle 的所有 requirements。存在该 virtual environment 时,trial 会使用 /opt/osmosis/uv 和 --no-deps 仅安装 bundle wheel。该 binary 和预装 dependencies 都不可缺少。托管运行的 image 应构建为 linux/amd64。

Daytona Sandbox 生命周期默认值

在 0.3.3 中,内置 Daytona 环境(type="daytona"、import_path=None 且 delete=True)默认设置 auto_stop_interval_mins=60 和 auto_delete_interval_mins=0。Daytona 在观测到 sandbox 连续 60 分钟无活动后将其停止,并在停止后立即删除。这为 rollout server 崩溃提供清理保障;正常的 trial 清理以及 agent 或 grader timeout 仍然生效。 活动指 Daytona 能识别的交互,不是 sandbox 内部的 CPU 运算。Server 驱动命令时,Harbor 的命令轮询通常会刷新活动。该策略不检查 server 健康状态,其他客户端的活动也可能让 sandbox 在 server 崩溃后继续存活。 如果 trial 存在较长时间没有 Daytona 可见活动的阶段,请在 environment_config.kwargs 中设置更大的间隔,或设为 0 禁用自动停止:
将此配置传给 HarborBackend(environment_config=environment_config, ...)。SDK 保留显式的生命周期设置,并且不会为 delete=False、自定义 import_path 或其他 provider 添加默认值。禁用自动停止后,清理由正常 trial 清理或您自己的清理策略负责。
Harbor 0.22 和 0.23 对基于 snapshot 的 Daytona sandbox 强制在停止后立即删除,即使指定了非零删除间隔;GPU task 也不接受非零删除间隔。默认值 0 适用于这两条路径。

下一步

执行后端概览

比较 LocalBackend、Harbor template mode 和 Harbor dataset mode。

v0.3 迁移

替换 legacy Harbor constructor 和 execution model。
最后修改于 2026年11月6日