A Harbor environment adapter backed by the Ascii Box public API.
BoxEnvironment runs Harbor agent trials and evals inside an Ascii Box instead
of a local Docker container, E2B, or Modal. It implements Harbor's
BaseEnvironment surface — lifecycle, command execution, environment variables,
and file/dir upload + download — on top of Box's public HTTP API.
Some Harbor features aren't available on Box today: network policies, Docker image builds / Compose, and GPUs / TPUs / Windows.
| Path | What |
|---|---|
sdks/harbor_box_environment.py |
BoxEnvironment — the Harbor adapter plus a small async Box API client |
sdks/harbor-box-evals/ |
End-to-end evals: a from-scratch Claude Agent SDK coding agent solving tasks inside a Box |
pip install harbor-box # imports as: harbor_box_environmentOr from a clone of this repo:
pip install -r requirements.txt # harbor>=0.14.0, httpx, tenacitycp .env.example .env
# fill in BOX_API_KEYBOX_API_KEY is required — get one at https://box.ascii.dev. Your .env is
gitignored; never commit secrets.
export BOX_API_KEY=...
harbor task run path/to/task.yaml \
--environment-import-path harbor_box_environment:BoxEnvironmentBox runs a ready Ubuntu image — it doesn't build Docker images. The adapter prepares each box from your Harbor environment directory instead:
- Files in the environment directory are uploaded into the box's working directory at start, so fixtures, configs, and scripts are in place before the agent runs.
- The
Dockerfileis read only for itsWORKDIR; build steps (RUN/COPY/ …) are not executed. Install dependencies from a setup command (await env.exec(...)) or your agent, not the image. - Environment variables come from the Harbor environment config and are
forwarded into the box; per-command env is passed through
exec.
task_env_config = EnvironmentConfig(
workdir="/workspace",
env={"DATABASE_URL": "postgres://..."},
)Have a Dockerfile? Reproduce its RUN / COPY / WORKDIR steps on Box as a
runtime setup (outbound network works, so apt/pip/npm installs run). A complete,
runnable example is in
examples/dockerfile_to_box.py.
Harbor stops the box as soon as a trial (one eval run) finishes — including when
it errors — so a box only costs you while a trial is actually running. By default
stop() removes the box (delete=True, matching Harbor); pass delete=False to
keep a resumable snapshot instead. Either way compute billing stops. The
ttl_seconds you set is just a safety backstop for an abandoned box.
Boxes are no-env by default: a trial gets none of your Box account's secrets,
credentials, or cloned repos and can't act on your account or other boxes. Pass
no_env=False to use your account's environment instead, configured in the
Box dashboard. See
Secrets & Setup.
A self-contained end-to-end self-test exercises start → persistent/per-command env vars → binary upload/download → nested directory upload/download → stop:
export BOX_API_KEY=...
python sdks/harbor_box_environment.py
# -> Box Harbor adapter e2e self-test PASSEDCI runs this self-test on every push.
A from-scratch Claude Agent SDK
coding agent solving tasks inside a Box, scored by inspecting the result. See
sdks/harbor-box-evals/README.md.
Maintainers publish harbor-box to PyPI from a local checkout — see
docs/release.md. CI never publishes.
MIT.