Harbor Framework 深度调研
Harbor Framework 深度调研
一句话概括:Harbor 是一个开源框架,用于在容器化沙箱环境中评估和优化 AI Agent 及 LLM——从跑 benchmark、生成 RL rollout 到 prompt 优化,一站式解决。
1. 项目概览
| 项 | 值 |
|---|---|
| GitHub | harbor-framework/harbor |
| Stars | ~4,500 |
| License | Apache 2.0 |
| 语言 | Python(CLI + SDK)、TypeScript、MDX、Shell 等 |
| 版本 | v0.16.1 |
| 创建时间 | 2025-08-04 |
| 官方文档 | harborframework.com |
| 来源 | Terminal-Bench 团队(Laude Institute) |
诞生背景
2025 年 5 月,Terminal-Bench 发布后,团队发现社区把它用于了很多非预期的场景:自定义 eval、prompt 优化、RL 训练、生成 SFT traces、CI/CD agent 测试等。核心痛点浮现——在大规模容器化任务中定义和管理 agent eval 极其困难。Harbor 应运而生,将 Terminal-Bench 的经验抽象为通用框架。
2. 核心概念
Harbor 的架构围绕 5 个核心原语 构建:
graph LR
T[Task] --> D[Dataset]
D --> J[Job]
A[Agent] --> J
E[Environment] --> T
J --> Tr[Trial]
2.1 Task(任务)
一个 task = 一条指令 + 一个容器环境 + 一个测试脚本。
目录结构:
my-task/
├── instruction.md # 任务指令(给 agent 看)
├── task.toml # 配置 & 元数据
├── environment/ # 环境定义
│ └── Dockerfile
├── solution/ # (可选)Oracle 解决方案
│ └── solve.sh
└── tests/ # 验证脚本
└── test.sh
task.toml 关键配置项:
schema_version = "1.4"
[task]
name = "org/name"
version = "1.0.0"
description = "..."
authors = [{ name = "...", email = "..." }]
keywords = ["programming"]
[metadata]
difficulty_explanation = "..."
category = "programming"
[verifier]
timeout_sec = 120.0
env = { API_KEY = "sk-test-123" }
user = "root"
[agent]
timeout_sec = 120.0
user = "agent"
[environment]
network_mode = "no-network" # public | no-network | allowlist
build_timeout_sec = 600.0
docker_image = "some-org/some-name:some-tag"
os = "linux" # 或 "windows"
cpus = 1
memory_mb = 2048
storage_mb = 10240
gpus = 0
gpu_types = ["H100", "A100"]
[environment.tpu] # 可选
type = "v6e"
topology = "2x4"
[[environment.mcp_servers]]
name = "mcp-server"
transport = "streamable-http"
url = "http://mcp-server:8000/mcp"
[environment.healthcheck]
command = "curl -f http://localhost:8080/health"
interval_sec = 5.0
timeout_sec = 30.0
retries = 3
网络策略(分层模型)
网络访问采用三层叠加机制:
| 层 | 字段 | 作用时机 |
|---|---|---|
| Baseline | [environment].network_mode |
环境启动时 |
| Phase Override | [agent].network_mode / [verifier].network_mode |
agent.run() 或 verify() 期间 |
| Run-time Merge | --allow-environment-host / --allow-agent-host |
CLI 运行时合并 |
模式:public(默认)| no-network | allowlist + allowed_hosts
Shared vs Separate Verifier
- Shared(默认):verifier 在 agent 同一容器内运行,可看到 agent 的工作目录和环境变量
- Separate:独立 verifier 容器,适用于需要隔离评分代码、不同 OS、干净镜像的场景
通过 [verifier.environment] 配置声明。
Multi-Step Tasks
支持将任务拆分为顺序步骤,每步有独立的 instruction、tests、可选的 pre-agent setup。早期步骤可用 shared verifier 快速反馈,最终步骤用 separate 锁定评分。
2.2 Dataset(数据集)
Task 的集合,通常对应一个 benchmark(Terminal-Bench、SWE-Bench Verified 等)。可通过 Harbor Registry 分发。
已支持的外部 benchmark:
- Terminal-Bench@2.0(官方 harness)
- SWE-Bench
- Aider Polyglot
- 更多通过
harbor datasets list查看
2.3 Agent(智能体)
两类接口:
| 类型 | 接口 | 特点 |
|---|---|---|
| External Agent | BaseAgent |
通过 BaseEnvironment.exec() 与环境交互,逻辑在容器外 |
| Installed Agent | BaseInstalledAgent |
安装进容器内,headless 模式运行,可携带自定义工具 |
已预集成的 Agent:Terminus-2(参考实现)、Claude Code、Codex CLI、OpenHands、Copilot CLI、Gemini CLI、Grok Build、Aider、Antigravity SDK、Mini-SWE-Agent、Cline CLI、Cursor CLI、fx、MCode 等
自定义 Agent 示例:
# Installed Agent
from harbor.agents.installed.base import BaseInstalledAgent, with_prompt_template
class MyAgent(BaseInstalledAgent):
async def install(self, environment):
await self.exec_as_root(environment, "apt-get update && apt-get install -y curl")
await self.exec_as_agent(environment, "pip install my-agent")
@with_prompt_template
async def run(self, instruction, environment, context):
await self.exec_as_agent(environment, f"my-agent run {shlex.quote(instruction)}")
def populate_context_post_run(self, context):
pass
运行自定义 agent:
harbor run -d "dataset@version" --agent path.to.agent:MyAgent
2.4 Environment(容器环境)
统一接口 BaseEnvironment,已适配:
| 云沙箱 | 类型 |
|---|---|
| Daytona | 云开发环境 |
| Modal | Serverless Python |
| E2B | 安全沙箱 |
| Runloop | 开发环境 |
| Tensorlake | Serverless |
| LangSmith | LangChain 生态 |
| Blaxel | 云沙箱 |
| Novita Sandbox | GPU 沙箱 |
| EC2 | AWS 原生 |
| Beam | GPU 云 |
| Hyperbrowser | 浏览器沙箱 |
| Vercel Sandbox | Vercel 生态 |
| GKE | Google Kubernetes Engine(TPU 支持) |
本地环境:Docker(默认)
自定义环境:实现 BaseEnvironment 接口即可。
2.5 Trial & Job
- Trial:一次 agent 尝试完成 task 的过程 = 一个 rollout → 产生 reward
- Job:Trial 的集合。一个 Job 可包含多个 dataset、agent、task、model 的组合
Job 配置:
# YAML 配置文件
harbor run -c "path/to/job.yaml"
# 或 adhoc 模式
harbor run -d "dataset@version" -m "model" -a "agent"
3. Terminus-2:参考 Agent 实现
Terminus-2 是 Harbor 内置的高性能参考 agent,专为评估 LLM 在终端环境中的能力而设计。
设计哲学
| 特性 | 说明 |
|---|---|
| Mono-tool | 唯一工具 = 交互式 tmux session,可发送按键、滚动输出、启动新 shell |
| 独立进程 | Agent 逻辑在容器外的独立 Python 进程,通过远程连接操作容器 |
| 自主优先 | 完全自主运行,不请求人类输入,适合沙箱环境 |
关键配置
AgentConfig(
name=AgentName.TERMINUS_2,
model_name="openai/gpt-5",
kwargs={
"parser_name": "json", # json | xml
"temperature": 0.7,
"max_turns": 100,
"enable_summarize": True, # 上下文摘要
"proactive_summarization_threshold": 8000,
"collect_rollout_details": False, # RL 训练用
"reasoning_effort": "medium", # none..max
"max_thinking_tokens": 2048, # Anthropic extended thinking
"session_id": "auto", # 用于 prefix cache 路由
}
)
对话历史管理
三步摘要流程,避免长上下文溢出:
Previous History → 1. Summary Subagent → 2. Question Subagent → 3. Answer Subagent → Compressed History
4. Reward Kit:轻量级验证器框架
独立的 Python 包(harbor-rewardkit),零外部依赖,用于定义和运行 verifiers。
安装
uv tool install harbor-rewardkit
# 或带图片/文档解析能力
uv tool install harbor-rewardkit[all]
与 Harbor 集成
# tests/test.sh
uvx --with harbor-rewardkit@0.1 rewardkit /tests
自动发现 /tests/ 下所有 criteria,对 /app 工作空间评估,结果写入 /logs/verifier/reward.json。
两类 Criteria
1. Programmatic(编程式):
import rewardkit as rk
# 内置 criteria(20+)
rk.file_exists("output.txt")
rk.file_contains("output.txt", "hello")
rk.command_succeeds("python main.py")
# 自定义 criteria
from rewardkit import criterion
@criterion
def has_valid_output(workspace) -> bool:
output = (workspace / "output.txt").read_text()
return len(output.splitlines()) >= 10
# 带参数
@criterion(description="output has at least {n} lines")
def has_n_lines(workspace, n: int) -> bool:
return len((workspace / "output.txt").read_text().splitlines()) >= n
rk.has_n_lines(10, weight=2.0)
rk.has_n_lines(50, weight=1.0)
2. Judge-based(LLM 评判):
# tests/quality.toml
[judge]
judge = "anthropic/claude-sonnet-4-6"
files = ["/app/main.py"]
[[criterion]]
description = "Is the code correct?"
type = "binary"
[[criterion]]
description = "How readable is the code?"
type = "likert"
points = 5
评分聚合
每个目录下的 .py 和 .toml criteria 形成一个 group,加权平均。可通过 reward.toml 控制聚合方式:
# tests/structure/reward.toml
weight = 2.0
[scoring]
aggregation = "all-pass" # weighted-mean | all-pass | any-pass | threshold | required-pass
threshold = 0.5
5. RL 优化:SkyRL 集成
Harbor 与 SkyRL 深度集成,提供 Trial → Reward → PPO/GRPO 的完整 RL 训练管线。
架构
SkyRL Trainer (PPO) ←→ HarborGenerator ←→ Harbor Trial
↑ ↓
Policy Update Harbor Trial Lifecycle:
1. Start Environment (Docker/Daytona/Modal)
2. Run Agent (Terminus-2 → vLLM HTTP)
3. Run Verifier (test.sh → reward.txt)
4. Cleanup
关键组件
| 组件 | 作用 |
|---|---|
HarborGenerator |
替换 SkyRL 默认 generator,运行 Harbor trial,将结果转为 GeneratorOutput |
HarborTaskDataset |
加载 Harbor task 目录作为 RL 训练数据 |
HarborExp |
入口,扩展 BasePPOExp,串联上述组件 |
Cache Salt 机制
HarborGenerator 为每个 policy 版本生成一个 cache salt,注入 vLLM 请求的 cache_salt 字段。效果:
- 同版本内:prefix cache 复用 → 吞吐提升
- 跨版本:cache 隔离 → 训练正确性保证
- 对全异步训练(weight sync 不完全清除 cache)尤为重要
Session-Aware Routing
SkyRL 的 VLLMRouter 使用 consistent_hash 策略,通过 X-Session-ID header 将同一 session 的请求 pin 到同一 vLLM replica,保持 prefix cache 温热。
关键超参
| 参数 | 位置 | 作用 |
|---|---|---|
agent.kwargs.max_turns |
Harbor | 更多 turn = 更丰富信号,但更慢更贵 |
agent.kwargs.temperature |
Harbor | RL 通常设 1.0 增加探索 |
generator.n_samples_per_prompt |
SkyRL | GRPO 优势估计的每 prompt 轨迹数 |
trainer.algorithm.advantage_estimator |
SkyRL | GRPO / RLOO / reinforce_pp 等 |
environment.type |
Harbor | 沙箱类型:daytona/docker/modal/e2b/gke |
W&B 监控指标
generate/avg_rewardgenerate/avg_response_lengthgenerate/avg_num_turnsgenerate/num_timeout_trajectoriesgenerate/num_error_trajectoriesgenerate/trajectories_context_length_exceededgenerate/trajectories_summarized
6. GEPA 集成
Harbor 还与 GEPA 集成,用于 prompt 优化。GEPA 通过遗传/进化搜索优化 agent 的 prompt template,Harbor 提供评估环境。
7. CLI 速查
# 安装
uv tool install harbor # 推荐
pip install harbor
# 运行 eval
harbor run -d "terminal-bench@2.0" -a claude-code -m anthropic/claude-opus-4-1
# 本地 task
harbor run -p "path/to/task" -a oracle
# 云沙箱(水平扩展)
harbor run -d "terminal-bench@2.0" -a claude-code -m anthropic/claude-opus-4-1 \
--env daytona -n 100
# 查看结果(Web UI)
harbor view
# 列出可用数据集
harbor datasets list
# 列出可用 agents
harbor run --help | grep -A 20 "--agent"
# 创建新 task
harbor init --task "org/name"
# 恢复中断的 job
harbor jobs resume --job-path ~/.harbor/jobs/<job-name>
# AI 分析失败原因
harbor jobs summarize ~/.harbor/jobs/<job-name> --model sonnet
# 导出训练数据
harbor run ... --export-traces --export-sharegpt
# Job 配置文件
harbor run -c "path/to/job.yaml"
8. 架构总览
graph TB
subgraph "用户层"
CLI["harbor CLI"]
SDK["Python SDK"]
end
subgraph "编排层"
Job["JobConfig"]
Trial["Trial"]
end
subgraph "Agent 层"
T2["Terminus-2"]
CC["Claude Code"]
OH["OpenHands"]
CA["Custom Agent"]
end
subgraph "环境层"
Docker["Docker (本地)"]
Daytona["Daytona"]
Modal["Modal"]
E2B["E2B"]
Other["EC2/Beam/GKE/..."]
end
subgraph "验证层"
RK["Reward Kit"]
Script["test.sh"]
Judge["LLM Judge"]
end
subgraph "优化层"
SkyRL["SkyRL (PPO/GRPO)"]
GEPA["GEPA (Prompt Opt)"]
end
CLI --> Job
SDK --> Job
Job --> Trial
Trial --> T2 & CC & OH & CA
Trial --> Docker & Daytona & Modal & E2B & Other
Trial --> RK & Script & Judge
Trial --> SkyRL & GEPA
9. 核心使用场景
| 场景 | 说明 |
|---|---|
| Agent Benchmark | 在标准化 benchmark(Terminal-Bench、SWE-Bench)上横向对比不同 agent |
| 自定义 Eval | 构建领域特定的评估任务,定义自定义验证逻辑和成功标准 |
| RL 训练 | 生成 rollout,接入 SkyRL 做 PPO/GRPO 策略优化 |
| Prompt 优化 | 通过 GEPA 进化搜索最优 prompt template |
| SFT 数据生成 | 导出 agent 轨迹为 ShareGPT 格式,用于监督微调 |
| CI/CD 测试 | 持续评估 agent 版本变更,防止回归 |
10. 与同类工具对比
| 维度 | Harbor | SWE-Bench 原生 | HumanEval / MBPP |
|---|---|---|---|
| 评估粒度 | 完整 agent 行为(多 turn、工具使用) | 单次代码生成 + 测试 | 函数级代码补全 |
| 环境 | 容器化沙箱(Docker/云) | 本地 conda | 无(纯代码) |
| Agent 支持 | 任意 CLI agent | 通常 Codex/Claude | 无 agent 概念 |
| 水平扩展 | 12+ 云沙箱 provider | 有限 | 不适用 |
| RL 集成 | SkyRL + GEPA 深度集成 | 无 | 无 |
| 自定义 eval | task.toml + Reward Kit | 需 fork 仓库 | 需新建数据集 |
11. 评价与思考
优势:
- ✅ 通用性强:不只评估"代码生成",而是评估"agent 完成任务"的全链路能力
- ✅ 开箱即用:主流 agent 全部预集成,一行命令跑 benchmark
- ✅ 水平扩展:12+ 云沙箱 provider,可并行上千 trial
- ✅ RL 原生:SkyRL/GEPA 集成,不是事后加的,是从设计上支持的
- ✅ Reward Kit:编程式 + LLM 评判混合,灵活度高
- ✅ 网络策略精细:三层叠加 + allowlist,安全可控
局限:
- ⚠️ 文档仍在建设中(许多页面为 placeholder)
- ⚠️ Open Issues 722+,项目活跃但问题也多
- ⚠️ 依赖 Docker/云沙箱,对轻量级评估不够友好
- ⚠️ Terminus-2 作为参考 agent,mono-tool (tmux) 设计有争议——灵活性高但不如专用工具精确
定位判断:Harbor 填补了 "Agent Eval Infra" 这一层的基础设施空白。如果说 SWE-Bench 是 benchmark,Harbor 就是跑 benchmark 的引擎 + 自定义 benchmark 的工具箱。对于需要系统性评估和优化 agent 的团队,这是一个值得关注的框架。
12. 实际使用方式与案例
12.1 快速上手:从安装到第一个 Eval
# 1. 安装(推荐 uv)
uv tool install harbor
# 2. 验证安装
harbor --version
# 3. 跑一个本地简单 task(Oracle agent 验证任务可解)
harbor run -p examples/tasks/hello-world -a oracle
# 4. 用真实 agent 跑
harbor run -p examples/tasks/hello-world -a claude-code -m anthropic/claude-sonnet-4-5
# 5. 查看 Web UI 结果
harbor view
第一次运行会构建 Docker 环境,耗时几分钟。后续运行利用缓存会快很多。
12.2 创建自定义 Task:SSH 密钥对生成
完整的 Task 创建流程(10 步):
Step 0-1:初始化
harbor task init ssh-key-pair
cd ssh-key-pair
生成的目录结构:
ssh-key-pair/
├── instruction.md
├── task.toml
├── environment/
│ └── Dockerfile
├── solution/
│ └── solve.sh
└── tests/
├── test.sh
└── test_outputs.py
Step 2:写指令
<!-- instruction.md -->
Generate an SSH key pair using the ssh-keygen command.
Save the private key to /app/id_rsa and the public key to /app/id_rsa.pub.
Use the following options:
- Key type: RSA
- Key size: 4096 bits
- No passphrase (empty passphrase)
- Comment: "harbor-test-key"
Step 3:配置元数据
# task.toml
[metadata]
difficulty_explanation = "Simple SSH key generation command"
category = "system-administration"
tags = ["ssh", "cryptography", "linux"]
[verifier]
timeout_sec = 120.0
[agent]
timeout_sec = 120.0
[environment]
build_timeout_sec = 600.0
Step 4-5:编写 Dockerfile 并手动测试
# 启动交互式容器测试
harbor task start-env -p ssh-key-pair -e docker -a -i
Step 6:写解决方案
#!/bin/bash
# solution/solve.sh
ssh-keygen -t rsa -b 4096 -f /app/id_rsa -N "" -C "harbor-test-key"
Step 7:写验证脚本
#!/bin/bash
# tests/test.sh
cd /app
pip install pytest -q
python -m pytest /tests/test_outputs.py -v
# tests/test_outputs.py
import subprocess
def test_private_key_exists():
result = subprocess.run(["ssh-keygen", "-l", "-f", "/app/id_rsa"],
capture_output=True, text=True)
assert result.returncode == 0
assert "4096" in result.stdout # 4096-bit key
def test_public_key_exists():
with open("/app/id_rsa.pub") as f:
content = f.read()
assert "harbor-test-key" in content
Step 8:用 Oracle 验证任务可解
harbor run -p ssh-key-pair -a oracle
# 成功应显示 reward = 1
Step 9:用真实 agent 测试
harbor run -p ssh-key-pair -a terminus-2 -m anthropic/claude-haiku-4-5
Step 10:查看轨迹
harbor view
# 在 Web UI 中浏览:agent 每步操作、verifier 输出、最终 reward
12.3 Cookbook Recipes 详解
Harbor Cookbook 包含 10 个 Task Recipe + 5 个 Optimization Example,是学习 Harbor 最佳实践的起点。
运行任意 recipe:
harbor run -p harbor_cookbook/recipes/<name> -a claude-code -m anthropic/claude-opus-4-6
Recipe 一览
| Recipe | 核心场景 | 关键技术点 |
|---|---|---|
| simple-task | 最小单容器任务 | instruction.md + Dockerfile + test.sh |
| multi-container | Docker Compose 多服务 | docker-compose.yaml,agent 与本地 REST API 交互 |
| mcp-tools | 给 Agent 自定义 MCP 工具 | FastMCP sidecar + [[environment.mcp_servers]] 声明 |
| multi-reward | 多维度独立评分 | 多个 verifier 各自产出分数 |
| simulated-user | Agent 与模拟用户对话发现需求 | MCP server 模拟用户回答 |
| computer-use-ubuntu | Ubuntu 桌面 GUI 操作 | 虚拟桌面 + computer use 参考实现 |
| computer-use-windows | Windows 远程桌面操作 | Daytona 远程 Windows 桌面 |
| dns-blacklisting | DNS 级网络黑名单 | exact / wildcard / regex 规则 |
| skills | 给 Agent 自定义 skills | Skill 集成机制 |
| multi-step | 多步骤顺序任务 | per-step instruction / tests / workdir / healthcheck / early stopping / artifacts |
Multi-Step Recipe 详解
最复杂的 recipe,展示多步骤任务的完整能力:
steps/
├── scaffold/ # Step 1: 创建 /app/greet.sh
│ ├── instruction.md
│ ├── tests/test.sh
│ └── solution/solve.sh
├── implement/ # Step 2: 读取 config.txt,打印 "Hello, <name>!"
│ ├── instruction.md
│ ├── tests/test.sh
│ ├── workdir/
│ │ ├── config.txt # per-step 文件上传
│ │ └── setup.sh # per-step 预处理脚本(运行后自删除)
│ └── solution/solve.sh
└── document/ # Step 3: 写 README.md
├── instruction.md
├── tests/test.sh
└── solution/solve.sh
task.toml 关键配置:
[[steps]]
name = "scaffold"
min_reward = 1.0 # 低于 1.0 立即终止后续步骤(没有脚手架就没法继续)
[steps.agent]
timeout_sec = 60.0
[steps.verifier]
timeout_sec = 30.0
[[steps]]
name = "implement"
min_reward = 0.5 # 允许部分完成
[steps.agent]
timeout_sec = 120.0
[steps.verifier]
timeout_sec = 30.0
env = { EXPECTED_NAME = "World", EXPECTED_GREETING = "Hello, World!" }
[[steps]]
name = "document"
[steps.agent]
timeout_sec = 60.0
关键机制:
min_reward早停:scaffold 必须满分才继续,implement 允许 50%workdir/setup.sh:per-step 预处理钩子,运行后自删除保持工作目录干净- Per-step healthcheck:implement 步骤检查 scaffold 的
greet.sh是否存在 - Per-step artifacts:每步快照
/app/greet.sh,document 步额外捕获/app/README.md multi_step_reward_strategy:默认"mean",Oracle agent 应产出 1.0
运行:
# Oracle 验证
harbor run -p harbor_cookbook/recipes/multi-step --agent oracle
# 真实 agent
harbor run -p harbor_cookbook/recipes/multi-step --agent claude-code --model anthropic/claude-sonnet-4-6
MCP Tools Recipe 详解
展示如何通过 Docker Compose 运行 FastMCP sidecar,让 agent 调用自定义工具:
docker-compose.yaml:
services:
main:
depends_on:
mcp-server:
condition: service_healthy
mcp-server:
build:
context: ./mcp-server
expose:
- "8000"
healthcheck:
test: ["CMD", "python", "-c", "import socket; ..."]
interval: 2s
timeout: 5s
retries: 15
task.toml 声明 MCP server:
[[environment.mcp_servers]]
name = "mcp-server"
transport = "streamable-http" # sse | streamable-http | stdio
url = "http://mcp-server:8000/mcp"
支持的 agent(如 Claude Code、Codex)会自动注册 MCP server。指令让 agent 连接 MCP、调用 get_secret 工具、将结果写入文件。
Simulated-User Recipe
Agent 必须通过与模拟用户对话来发现需求,而非从 instruction 中直接获取:
task.toml:
[[environment.mcp_servers]]
name = "user-server"
transport = "streamable-http"
url = "http://user-server:8000/mcp"
Agent 的 instruction 不是直接告诉它要做什么,而是告诉它"有一个用户服务器可以对话,去问用户需要什么"。这种模式更接近真实场景——agent 通常需要主动收集信息。
12.4 自定义 Agent 实战
External Agent 示例(OpenAI Agent)
# openai_agent.py
import os, json
from openai import AsyncOpenAI
from harbor.agents.base import BaseAgent
from harbor.environments.base import BaseEnvironment
from harbor.models.agent.context import AgentContext
class OpenAIAgent(BaseAgent):
def __init__(self, max_iterations: int = 10, *args, **kwargs):
super().__init__(*args, **kwargs)
self._max_iterations = max_iterations
self._client = AsyncOpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
@staticmethod
def name() -> str:
return "openai-agent"
def version(self) -> str | None:
return "1.0.0"
async def setup(self, environment: BaseEnvironment) -> None:
pass # 无需安装
async def run(self, instruction, environment, context):
messages = [
{"role": "system", "content": "You are a helpful assistant that solves tasks."},
{"role": "user", "content": instruction}
]
total_input_tokens = 0
total_output_tokens = 0
iterations = 0
for i in range(self._max_iterations):
iterations += 1
response = await self._client.chat.completions.create(
model=self.model_name or "gpt-4",
messages=messages
)
if response.usage:
total_input_tokens += response.usage.prompt_tokens
total_output_tokens += response.usage.completion_tokens
message = response.choices[0].message
messages.append(message.model_dump())
if message.tool_calls:
for tool_call in message.tool_calls:
if tool_call.function.name == "execute_bash":
args = json.loads(tool_call.function.arguments)
result = await environment.exec(args["command"])
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result.stdout or result.stderr or ""
})
if message.content and "task complete" in message.content.lower():
break
context.commands_executed = iterations
context.n_input_tokens = total_input_tokens
context.n_output_tokens = total_output_tokens
context.exit_code = 0
运行:
export OPENAI_API_KEY=<YOUR-KEY>
harbor run --tasks ./my-task \
--agent openai_agent:OpenAIAgent \
--agent-import-path openai_agent.py \
--model gpt-4 \
--ak max_iterations:int=20
12.5 RL 训练实战
方式一:harbor.rl + Tinker
最轻量的 RL 入口,使用 Harbor 的 step() / grade() 接口:
# 下载 Terminal-Bench 2.0 任务
uvx harbor datasets download terminal-bench@2.0
# 启动 RL 训练
uv run python tinker_cookbook/recipes/harbor_rl/scripts/train_terminal_bench.py \
model_name=moonshotai/Kimi-K2.6 \
max_tokens=8192 \
group_size=4 \
groups_per_batch=8 \
learning_rate=1e-5 \
lora_rank=32 \
wandb_project=cookbook_harbor_rl
架构:
HarborBashTool:将 Harbor 的 bash 工具适配为 Tinker 可用的 toolHarborReward:将 Harbor 的grade()适配为 Tinker 的 reward 函数SandboxFactory:后端无关的沙箱工厂,默认使用 Modal,可替换
Kimi-K2.6 基线结果(32K context,无 compaction):
| Benchmark | Total | PASS | FAIL | ERROR | Pass Rate |
|---|---|---|---|---|---|
| SWE-Bench Verified 1.0 | 500 | 145 | 52 | 303 | 29.0% |
| Terminal-Bench 2.0 | 89 | 14 | 31 | 44 | 15.7% |
所有 ERROR 均为 context window 溢出,发生在对话历史超过 ~24.5K tokens 时。
方式二:Tinker Terminal RL Recipe(更灵活)
支持 Docker/Daytona 沙箱,可自定义 renderer:
python tinker_cookbook/recipes/terminal_rl/train.py \
--task-dir harbor_envs/devops_task \
--env docker \
--model-name Qwen/Qwen3-30B-A3B-Instruct-2507 \
--renderer-name qwen3 \
--max-tokens 4096 \
--temperature 0.7 \
--groups-per-batch 4 \
--group-size 8 \
--num-batches 25 \
--learning-rate 4e-5 \
--lora-rank 32
实验结果(单 DevOps task,25 steps):
| 学习率 | 最终 Reward | Turns/Episode | 观察 |
|---|---|---|---|
| 1e-5 | ~0.40 | ~7.0 | 策略停滞 |
| 2e-5 | ~0.45 | ~7.0 | 微弱提升 |
| 4e-5 | ~0.78 | ~5.0 | 显著提升,agent 学会了更高效地完成任务 |
关键发现:sparse-reward 终端任务需要更大的学习率来探索有效命令序列。最佳 run 不仅 reward 最高,turns 也从 7 降到 5——说明模型学会了更高效地解决问题。
方式三:SkyRL(生产级)
# 使用 SkyRL + Daytona 云沙箱做大规模 RL
# 详见 12.7 节完整示例
方式四:GEPA Prompt 优化
不需要训练模型权重,通过进化搜索优化 agent 的 prompt template:
# 在 MedAgentBench 上优化 Codex agent 的 prompt
uv run harbor_cookbook/gepa/optimize.py
效果:Codex + gpt-5-nano 在 MedAgentBench 32-task 验证集上,准确率从 ~28% 提升到 ~50%(3 轮优化后)。
12.6 Reward Kit 实战
混合验证:代码检查 + LLM 评判
tests/
├── test.sh # 入口脚本
├── check.py # 编程式 criteria
├── quality.toml # LLM Judge criteria
└── structure/
├── check.py # 子目录 criteria
└── reward.toml # 聚合配置
tests/test.sh:
#!/bin/bash
uvx --with harbor-rewardkit@0.1 rewardkit /tests
tests/check.py(编程式):
import rewardkit as rk
from rewardkit import criterion
from pathlib import Path
# 内置 criteria
rk.file_exists("/app/main.py")
rk.file_contains("/app/main.py", "def solve")
rk.command_succeeds("python /app/main.py --test")
# 自定义 criteria
@criterion
def no_hardcoded_secrets(workspace: Path) -> bool:
code = (workspace / "main.py").read_text()
return "sk-" not in code and "password" not in code.lower()
# 带参数 + 权重
@criterion(description="at least {n} test cases")
def has_n_test_cases(workspace: Path, n: int) -> bool:
code = (workspace / "main.py").read_text()
return code.count("def test_") >= n
rk.has_n_test_cases(3, weight=1.0)
rk.has_n_test_cases(10, weight=0.5)
tests/quality.toml(LLM 评判):
[judge]
judge = "anthropic/claude-sonnet-4-6"
files = ["/app/main.py"]
[[criterion]]
description = "Does the code handle edge cases correctly?"
type = "binary"
[[criterion]]
description = "How well-structured is the code?"
type = "likert"
points = 5
[[criterion]]
description = "Is the error handling adequate?"
type = "binary"
tests/structure/reward.toml(聚合配置):
weight = 2.0 # 此 group 在维度中占比
[scoring]
aggregation = "all-pass" # 任一检查失败 → 整组 0 分
运行后产出:
// /logs/verifier/reward.json
{ "reward": 0.75 }
12.7 大规模云沙箱评估
Daytona(推荐)
export ANTHROPIC_API_KEY=<KEY>
export DAYTONA_API_KEY=<KEY>
# 100 并发跑 Terminal-Bench 2.0
harbor run \
--dataset terminal-bench@2.0 \
--agent claude-code \
--model anthropic/claude-opus-4-1 \
--n-concurrent 100 \
--env daytona
AWS EC2
export AWS_ACCESS_KEY_ID=<KEY>
export AWS_REGION=us-east-1
harbor run \
--dataset terminal-bench@2.0 \
--agent claude-code \
--model anthropic/claude-opus-4-1 \
--n-concurrent 32 \
--env ec2 \
--ae AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
--ae AWS_REGION=us-east-1
混合 Agent 对比评测
# Job 配置文件方式:同时跑多个 agent + model 组合
harbor run -c job.yaml
# job.yaml 示例
environment:
type: daytona
agents:
- name: claude-code
model: anthropic/claude-opus-4-1
- name: openhands
model: anthropic/claude-sonnet-4
- name: terminus-2
model: openai/gpt-5
datasets:
- terminal-bench@2.0
orchestrator:
n_concurrent_trials: 32
12.8 RL Rollout 接口实战
Harbor 提供了 harbor.rl 模块,直接在代码中生成 rollout:
from harbor.models.trial.config import JobConfig, AgentConfig, EnvironmentConfig
from harbor.models.agent_name import AgentName
from harbor.models.environment_type import EnvironmentType
from harbor.job import Job
from pathlib import Path
class HarborRolloutInterface:
async def run(self, task_ids: list[str]) -> list[dict]:
# 构造 JobConfig
task_configs = [...] # 从 task_ids 构造 TaskConfig 列表
job = Job(
config=JobConfig(
jobs_dir=Path("jobs"),
environment=EnvironmentConfig(
type=EnvironmentType.DAYTONA,
),
agents=[
AgentConfig(
name=AgentName.TERMINUS_2,
model_name="hosted_vllm/my-model",
kwargs={
"base_url": "https://vllm-server:8000",
"collect_rollout_details": True, # 收集 token_ids + logprobs
}
)
],
orchestrator=OrchestratorConfig(
n_concurrent_trials=32,
),
tasks=task_configs,
),
)
result = await job.run()
rollouts = []
for trial_result in result.trial_results:
# 提取 reward
reward = (
trial_result.verifier_result.rewards.get("reward", 0)
if trial_result.verifier_result and trial_result.verifier_result.rewards
else 0
)
# 提取 token_ids 和 mask_ids(用于 RL 训练)
if (trial_result.agent_result
and trial_result.agent_result.metadata
and "token_ids" in trial_result.agent_result.metadata
and "mask_ids" in trial_result.agent_result.metadata):
token_ids = trial_result.agent_result.metadata["token_ids"]
mask_ids = trial_result.agent_result.metadata["mask_ids"]
else:
raise ValueError(f"Missing token_ids or mask_ids for trial {trial_result.trial_name}")
rollouts.append({
"reward": reward,
"token_ids": token_ids,
"mask_ids": mask_ids,
})
return rollouts
Token 收集策略:
- vLLM 服务端拦截:适用于使用 vLLM 生成 token 的框架(SkyRL 采用)
- Agent result metadata:agent 配置
collect_rollout_details=True,在结果中返回token_ids和mask_ids
12.9 轨迹分析与结果查看
Web UI 查看器
harbor view
在浏览器中浏览:
- Trajectory:agent 每步操作,逐 turn 展示
- Verifier Logs:pytest 输出、reward 计算过程
- Artifacts:agent 产出的文件快照
- Performance Metrics:token 使用、耗时等
AI 辅助分析
# 用 Claude 分析失败原因
harbor jobs summarize ~/.harbor/jobs/<job-name> --model sonnet
导出训练数据
# 导出轨迹用于 SFT
harbor run ... --export-traces
# 导出 ShareGPT 格式对话数据
harbor run ... --export-sharegpt
Job 恢复
# 中断后恢复未完成的 trial
harbor jobs resume --job-path ~/.harbor/jobs/<job-name>
12.10 Agent Skill 辅助开发
Harbor 提供了 coding agent 辅助工具,可在开发环境中使用:
# 创建 task 的交互式引导
npx skills add harbor-framework/harbor --skill create-task
# 设计 verifier 的交互式引导
npx skills add harbor-framework/harbor --skill rewardkit