HarborForge
Forge Harbor task directories from any evaluation benchmark.
HarborForge provides the abstract contracts (DataMapper, DatasetHandler) for turning raw benchmark datasets into Harbor-compatible task directories, enabling large-scale parallel agent evaluation.
How it works
Raw benchmark data
↓ DataMapper.map()
Harbor task directories
↓ harbor jobs start
Agent runs in isolated Docker container
↓
Verifier scores the output → reward written to Harbor
Each task directory contains an instruction.md (shown to the agent), a Dockerfile (the agent's environment), and a test.sh verifier that writes a float reward to /logs/verifier/reward.txt.
Installation
pip install harborforge
Or with uv:
uv add harborforge
Requires Python 3.11+.
Usage
Implement DatasetHandler for each dataset type in your benchmark, then DataMapper to iterate over tasks:
from harborforge import DataMapper, DatasetHandler
class MyHandler(DatasetHandler):
dataset_name = "my_dataset"
def instruction(self, task_data):
return f"Solve this: {task_data['problem']}"
def dockerfile(self, task_data):
return "FROM python:3.12-slim\nWORKDIR /app\n"
def test_sh(self, task_data):
answer = task_data["answer"]
return f"""#!/bin/bash
mkdir -p /logs/verifier
actual=$(cat /output/answer.txt 2>/dev/null)
[ "$actual" = "{answer}" ] && echo 1 || echo 0 > /logs/verifier/reward.txt
"""
class MyMapper(DataMapper):
def iter_tasks(self):
for i, task in enumerate(load_my_benchmark()):
yield f"my_dataset/{i}", f"my_dataset/{i}", MyHandler(), task
# Generate Harbor task directories
MyMapper().run(output_dir=Path(".data/tasks"), registry_path=Path("registry.json"))
By default, map()/run() refuse to touch a non-empty output_dir and raise FileExistsError. Pass overwrite=True to wipe and recreate it, as in earlier versions.
Handler contract
| Method | Required | Purpose |
|---|---|---|
instruction(task_data) |
✅ | Content for instruction.md — no answer leakage |
test_sh(task_data) |
✅ | Content for tests/test.sh — must write float reward to /logs/verifier/reward.txt |
dockerfile(task_data) |
✅ | Content for environment/Dockerfile |
setup() |
optional | Download/prepare data for this dataset |
data_files(task_data) |
optional | Local files to COPY into the image build context |
verifier_files(task_data) |
optional | Local files to COPY into the SEPARATE verifier build context (tests/ → /verifier/) |
solution_sh(task_data) |
optional | Content for solution/solve.sh — a reference solution Harbor's oracle agent can run to validate the task and verifier |
solution_files(task_data) |
optional | Local files to COPY into solution/ alongside solve.sh |
task_toml(task_id, task_data=None) |
optional | Content for task.toml — override to set per-task metadata, timeouts, or allow_internet |
artifacts() |
optional | Container paths to capture after trial |
verifier_env_keys() |
optional | Env var keys to forward to the SEPARATE verifier |
verifier_image_tag(task_data) |
optional | Pre-built image for SEPARATE verifier (skips slow base layers) |
verifier_dockerfile(task_data) |
optional | Full verifier Dockerfile when no pre-built image tag |
SEPARATE verifier mode activates when any of verifier_dockerfile(), verifier_image_tag(), or verifier_files() is set. Files from verifier_files() are copied into tests/ and the generated Dockerfile adds COPY {dest} /verifier/{dest} lines (top-level directories deduplicated).
solution/ is emitted only when solution_sh() returns non-None or solution_files() is non-empty, preserving prior output for handlers that don't implement it.
CLI
Installing the package also installs a harborforge command:
harborforge --version
harborforge registry <tasks_dir> <registry_path> # same as generate_registry()
Metadata
Release files for harborforge 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| harborforge-1.2.0.tar.gz | 37.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| harborforge-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.5 kB
Release files / harborforge-1.2.0.tar.gz
| Download URL | harborforge-1.2.0.tar.gz |
|---|---|
| Size | 37.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8c89f59a4fcbf7cf789ec64f200c3a6c180b8e810e98a06cbd2a904d71927caf
|
|
BLAKE2b-256 checksum How to use checksums |
8cb7ffba921e96eca955d2ccd859160bc264fc528a8cd186874288cd5b6696db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / harborforge-1.2.0-py3-none-any.whl
| Download URL | harborforge-1.2.0-py3-none-any.whl |
|---|---|
| Size | 13.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f773c791ea0fbb8a4ffa4457badbf96f688aed338678f7f26b51f7e65515900e
|
|
BLAKE2b-256 checksum How to use checksums |
b8e7268a18891620e6897fbace1b9ff2b26ffbf14ccaaf83694198c056a17914
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|