Buckets:

download
raw
56.2 kB
<meta charset="utf-8" /><meta name="hf:doc:metadata" content="{&quot;title&quot;:&quot;Harbor Environment&quot;,&quot;local&quot;:&quot;harbor-environment&quot;,&quot;sections&quot;:[{&quot;title&quot;:&quot;Quick start&quot;,&quot;local&quot;:&quot;quick-start&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Execution modes&quot;,&quot;local&quot;:&quot;execution-modes&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Task policies&quot;,&quot;local&quot;:&quot;task-policies&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;The task format&quot;,&quot;local&quot;:&quot;the-task-format&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Rewards&quot;,&quot;local&quot;:&quot;rewards&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Action space&quot;,&quot;local&quot;:&quot;action-space&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Working with Repo2RLEnv&quot;,&quot;local&quot;:&quot;working-with-repo2rlenv&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Writing a task that runs in both places&quot;,&quot;local&quot;:&quot;writing-a-task-that-runs-in-both-places&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Configuration&quot;,&quot;local&quot;:&quot;configuration&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Running in Docker&quot;,&quot;local&quot;:&quot;running-in-docker&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Examples&quot;,&quot;local&quot;:&quot;examples&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Layout&quot;,&quot;local&quot;:&quot;layout&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Tests&quot;,&quot;local&quot;:&quot;tests&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2}],&quot;depth&quot;:1}"/>
<link href="/docs/openenv/pr_1018/en/_app/immutable/entry/start.B9IBUExw.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/chunks/DTQnX4l5.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/chunks/DfHjNWj2.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/entry/app.CiZ4jjXn.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/chunks/Ba1drWuH.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/chunks/K5XANBgt.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/chunks/DsnmJJEf.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/chunks/PGLvW8OU.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/nodes/0.Cl0mWmHV.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/chunks/CFswWuIO.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/nodes/3.PDbBxqNS.js" rel="modulepreload">
<link href="/docs/openenv/pr_1018/en/_app/immutable/chunks/Bln0COW0.js" rel="modulepreload">
<!--gg71d6--><meta name="hf:doc:metadata" content="{&quot;title&quot;:&quot;Harbor Environment&quot;,&quot;local&quot;:&quot;harbor-environment&quot;,&quot;sections&quot;:[{&quot;title&quot;:&quot;Quick start&quot;,&quot;local&quot;:&quot;quick-start&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Execution modes&quot;,&quot;local&quot;:&quot;execution-modes&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Task policies&quot;,&quot;local&quot;:&quot;task-policies&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;The task format&quot;,&quot;local&quot;:&quot;the-task-format&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Rewards&quot;,&quot;local&quot;:&quot;rewards&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Action space&quot;,&quot;local&quot;:&quot;action-space&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Working with Repo2RLEnv&quot;,&quot;local&quot;:&quot;working-with-repo2rlenv&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Writing a task that runs in both places&quot;,&quot;local&quot;:&quot;writing-a-task-that-runs-in-both-places&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Configuration&quot;,&quot;local&quot;:&quot;configuration&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Running in Docker&quot;,&quot;local&quot;:&quot;running-in-docker&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Examples&quot;,&quot;local&quot;:&quot;examples&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Layout&quot;,&quot;local&quot;:&quot;layout&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2},{&quot;title&quot;:&quot;Tests&quot;,&quot;local&quot;:&quot;tests&quot;,&quot;sections&quot;:[],&quot;depth&quot;:2}],&quot;depth&quot;:1}"/><!---->
<link href="/docs/openenv/pr_1018/en/_app/immutable/assets/0.tn0RQdqM.css" rel="modulepreload"> <!--[--><!--[0--><!--[--><!--[0--><!--[--><p></p> <div class="items-center shrink-0 min-w-[100px] max-sm:min-w-[50px] justify-end ml-auto flex" style="float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"><div class="inline-flex rounded-md max-sm:rounded-sm"><button class="inline-flex items-center gap-1 h-7 max-sm:h-7 px-2 max-sm:px-1.5 text-sm font-medium text-gray-800 border border-r-0 rounded-l-md max-sm:rounded-l-sm border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-live="polite"><span class="inline-flex items-center justify-center rounded-md p-0.5 max-sm:p-0 hover:text-gray-800 dark:hover:text-gray-200"><svg class="sm:size-3.5 size-3" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----></span> <span>Copy page</span></button> <button class="inline-flex items-center justify-center w-6 max-sm:w-5 h-7 max-sm:h-7 disabled:pointer-events-none text-sm text-gray-500 hover:text-gray-700 dark:hover:text-white rounded-r-md max-sm:rounded-r-sm border border-l transition border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-haspopup="menu" aria-expanded="false" aria-label="Open copy menu"><svg class="transition-transform text-gray-400 overflow-visible sm:size-3.5 size-3 rotate-0" width="1em" height="1em" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L6 6L11 1" stroke="currentColor"></path></svg><!----></button></div> <!--[-1--><!--]--></div><!----> <!--[0--><h1 class="relative group"><a id="harbor-environment" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#harbor-environment"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Harbor Environment</span></h1><!--]--><!----> <p>Runs <a href="https://www.harborframework.com/docs/tasks" rel="nofollow">Harbor</a> task directories as an
OpenEnv environment.</p> <p><strong>The task directory is the interface.</strong> A directory that <code>harbor run</code> accepts is
served here unchanged — no conversion, no re-authoring, no second copy of the
data. That covers Terminal-Bench-lineage tasks and everything <a href="https://github.com/huggingface/Repo2RLEnv" rel="nofollow">Repo2RLEnv</a> generates from a GitHub
repository, so a task set built for evaluation is also a training environment.</p> <p>The reward always comes from the task’s own verifier. This environment forwards
it and never computes one of its own.</p> <!--[1--><h2 class="relative group"><a id="quick-start" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#quick-start"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Quick start</span></h2><!--]--><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-bash "><!----><span class="hljs-comment"># 1. Serve the bundled example task</span>
uv run --project envs/harbor_env server
<span class="hljs-comment"># 2. Solve it through the client</span>
PYTHONPATH=src:envs uv run python envs/harbor_env/examples/quickstart.py<!----></pre></div><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">import</span> asyncio
<span class="hljs-keyword">from</span> harbor_env <span class="hljs-keyword">import</span> HarborEnv
<span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">main</span>():
env = HarborEnv(base_url=<span class="hljs-string">&quot;http://localhost:8000&quot;</span>)
start = <span class="hljs-keyword">await</span> env.reset(task_id=<span class="hljs-string">&quot;fix-sum-bug&quot;</span>)
<span class="hljs-built_in">print</span>(start.observation.instruction) <span class="hljs-comment"># the task&#x27;s instruction.md</span>
<span class="hljs-keyword">await</span> env.write_file(<span class="hljs-string">&quot;stats.py&quot;</span>, my_fix) <span class="hljs-comment"># the agent works</span>
result = <span class="hljs-keyword">await</span> env.evaluate() <span class="hljs-comment"># the task&#x27;s tests/test.sh grades it</span>
<span class="hljs-built_in">print</span>(result.reward) <span class="hljs-comment"># 1.0</span>
<span class="hljs-built_in">print</span>(result.observation.info[<span class="hljs-string">&quot;reward_metrics&quot;</span>])
<span class="hljs-keyword">await</span> env.close()
asyncio.run(main())<!----></pre></div><!----> <p>Point it at your own tasks with <code>HARBOR_TASKS_DIR</code>, which accepts a local
directory or a Hugging Face dataset:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-bash "><!---->HARBOR_TASKS_DIR=./tasks uv run --project envs/harbor_env server
HARBOR_TASKS_DIR=hf://datasets/my-org/click-tasks uv run --project envs/harbor_env server
HARBOR_TASKS_DIR=./tasks HARBOR_MODE=docker uv run --project envs/harbor_env server<!----></pre></div><!----> <!--[1--><h2 class="relative group"><a id="execution-modes" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#execution-modes"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Execution modes</span></h2><!--]--><!----> <table><thead><tr><th>Mode</th><th>How it runs</th><th>Use it for</th></tr></thead><tbody><tr><td><code>docker</code> (default)</td><td>Inside the task’s own image, files streamed over the Docker API</td><td>Everything — and the only backend that can enforce a task’s network, resource and user policies</td></tr><tr><td><code>local</code></td><td>Subprocesses under a per-episode directory tree</td><td>Self-contained tasks on Docker-less hosts such as Hugging Face Spaces</td></tr></tbody></table> <blockquote><p><strong><code>local</code> mode is not a security boundary.</strong> <code>exec</code> runs shell commands as
the server’s own user, so a task or a policy can read whatever that user can
and can reach the network. It is opt-in for that reason.</p> <p>The server’s environment is not passed through — only <code>PATH</code>, <code>HOME</code> and a
short allowlist — which keeps API keys out of the common case. Treat that as
hygiene, <strong>not</strong> containment: on Linux a child process can still recover the
parent’s environment through <code>/proc/&lt;ppid>/environ</code>. If a policy you do not
control can reach the socket, use <code>docker</code> mode.</p></blockquote> <p><code>local</code> mode refuses any task whose <code>task.toml</code> declares a policy it cannot
enforce — <code>network_mode</code>, <code>cpus</code>/<code>memory_mb</code>, or an <code>[agent].user</code> — rather than
running it unconstrained and reporting a score the task never sanctioned.</p> <p><code>docker</code> mode needs the <code>docker</code> Python package. It ships in this environment’s
own dependencies, so <code>uv run --project envs/harbor_env server</code> already has it;
add it explicitly when driving the environment from the repo root:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-bash "><!---->PYTHONPATH=src:envs uv run --with docker python envs/harbor_env/examples/validate_taskset.py --mode docker<!----></pre></div><!----> <p>A task is <strong>self-contained</strong> when it ships its starting files in <code>environment/</code> and declares no <code>environment/Dockerfile</code> or <code>docker-compose.yaml</code>. Those run in
either mode. Anything else — including every <code>repo2rlenv</code> task with an <code>environment/Dockerfile</code> — needs <code>docker</code>, and <code>local</code> mode says so explicitly
rather than grading an empty directory:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class=" "><!---->task <span class="hljs-string">&#x27;pallets__click-2951&#x27;</span> keeps its starting state <span class="hljs-keyword">in</span> <span class="hljs-keyword">a</span> container image
(environment/Dockerfile), which <span class="hljs-keyword">the</span> <span class="hljs-built_in">local</span> backend cannot reproduce.
Run <span class="hljs-keyword">the</span> server <span class="hljs-keyword">with</span> HARBOR_MODE=docker, <span class="hljs-keyword">or</span> use <span class="hljs-keyword">a</span> task that ships its <span class="hljs-built_in">files</span> <span class="hljs-keyword">in</span> environment/.<!----></pre></div><!----> <!--[1--><h2 class="relative group"><a id="task-policies" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#task-policies"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Task policies</span></h2><!--]--><!----> <p><code>task.toml</code> may constrain how a task runs. These are honoured in <code>docker</code> mode
and cause <code>local</code> mode to refuse the task:</p> <table><thead><tr><th>Declaration</th><th>Effect</th></tr></thead><tbody><tr><td><code>[environment].network_mode = "no-network"</code></td><td>The container gets no network</td></tr><tr><td><code>[environment].cpus</code> / <code>memory_mb</code> / <code>storage_mb</code></td><td>Real container limits</td></tr><tr><td><code>[environment].workdir</code></td><td>Overrides the image’s <code>WORKDIR</code></td></tr><tr><td><code>[agent].user</code> / <code>[verifier].user</code></td><td>That phase runs as the named account</td></tr><tr><td><code>network_mode = "allowlist"</code>, <code>gpus</code></td><td><strong>Refused</strong> — needs a filtering proxy / accelerators this backend does not provide. Grade with <code>harbor run</code>.</td></tr></tbody></table> <p>A task whose phases disagree (say a <code>public</code> agent and a <code>no-network</code> verifier)
gets the <strong>restrictive</strong> setting for the whole episode: a container has one
network, and resolving the conflict permissively would hand a sandboxed
verifier the internet.</p> <!--[1--><h2 class="relative group"><a id="the-task-format" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#the-task-format"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>The task format</span></h2><!--]--><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-text "><!---->&lt;task&gt;/
├── task.toml # config + metadata (required)
├── instruction.md # the prompt shown to the agent
├── environment/ # Dockerfile, compose file, or seed files
├── tests/
│ └── test.sh # the verifier (required to grade)
└── solution/
└── solve.sh # the reference solution (optional)<!----></pre></div><!----> <p>Both spellings of the schema field are read: Harbor writes <code>schema_version</code>,
Repo2RLEnv writes <code>version</code>. Harbor’s special paths are honoured exactly:</p> <table><thead><tr><th>Path</th><th>Contents</th><th>When</th></tr></thead><tbody><tr><td>working directory</td><td>what the agent edits — the image’s <code>WORKDIR</code></td><td>for the whole episode</td></tr><tr><td><code>/tests</code></td><td>the task’s <code>tests/</code></td><td>staged just before the verifier runs</td></tr><tr><td><code>/solution</code></td><td>the task’s <code>solution/</code></td><td>staged only for <code>solve</code></td></tr><tr><td><code>/logs/verifier</code></td><td><code>reward.json</code> / <code>reward.txt</code></td><td>written by the verifier</td></tr><tr><td><code>/logs/agent</code></td><td>scratch space for agent logs</td><td>for the whole episode</td></tr></tbody></table> <!--[1--><h2 class="relative group"><a id="rewards" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#rewards"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Rewards</span></h2><!--]--><!----> <p>The verifier writes its verdict into <code>/logs/verifier</code>; <code>reward.json</code> is read
first and <code>reward.txt</code> is the fallback, matching Harbor.</p> <table><thead><tr><th>Verifier wrote</th><th><code>result.reward</code></th><th><code>observation.info["reward_source"]</code></th></tr></thead><tbody><tr><td><code>reward.json</code> with a <code>reward</code> key</td><td>that value</td><td><code>reward.json</code></td></tr><tr><td><code>reward.json</code> with one metric</td><td>that value</td><td><code>reward.json</code></td></tr><tr><td><code>reward.json</code> with several metrics, no <code>reward</code> key</td><td>falls back to <code>reward.txt</code></td><td><code>reward.txt</code></td></tr><tr><td><code>reward.txt</code> only</td><td>that value</td><td><code>reward.txt</code></td></tr><tr><td>nothing</td><td><code>None</code>, <code>success=False</code></td><td><code>missing</code></td></tr></tbody></table> <p>Every numeric metric from <code>reward.json</code> is surfaced in <code>observation.info["reward_metrics"]</code>, and Repo2RLEnv’s nested <code>reward-details.json</code> sidecar (F2P/P2P counts, diff-similarity components) in <code>observation.info["reward_details"]</code>.</p> <p>A verifier that writes no reward file yields <strong>no reward at all</strong>, not a <code>0.0</code>.
A fabricated zero is indistinguishable from a genuine failure and would quietly
poison a training run.</p> <!--[1--><h2 class="relative group"><a id="action-space" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#action-space"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Action space</span></h2><!--]--><!----> <p><code>HarborAction.action_type</code> is one of:</p> <table><thead><tr><th>Action</th><th>Fields</th><th>Purpose</th></tr></thead><tbody><tr><td><code>exec</code></td><td><code>command</code>, <code>timeout_s</code></td><td>Run a shell command in the working directory</td></tr><tr><td><code>read</code></td><td><code>path</code></td><td>Read a file, relative to the working directory</td></tr><tr><td><code>write</code></td><td><code>path</code>, <code>content</code></td><td>Write a file, relative to the working directory</td></tr><tr><td><code>evaluate</code></td><td></td><td>Run <code>tests/test.sh</code> and end the episode</td></tr><tr><td><code>solve</code></td><td></td><td>Apply <code>solution/solve.sh</code> — Harbor’s oracle agent</td></tr></tbody></table> <p><code>exec</code>, <code>read</code> and <code>write</code> are the agent’s action space. <code>evaluate</code> and <code>solve</code> are training-orchestration controls: they decide when an episode ends and can
hand over the answer, so they belong on the infrastructure side of OpenEnv’s <a href="https://github.com/huggingface/OpenEnv/blob/main/rfcs/001-architecture.md" rel="nofollow">dual API boundary</a>.
Set <code>HARBOR_ALLOW_CONTROL_ACTIONS=0</code> to have the server refuse them outright,
for deployments where a policy can reach the same socket.</p> <p><code>evaluate</code> ends the episode. Every later action is refused and keeps reporting <code>done=True</code> — the episode never returns to a running state without <code>reset()</code>.</p> <p><code>read</code> and <code>write</code> are confined to the working directory, so an agent cannot
reach <code>/tests</code> or <code>/solution</code>. The verifier log directory is also cleared
immediately before the verifier runs, so a planted reward file cannot survive
into the score.</p> <!--[1--><h2 class="relative group"><a id="working-with-repo2rlenv" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#working-with-repo2rlenv"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Working with Repo2RLEnv</span></h2><!--]--><!----> <p><a href="https://github.com/huggingface/Repo2RLEnv" rel="nofollow">Repo2RLEnv</a> turns a GitHub
repository into verifiable Harbor tasks. The output needs no conversion:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-bash "><!----><span class="hljs-comment"># 1. Synthesize tasks from a repository</span>
repo2rlenv generate --repo pallets/click --pipeline pr_runtime \
--pipeline-opt <span class="hljs-built_in">limit</span>=10 --llm anthropic/claude-sonnet-4-6 --out ./tasks
<span class="hljs-comment"># 2. Check every task is solvable by its own oracle before training on it</span>
PYTHONPATH=src:envs uv run --with docker python envs/harbor_env/examples/validate_taskset.py \
--tasks ./tasks --mode docker
<span class="hljs-comment"># 3. Serve them</span>
HARBOR_TASKS_DIR=./tasks HARBOR_MODE=docker uv run --project envs/harbor_env server<!----></pre></div><!----> <p>Tasks published with <code>repo2rlenv push</code> live under <code>tasks/&lt;id>/</code> in a Hugging Face
dataset; that layout is discovered automatically, so <code>HARBOR_TASKS_DIR=hf://datasets/&lt;org>/&lt;name></code> is enough.</p> <p>Rewards line up with what the pipeline produced: <code>test_execution</code> (<code>f2p_rate × p2p_rate</code>) for the <code>_runtime</code> pipelines and <code>diff_similarity</code> for <code>pr_diff</code>, forwarded exactly as the verifier computed them.</p> <!--[1--><h2 class="relative group"><a id="writing-a-task-that-runs-in-both-places" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#writing-a-task-that-runs-in-both-places"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Writing a task that runs in both places</span></h2><!--]--><!----> <p>Harbor’s absolute paths only exist inside a container. A verifier that prefers
the <code>HARBOR_*</code> variables and falls back to those paths runs unchanged under <code>harbor run</code>, under <code>docker</code> mode, and under <code>local</code> mode:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-bash "><!----><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-built_in">set</span> -uo pipefail
LOGS_DIR=<span class="hljs-string">&quot;<span class="hljs-variable">${HARBOR_LOGS_DIR:-/logs/verifier}</span>&quot;</span>
TESTS_DIR=<span class="hljs-string">&quot;<span class="hljs-variable">${HARBOR_TESTS_DIR:-/tests}</span>&quot;</span>
WORKDIR=<span class="hljs-string">&quot;<span class="hljs-variable">${HARBOR_WORKDIR:-$(pwd)}</span>&quot;</span>
<span class="hljs-built_in">mkdir</span> -p <span class="hljs-string">&quot;<span class="hljs-variable">$LOGS_DIR</span>&quot;</span>
<span class="hljs-built_in">cd</span> <span class="hljs-string">&quot;<span class="hljs-variable">$WORKDIR</span>&quot;</span>
<span class="hljs-comment"># ...grade, then write the reward...</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">&#x27;{&quot;reward&quot;: 1.0}&#x27;</span> &gt; <span class="hljs-string">&quot;<span class="hljs-variable">$LOGS_DIR</span>/reward.json&quot;</span>
<span class="hljs-built_in">exit</span> 0 <span class="hljs-comment"># the reward file is the verdict, not the exit code</span><!----></pre></div><!----> <p>The bundled <code>examples/tasks/fix-sum-bug</code> task does exactly this, and grades
identically across all three runtimes (verified against <code>harbor</code> 0.20.0):</p> <table><thead><tr><th>Runtime</th><th>Untouched task</th><th>After <code>solution/solve.sh</code></th></tr></thead><tbody><tr><td><code>harbor run -a nop</code> / <code>-a oracle</code></td><td>0.600</td><td>1.000</td></tr><tr><td><code>harbor_env</code> in <code>local</code> mode</td><td>0.600</td><td>1.000</td></tr><tr><td><code>harbor_env</code> in <code>docker</code> mode</td><td>0.600</td><td>1.000</td></tr></tbody></table> <p>Reproduce the first row with <code>harbor run -p envs/harbor_env/examples/tasks/fix-sum-bug -a nop</code> and the other two with <code>examples/validate_taskset.py</code>.</p> <p>A verifier that hardcodes <code>/logs/verifier</code> still works in <code>docker</code> mode; in <code>local</code> mode the episode reports that it could not be scored and names the fix.</p> <!--[1--><h2 class="relative group"><a id="configuration" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#configuration"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Configuration</span></h2><!--]--><!----> <table><thead><tr><th>Variable</th><th>Default</th><th>Meaning</th></tr></thead><tbody><tr><td><code>HARBOR_TASKS_DIR</code></td><td>bundled examples</td><td>Task directory, or <code>hf://datasets/&lt;org>/&lt;name>[@rev]</code></td></tr><tr><td><code>HARBOR_MODE</code></td><td><code>docker</code></td><td><code>docker</code> or <code>local</code></td></tr><tr><td><code>HARBOR_ALLOW_CONTROL_ACTIONS</code></td><td><code>1</code></td><td>Accept <code>evaluate</code>/<code>solve</code>; set <code>0</code> for agent-facing deployments</td></tr><tr><td><code>HARBOR_DEFAULT_TASK_ID</code></td><td></td><td>Task used when <code>reset()</code> names none</td></tr><tr><td><code>HARBOR_COMMAND_TIMEOUT_S</code></td><td><code>120</code></td><td>Timeout for agent <code>exec</code> actions</td></tr><tr><td><code>HARBOR_DEFAULT_IMAGE</code></td><td><code>python:3.12-slim</code></td><td>Image for self-contained tasks in <code>docker</code> mode</td></tr><tr><td><code>MAX_CONCURRENT_ENVS</code></td><td><code>8</code></td><td>Concurrent WebSocket sessions</td></tr></tbody></table> <p>Verifier and oracle timeouts come from <code>[verifier].timeout_sec</code> and <code>[agent].timeout_sec</code> in each task’s <code>task.toml</code>.</p> <!--[1--><h2 class="relative group"><a id="running-in-docker" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#running-in-docker"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Running in Docker</span></h2><!--]--><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-bash "><!---->docker build -t harbor-env:latest -f envs/harbor_env/server/Dockerfile envs/harbor_env
<span class="hljs-comment"># local mode, your own tasks</span>
docker run --<span class="hljs-built_in">rm</span> -p 8000:8000 -v <span class="hljs-string">&quot;<span class="hljs-variable">$PWD</span>/tasks:/tasks:ro&quot;</span> -e HARBOR_TASKS_DIR=/tasks harbor-env:latest
<span class="hljs-comment"># docker mode needs the host daemon, so tasks can start their own containers</span>
docker run --<span class="hljs-built_in">rm</span> -p 8000:8000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v <span class="hljs-string">&quot;<span class="hljs-variable">$PWD</span>/tasks:/tasks:ro&quot;</span> \
-e HARBOR_TASKS_DIR=/tasks -e HARBOR_MODE=docker \
harbor-env:latest<!----></pre></div><!----> <p>Hugging Face Spaces cannot run Docker-in-Docker, so a Space serves <code>local</code> mode
and therefore self-contained tasks that declare no restrictive policies.</p> <!--[1--><h2 class="relative group"><a id="examples" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#examples"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Examples</span></h2><!--]--><!----> <table><thead><tr><th>Script</th><th>What it shows</th></tr></thead><tbody><tr><td><a href="https://github.com/huggingface/OpenEnv/blob/main/envs/harbor_env/examples/quickstart.py" rel="nofollow"><code>examples/quickstart.py</code></a></td><td>A full episode against a running server</td></tr><tr><td><a href="https://github.com/huggingface/OpenEnv/blob/main/envs/harbor_env/examples/validate_taskset.py" rel="nofollow"><code>examples/validate_taskset.py</code></a></td><td>Oracle sweep over a task set — run this before training</td></tr><tr><td><a href="https://github.com/huggingface/OpenEnv/tree/main/envs/harbor_env/examples/tasks/fix-sum-bug" rel="nofollow"><code>examples/tasks/fix-sum-bug/</code></a></td><td>A Harbor task written to run under every runtime</td></tr></tbody></table> <!--[1--><h2 class="relative group"><a id="layout" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#layout"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Layout</span></h2><!--]--><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-text "><!---->envs/harbor_env/
├── models.py # HarborAction / HarborObservation / HarborState
├── client.py # HarborEnv
├── examples/
└── server/
├── task.py # task.toml parsing + task discovery
├── sandbox.py # Harbor&#x27;s sandbox contract; local + docker backends
├── reward.py # the reward-file contract
├── harbor_env_environment.py # Gymnasium orchestration over the three above
└── app.py # FastAPI server<!----></pre></div><!----> <!--[1--><h2 class="relative group"><a id="tests" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#tests"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Tests</span></h2><!--]--><!----> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-bash "><!---->PYTHONPATH=src:envs uv run pytest tests/envs/test_harbor_env.py -v<!----></pre></div><!----> <p>They are hermetic — no Docker, no network — and use the bundled example task as
the end-to-end fixture.</p> <a class="!text-gray-400 !no-underline text-sm flex items-center not-prose mt-4" href="https://github.com/huggingface/openenv/blob/main/docs/source/environments/harbor.md" target="_blank"><svg class="mr-1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M31,16l-7,7l-1.41-1.41L28.17,16l-5.58-5.59L24,9l7,7z"></path><path d="M1,16l7-7l1.41,1.41L3.83,16l5.58,5.59L8,23l-7-7z"></path><path d="M12.419,25.484L17.639,6.552l1.932,0.518L14.351,26.002z"></path></svg><!----> <span><span class="underline">Update</span> on GitHub</span></a><!----> <p></p><!--]--><!----><!--]--><!--]--><!--]--> <!--[-1--><!--]--><!--]-->
<script>
{
__sveltekit_1ved3fe = {
base: "/docs/openenv/pr_1018/en",
assets: "/docs/openenv/pr_1018/en"
};
const element = document.currentScript.parentElement;
Promise.all([
import("/docs/openenv/pr_1018/en/_app/immutable/entry/start.B9IBUExw.js"),
import("/docs/openenv/pr_1018/en/_app/immutable/entry/app.CiZ4jjXn.js")
]).then(([kit, app]) => {
kit.start(app, element, {
node_ids: [0, 3],
data: [null,null],
form: null,
error: null
});
});
}
</script>

Xet Storage Details

Size:
56.2 kB
·
Xet hash:
3a3bbe13b705d3309673a8800d459d8b63f7369e593673193fc8591c935650a2

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.