lolspider / notes
Clipping · 10 分钟

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 = 一条指令 + 一个容器环境 + 一个测试脚本。

目录结构:

plaintext
my-task/
├── instruction.md       # 任务指令(给 agent 看)
├── task.toml            # 配置 & 元数据
├── environment/         # 环境定义
│   └── Dockerfile
├── solution/            # (可选)Oracle 解决方案
│   └── solve.sh
└── tests/               # 验证脚本
    └── test.sh

task.toml 关键配置项:

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 示例:

python
# 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:

bash
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 配置:

bash
# 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 进程,通过远程连接操作容器
自主优先 完全自主运行,不请求人类输入,适合沙箱环境

关键配置

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 路由
    }
)

对话历史管理

三步摘要流程,避免长上下文溢出:

plaintext
Previous History → 1. Summary Subagent → 2. Question Subagent → 3. Answer Subagent → Compressed History

4. Reward Kit:轻量级验证器框架

独立的 Python 包(harbor-rewardkit),零外部依赖,用于定义和运行 verifiers。

安装

bash
uv tool install harbor-rewardkit
# 或带图片/文档解析能力
uv tool install harbor-rewardkit[all]

与 Harbor 集成

bash
# tests/test.sh
uvx --with harbor-rewardkit@0.1 rewardkit /tests

自动发现 /tests/ 下所有 criteria,对 /app 工作空间评估,结果写入 /logs/verifier/reward.json。

两类 Criteria

1. Programmatic(编程式):

python
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 评判):

toml
# 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 控制聚合方式:

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 训练管线。

架构

plaintext
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_reward
  • generate/avg_response_length
  • generate/avg_num_turns
  • generate/num_timeout_trajectories
  • generate/num_error_trajectories
  • generate/trajectories_context_length_exceeded
  • generate/trajectories_summarized

6. GEPA 集成

Harbor 还与 GEPA 集成,用于 prompt 优化。GEPA 通过遗传/进化搜索优化 agent 的 prompt template,Harbor 提供评估环境。


7. CLI 速查

bash
# 安装
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

bash
# 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:初始化

bash
harbor task init ssh-key-pair
cd ssh-key-pair

生成的目录结构:

plaintext
ssh-key-pair/
├── instruction.md
├── task.toml
├── environment/
│   └── Dockerfile
├── solution/
│   └── solve.sh
└── tests/
    ├── test.sh
    └── test_outputs.py

Step 2:写指令

markdown
<!-- 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:配置元数据

toml
# 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 并手动测试

bash
# 启动交互式容器测试
harbor task start-env -p ssh-key-pair -e docker -a -i

Step 6:写解决方案

bash
#!/bin/bash
# solution/solve.sh
ssh-keygen -t rsa -b 4096 -f /app/id_rsa -N "" -C "harbor-test-key"

Step 7:写验证脚本

bash
#!/bin/bash
# tests/test.sh
cd /app
pip install pytest -q
python -m pytest /tests/test_outputs.py -v
python
# 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 验证任务可解

bash
harbor run -p ssh-key-pair -a oracle
# 成功应显示 reward = 1

Step 9:用真实 agent 测试

bash
harbor run -p ssh-key-pair -a terminus-2 -m anthropic/claude-haiku-4-5

Step 10:查看轨迹

bash
harbor view
# 在 Web UI 中浏览:agent 每步操作、verifier 输出、最终 reward

12.3 Cookbook Recipes 详解

Harbor Cookbook 包含 10 个 Task Recipe + 5 个 Optimization Example,是学习 Harbor 最佳实践的起点。

运行任意 recipe:

bash
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,展示多步骤任务的完整能力:

plaintext
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 关键配置:

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

运行:

bash
# 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:

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:

toml
[[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:

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)

python
# 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

运行:

bash
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() 接口:

bash
# 下载 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 可用的 tool
  • HarborReward:将 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:

bash
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(生产级)

bash
# 使用 SkyRL + Daytona 云沙箱做大规模 RL
# 详见 12.7 节完整示例

方式四:GEPA Prompt 优化

不需要训练模型权重,通过进化搜索优化 agent 的 prompt template:

bash
# 在 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 评判

plaintext
tests/
├── test.sh                 # 入口脚本
├── check.py                # 编程式 criteria
├── quality.toml            # LLM Judge criteria
└── structure/
    ├── check.py            # 子目录 criteria
    └── reward.toml         # 聚合配置

tests/test.sh:

bash
#!/bin/bash
uvx --with harbor-rewardkit@0.1 rewardkit /tests

tests/check.py(编程式):

python
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 评判):

toml
[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(聚合配置):

toml
weight = 2.0   # 此 group 在维度中占比

[scoring]
aggregation = "all-pass"  # 任一检查失败 → 整组 0 分

运行后产出:

json
// /logs/verifier/reward.json
{ "reward": 0.75 }

12.7 大规模云沙箱评估

Daytona(推荐)

bash
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

bash
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 对比评测

bash
# Job 配置文件方式:同时跑多个 agent + model 组合
harbor run -c job.yaml
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:

python
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 收集策略:

  1. vLLM 服务端拦截:适用于使用 vLLM 生成 token 的框架(SkyRL 采用)
  2. Agent result metadata:agent 配置 collect_rollout_details=True,在结果中返回 token_ids 和 mask_ids

12.9 轨迹分析与结果查看

Web UI 查看器

bash
harbor view

在浏览器中浏览:

  • Trajectory:agent 每步操作,逐 turn 展示
  • Verifier Logs:pytest 输出、reward 计算过程
  • Artifacts:agent 产出的文件快照
  • Performance Metrics:token 使用、耗时等

AI 辅助分析

bash
# 用 Claude 分析失败原因
harbor jobs summarize ~/.harbor/jobs/<job-name> --model sonnet

导出训练数据

bash
# 导出轨迹用于 SFT
harbor run ... --export-traces

# 导出 ShareGPT 格式对话数据
harbor run ... --export-sharegpt

Job 恢复

bash
# 中断后恢复未完成的 trial
harbor jobs resume --job-path ~/.harbor/jobs/<job-name>

12.10 Agent Skill 辅助开发

Harbor 提供了 coding agent 辅助工具,可在开发环境中使用:

bash
# 创建 task 的交互式引导
npx skills add harbor-framework/harbor --skill create-task

# 设计 verifier 的交互式引导
npx skills add harbor-framework/harbor --skill rewardkit

参考链接