HEMRA

Sandboxes

A sandbox is where a harness runs. A run file sets it in [sandbox], and --sandbox overrides it. The default is Docker.

kindWhereNotes
dockerA container on this machineThe default. No network, no capabilities, your own uid, bounded memory, CPU and processes
localA process on this hostRecorded as such. Nothing is isolated beyond the cleared environment
modalA Modal Sandbox[sandbox] image from a registry, pinned by digest
flyA Fly.io MachineAlways has a network, so it needs network = "open"
spritesA Fly SpriteFly's own base image (no image); the network can be closed except for egress domains

hemra doctor lists every sandbox, whether it is available, and the capabilities it enforces as configured.

Docker

Program harnesses need an image:

[sandbox]
image = "alpine:3.20"
mounts = [".:/harness"]      # read-only unless :rw; relative to the run file
# network = "bridge"         # to let the harness reach a model API
# memory = "4g"
# cpus = 2
# pids = 512
# read_only = true

A driver harness (cli) on a Harbor task runs in the task's own image instead, built from its environment/Dockerfile, with the driver and the agent mounted read-only. After the attempt, the task's verifier runs in a separate container on a snapshot of the agent's container, with no network, and its reward becomes the trial's score. The image is pinned to its ID in every attempt's manifest, every container is labelled as HEMRA's, and each is removed before artifacts are read.

hemra doctor --prune removes containers that a killed hemra left behind.

Managed sandboxes

Modal, Fly.io Machines and Fly Sprites are reached through a small bridge program, built from the repository with Node.js (npm ci && npm run build) and found with --sandbox-bin, its HEMRA_SANDBOX_<KIND>_BIN variable, or hemra-sandbox-<kind> on PATH. HEMRA itself never links a vendor SDK.

SandboxCredentialsRun file example
ModalMODAL_TOKEN_ID and MODAL_TOKEN_SECRET, or modal token newmodal-run.toml
Fly.io MachinesFLY_API_TOKEN, a Fly app (app = "..."), and flyctl on PATHfly-run.toml
Fly SpritesSPRITES_TOKENsprites-run.toml
hemra run examples/harness-sh/modal-run.toml --harness-dir examples/harness-sh \
  --sandbox-bin packages/sandboxes/modal/dist/main.js

mounts copies each host directory into the sandbox before the harness starts. A problem with the provider, a lost stream or an artifact copy that failed is an infrastructure failure, never a failed task.

Requiring protections

--require (or require = [...] in a run file) refuses the run, before anything is recorded, unless the sandbox as configured offers every capability named:

hemra run run.toml --require network_block,resource_limit

The ones sandboxes offer today are network_block, egress_allowlist, resource_limit, filesystem_mount, custom_image, linux_container, linux_vm, stream_stdio, stream_logs and graceful_cancel; hemra doctor shows which. A sandbox that cannot enforce a setting refuses it rather than ignoring it: a Fly Machine refuses network = "none", and only Sprites take egress.

Verifiers

Task verifiers get no network and no host variables, unless the run allows them. A verifier that calls a model needs both:

[verifier]
network = "bridge"
env = ["OPENAI_API_KEY"]     # names the task's [verifier.env] may read

or --verifier-network bridge --verifier-env OPENAI_API_KEY. Names are recorded with the run; values never are.

Edit this page on GitHub