Skip to content
View as .md

Environments

A named execution context binding one sandbox + one repo policy + a set of secret-name bindings into something a thread can reference, durable and inspectable within a house. threads.environment_id carries an FK with on delete set null, and the thread row keeps a snapshot of the environment — so later env edits or teardown don’t rewrite a thread’s history.

environments {
id, house_id (FK cascade), author_id, name, sandbox_id (required at row level),
default_repo, allowed_repos[], github_installation_id,
secret_bindings: jsonb [{name, required}] # resolved against house secrets at dispatch
}

POST /api/environments with sandbox_id omitted auto-provisions a box on the env’s runtime. Daytona (the default) creates a fresh house-scoped sandbox via DAYTONA_API_KEY — no pi install (a daytona box ships a shell; delegate_task spins its own per-run box). runtime: 'sprite' instead provisions a sprite (name <env-name>-<short-id>, requires the house’s SPRITES_TOKEN) and runs setupLifecycle to install pi before writing the row. Bindings store names, not values — see secrets for resolution. Sandbox pi defaults to defaultModelRef (llm-keys) — bind OPENROUTER_API_KEY. Provider-specific keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, …) still work paired with a matching thread.config.model override.

EndpointAuthNotes
GET /api/environments?house_id=<uuid>house memberlist
GET /api/environments/<id>house memberfetch one
POST /api/environmentsmember-writeauto-provisions on the runtime (daytona default) when sandbox_id omitted
PATCH /api/environments/<id>member-writepartial update
DELETE /api/environments/<id>owner-onlysoft delete

GitHub App integration: when github_installation_id is set, dispatch mints a short-lived installation access token scoped to allowed_repos and injects it as GITHUB_TOKEN. Two browser-only endpoints (/api/github/installations, /api/github/installations/:id/repos) require a GitHub OAuth provider session — not callable with an arbe API key. Server needs GITHUB_APP_ID (numeric) + GITHUB_APP_PRIVATE_KEY (PEM RSA) as wrangler secrets; absent → 501 on listing endpoints, dispatch silently skips token minting (the environment still works, just without GITHUB_TOKEN).

CLI (all commands operate on the active house, set via arbe house select):

Terminal window
arbe env list [--json]
arbe env view <name-or-id> # name (case-insensitive) or UUID
arbe env create <name> --sandbox <id> --secret OPENROUTER_API_KEY [--optional-secret NICE_KEY]
arbe env bind-secret <name|id> <SECRET_NAME> [--optional] # idempotent — same --optional is no-op,
arbe env unbind-secret <name|id> <SECRET_NAME> # different value upgrades/downgrades
arbe env delete <name|id>

--secret (required) and --optional-secret (warn-only at dispatch) are repeatable on create. Dispatch with --env: arbe --env work thread entries create <ref> "fix the bug"--env is a root-level option that resolves the environment by name or ID and uses its sandbox_id, overriding any -s flag. Sandboxes are created once and reused across dispatches.

Code: packages/core/schemas/environment.ts (EnvironmentRowSchema), packages/core/environments.ts, apps/www/src/routes/api/environments/.
See daytona runtime, system/sandbox-sprite, system/secrets, system/dispatch, runtime.