Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Your first agent

The shortest path from an empty board to one real sandboxed run that opens a pull request.

This spends real money and opens pull requests. Do this once on a repo you do not mind receiving a small PR against.

Start in the product

On an empty board, Welcome to sandboard embeds the same operator guide as Help (nav → Help). That guide is the named first-run path:

  1. Connect MCP
  2. OpenShell + sandbox — Connectivity, Providers, Policies, Sandbox specs
  3. First Project loop

Work the checklist there; deep links land on Settings → OpenShell and Agent runtime. This page is the prose companion: the same order, with checks and the host-side pieces the UI does not run for you. An operator agent should start from the public /llms.txt guide (same order, API-shaped checks).

Every step has a check. Do not move on until the check passes — see why below: in this stack a half-finished step does not error, it hangs.

What you are assembling

Four things have to be true on the host. The tools named are examples, not the only stack.

#RoleConcretely
1Something that runs containerspodman, Colima, or Docker
2The OpenShell gatewayholds sandboxes, network policy, credentials
3Model + GitHub credentialsas OpenShell providers, never baked into an image
4A sandbox imagewith whatever toolchain the work needs

sandboard itself holds none of those credentials. It talks to the gateway over gRPC and the gateway injects secrets on egress, so nothing sensitive enters the sandbox.

1. A compute driver

OpenShell’s gateway needs a working Docker-compatible API. How you provide it is your choice:

DriverTypical setup
podmanpodman machine start
Colimacolima start, then point the gateway at unix://$HOME/.colima/default/docker.sock
Docker Desktop / engineMake sure the daemon is up and the gateway can reach its socket

DOCKER_HOST and friends belong to the gateway process, not to sandboard Settings.

Check:

docker info        # must succeed

The driver can stop on its own — the podman machine especially. sandboard classifies that as infrastructure rather than the card failing, so it will not burn a card’s retry budget, but it cannot prevent the outage.

2. The OpenShell gateway

Start it however your install expects (Homebrew service, systemd, …). sandboard does not spawn an openshell CLI for board traffic: src/openshell.rs talks to the gateway in-process over gRPC with client certificates.

Check:

openshell status   # expect Connected + Authenticated

Then tell sandboard how to reach it, in Settings → OpenShell → Connectivity (Welcome/Help deep-links here):

  • Gateway endpoint — often https://127.0.0.1:17670 (not sandboard’s 8080; your install may differ).
  • mTLS PEMs — CA, client cert, client key. Paste them in. They are stored encrypted in the board database (~/.config/sandboard/master.key). The API does not return private keys. sandboard does not read them from disk — upload them in Settings.

Settings (stored on the board) is the live source of truth for gateway endpoint and sealed PEMs — same split as Configuration.

Check: hit Refresh status in Settings. You want Healthy.

3. Providers

Settings → OpenShell → Providers is the credential list on the board. Sync applies it to the gateway. Which providers attach on create is chosen per Sandbox spec.

For claude sandboxes, point OpenShell’s local router at your model. OpenCode can use the same route when its model is unset, or a direct provider such as OpenRouter when its Sandbox spec has a provider/model value. Hermes uses its own endpoint-bearing OpenShell provider so it can use OpenRouter without changing the shared inference route:

openshell provider create --name vertex --type google-vertex-ai --from-gcloud-adc \
  --config VERTEX_AI_PROJECT_ID=<project> --config VERTEX_AI_REGION=global
openshell inference set --provider vertex --model claude-sonnet-4-6@default

Those agents then reach models at https://inference.local and the gateway swaps in the real credential on the way out. For Hermes, create an openrouter provider with OPENROUTER_API_KEY and attach it to the sandbox-hermes profile. Details: Sandbox.

For agy, cursor, opencode, and hermes, model selection is on the Sandbox spec (or per card at claim); sandboard passes the resolved value as agy --model …, agent --model …, opencode --model provider/model, or hermes --model …. See Configuration and Sandbox.

For GitHub, add or edit the shipped github-app provider under Settings → OpenShell → Providers (type profile under Provider types, same catalog as cursor-agent / antigravity). Set App ID, private key, and installation; Save/Sync mints GH_TOKEN onto the gateway — attach that provider on your Sandbox spec.

Check: Sync reports success and the providers you expect are listed on the gateway.

4. Policies and a sandbox image

OpenShell allow-lists are named Policies on the board (Settings → OpenShell → Policies). A Sandbox spec picks one by id — image, resources, engine, and providers live on the spec; YAML lives on the Policy. Configuration covers the split; a running sandbox keeps the policy it was created with.

A fresh board already has five seeded specs — sandbox-cursor, sandbox-agy, sandbox-claude, sandbox-opencode, sandbox-hermes — each pointed at quay.io/sandboard-app/sandbox-<engine>:latest and a matching minimal Cockpit policy. None of them is the default yet — pick one (Welcome flags this until you do). Build and push those images yourself (or point the seeded specs at wherever you host them):

make sandbox        # builds all five quay.io/sandboard-app/sandbox-<engine>:latest
make sandbox-push   # builds, then pushes all five
# Docker: CONTAINER_ENGINE=docker make sandbox
# Different registry: REGISTRY=ghcr.io/you make sandbox

From the repo root, not sandbox/ — the Containerfile is multi-stage and podman build -f sandbox/Containerfile resolves relative to wherever you run it. Each image bakes a Rust toolchain but no sandboard source or dependency cache; a card’s own cargo build/npm ci fetch crates.io/npm live, so the seeded Cockpit policies allow that egress (src/seed_policies.rs).

Then set the board’s default sandbox spec in Settings → OpenShell → Sandbox specs (Welcome/Help deep-links here) — either one of the five seeded rows or one you made. Nothing is default until you choose; the Welcome “Sandbox spec” readiness check stays red until then. Optionally set Model on the spec when using agy, cursor, opencode, or hermes (or override per card at claim); claude model routing stays on the gateway via openshell inference set as above. Specs live on the board; Configuration and Sandbox cover resolution.

Check: podman image ls | grep sandbox-, and Welcome’s “Sandbox spec” readiness check turns green.

5. Agent runtime (optional tune)

Tune concurrency / timeouts / sweep under Settings → Agent runtime if you want (Configuration).

Check: OpenShell readiness on Welcome shows Gateway/mTLS and Sandbox spec ready.

6. Run one card

This is the First Project loop section of Welcome/Help:

  1. Create a Project pointed at your repo (clone_repo as owner/name).
  2. Start its Initial plan card.
  3. Watch it move Backlog → Running. The card shows its sandbox name.
  4. It lands in Review with a proposed breakdown. Read it, edit it, Approve.
  5. Start one of the resulting Tasks.
  6. It opens a pull request and lands in Review.
  7. Merge on GitHub. The card moves to Done.

Keep max_concurrent at 1 until you have watched this work end to end.

If something takes longer than it should, it has already failed — Troubleshooting is the next page you want. Denied egress, missing credentials, and wedged relays present as silence; treat hangs as failure, not as “give it more time.”

Next

  • Workflow — steering cards day to day
  • Configuration — Policies, sandbox specs, engines, timeouts
  • Sandbox — what actually happens inside a run
  • Cockpit — a durable terminal with operator reach