W&B Sandboxes Provider
Read when:
- choosing
provider: wandb(aliasweights-and-biases); - pointing Crabbox at a Weights & Biases Sandbox;
- changing
internal/providers/wandb.
W&B Sandboxes are managed, isolated Linux containers backed by CoreWeave Sandboxes. The provider talks to the CoreWeave gateway over gRPC (coreweave.sandbox.v1beta2) using the W&B API key as the x-wandb-api-key metadata header, so a caller who has already run wandb login does not need a new provider-specific credential.
This is a delegated-run provider: Crabbox does not provision an SSH box and does not go through the broker coordinator. The CLI starts a sandbox, runs a single command in it via the unary Exec RPC, and stops it again. There is no workspace sync, so crabbox run requires --no-sync.
> Experimental. The upstream API is coreweave.sandbox.v1beta2 and W&B > Sandboxes are in preview. Expect field renames and breaking changes until > upstream cuts a stable v1; the protos are pinned via buf.lock in > internal/providers/wandb/proto/.
#When to use
Use W&B Sandboxes when you already have W&B credentials and want a managed Linux sandbox without provisioning your own runner or creating a new account. Pick a provider with SSH (AWS, Hetzner, Static SSH, Daytona) instead when you need direct shell access or a persistent dev box — this provider is exec-only by design.
W&B Sandboxes are Linux-only. Desktop, browser, code, SSH, Actions hydration, and the broker coordinator are not available.
#Commands
crabbox run --provider wandb --no-sync -- python eval.py
crabbox run --provider wandb --no-sync --id swift-crab -- pnpm test
crabbox run --provider wandb --no-sync --keep --lease-output session.json -- true
crabbox status --provider wandb --id swift-crab
crabbox stop --provider wandb swift-crab
crabbox list --provider wandb
crabbox doctor --provider wandb
Without --id, run acquires a new sandbox, runs the command, and stops the sandbox afterwards. With --id <sandbox-id> it execs into the existing sandbox and leaves it running. warmup is rejected — sandboxes are acquired per run, with no separate provisioning phase.
--lease-output <path> writes a reusable session handle containing the stable sandbox ID and an exact cleanup command. Pair it with --keep when another process should reuse the newly acquired sandbox.
#Auth
Resolve the W&B API key in this precedence (first match wins):
CRABBOX_WANDB_API_KEY— explicit override, CI-friendly.wandb.apiKey— config-file value.WANDB_API_KEY— canonical env var written bywandb login.~/.netrc— themachine api.wandb.ai(or.com) entry written bywandb login.
WANDB_ENTITY_NAME is also required; it is sent as the x-entity-id gRPC header. WANDB_PROJECT is optional and, when set, is sent as x-project-name.
export CRABBOX_WANDB_API_KEY=wandb_v1_...
export WANDB_ENTITY_NAME=my-team
The API key is never exposed as a CLI flag; do not pass secrets on the command line.
#Config
provider: wandb
target: linux
wandb:
defaultImage: ubuntu:24.04
maxLifetimeSeconds: 1800 # 30 min; W&B reclaims the sandbox at this limit
Runtime defaults applied when unset: defaultImage is ubuntu:24.04 and maxLifetimeSeconds is 1800. The raw configuration remains empty/zero until the provider applies these defaults; flag registration does not eagerly fill them.
Provider flags (each overrides the matching wandb.* config key):
--wandb-image # container image used when acquiring a new sandbox
--wandb-max-lifetime # maximum sandbox lifetime in seconds
Environment overrides:
defaultImagealso readsCRABBOX_WANDB_DEFAULT_IMAGE, thenWANDB_DEFAULT_IMAGE.maxLifetimeSecondsalso readsCRABBOX_WANDB_MAX_LIFETIME_SECONDS, thenWANDB_MAX_LIFETIME_SECONDS.CWSANDBOX_BASE_URLoverrides the gateway endpoint (defaultapi.cwsandbox.com:443); thehttps:///http://scheme is stripped if present.
The three configuration settings use shared typed bindings. Empty file/environment strings preserve prior values. File maxLifetimeSeconds assigns only when positive; zero or negative file values leave the prior setting intact. Environment parsing instead accepts signed integers: a parsed primary value, including zero or a negative value, wins. An empty or malformed primary falls back to the vendor alias, then to the prior setting. Runtime defaulting and the lease TTL still determine the effective lifetime. The client-owned API-key precedence above is unchanged.
#Lifecycle
crabbox run:
- With
--id <sandbox-id>, require the exact local claim created when Crabbox acquired the sandbox, verify that the claim still matches the W&B endpoint, entity, project, and sandbox ID, then require the provider-sidecrabboxinventory tag beforeExec. - Otherwise,
Starta sandbox with an idle keep-alive command, poll until it reachesRUNNING(200 ms backoff, ×1.5, capped at 2 s), persist the exact ownership claim,Execthe command, thenStopit unless--keepis set. If claim persistence fails, Crabbox rolls back the acquired sandbox before returning.
Run outcomes and timing are finalized after automatic Stop. A Stop failure makes an otherwise successful run fail with exit 1 and retains its recovery session and unchanged claim. Command failures and mapped gRPC exit codes stay primary when Stop or timing output also fails; secondary diagnostics remain visible. gRPC/API failures are classified as provider-error, not as observed command exits, while keeping their mapped numeric exit codes. --keep-on-failure is decided before timing output, so a reporting failure cannot discard an already-failed run's sandbox. A timing-output failure after successful Stop does not claim the sandbox is retained. Closing the local gRPC connection remains warning-only. Command timing measures Exec separately; total timing includes acquisition and automatic cleanup.
status and stop enforce the same exact claim and tagged-inventory checks before issuing Get or Stop. A tagged sandbox without the matching local claim, or a claim from another endpoint, entity, or project, fails closed. Successful automatic or explicit stop removes the unchanged claim; failed cleanup keeps it so a later retry can still route to the owned resource. If tagged inventory no longer contains a claimed sandbox, Crabbox probes that exact ID: a confirmed provider NotFound lets stop remove only the unchanged stale claim. An untagged but existing sandbox or any lookup error preserves the claim and fails closed. status renders the sandbox state (for example running; a COMPLETED sandbox is reported as stopped so status --wait treats it as terminal). list paginates sandboxes tagged crabbox. stop issues a graceful stop (15 s timeout). Acquire and exec apply a startup timeout that is the lesser of five minutes and the sandbox lifetime.
#Capabilities
- SSH: no — gRPC
Execonly. - Crabbox sync: no —
--no-syncis required. - Desktop / browser / code: no.
- Actions hydration: no.
- Coordinator (broker): no — always direct from the CLI.
#Gotchas
maxLifetimeSecondsis the main billing-safety limit. Crabbox defaults to 30 minutes; raise it with--wandb-max-lifetimeonly when needed. A lease TTL shorter than the configured lifetime narrows it further.Execis the unary RPC, so command output is buffered server-side and returned at completion rather than streamed; there is no interactive PTY.- Environment variables are applied at
Starttime only. When you target an existing sandbox with--id, selected user env vars cannot be forwarded onto it (theExecRPC has no env field), so explicit--allow-envselections containing such values are rejected, includingCIandNODE_OPTIONS. Crabbox's local run metadata (CRABBOX_LEASE_ID,CRABBOX_RUN_ID, andCRABBOX_SLUG) may be omitted for reuse, including when an env summary is requested. The built-in implicitCI/NODE_OPTIONSdefaults retain their existing omission exception. Neither exception forwards values throughExecor refreshes the sandbox's originalStart-time environment; similarly named custom variables are not treated as reserved metadata. --reclaim,--shell,--sync-only,--checksum,--force-sync-large,--full-resync,--download,--artifact-glob, and--require-artifactare rejected: W&B owns the sandbox lifecycle and there is no Crabbox SSH/rsync target.--reclaimremains unsupported because the pinned W&B API has no safe way to adopt a tagged external sandbox into a conflict-safe exact local claim.--keepretains a newly acquired sandbox after the run;--keep-on-failureretains it only when the command fails, so you can debug. Both paths retain the exact local claim needed by laterrun --id,status, andstopcalls.- gRPC failures map to sysexits-aligned exit codes:
77(unauthenticated / permission denied),4(not found),124(deadline exceeded),69(unavailable / resource exhausted).
#Live smoke
Run a live smoke when changing W&B lifecycle, exec, status, or auth code. Keep the API key in the environment; never pass it as an argument.
export CRABBOX_WANDB_API_KEY=wandb_v1_...
export WANDB_ENTITY_NAME=my-team
go build -trimpath -o bin/crabbox ./cmd/crabbox
CRABBOX_LIVE=1 \
CRABBOX_LIVE_PROVIDERS=wandb \
CRABBOX_LIVE_COORDINATOR=0 \
CRABBOX_LIVE_REPO=/path/to/my-app \
scripts/live-smoke.sh
The shared harness exits before any W&B provider command when no API key is exported. With the API key and entity configured, it runs doctor, creates a kept sandbox with a 60-second lifetime, proves status and reuse through the exact claim, proves that the provider tag alone cannot authorize stop, then stops the sandbox and confirms no active remote inventory or local claim residue.
For manual debugging, run the same lifecycle directly:
export CRABBOX_WANDB_API_KEY=wandb_v1_...
export WANDB_ENTITY_NAME=my-team
go build -trimpath -o bin/crabbox ./cmd/crabbox
bin/crabbox doctor --provider wandb
bin/crabbox run --provider wandb --no-sync --wandb-max-lifetime 60 -- echo crabbox-wandb-ok
Or the Go smoke test (acquire, exec, stop):
go test -tags smoke -run TestSmokeVersionAndExec -v ./internal/providers/wandb/
#Regenerating the proto stubs
cd internal/providers/wandb/proto
buf dep update # refresh buf.lock
buf generate # regenerate ../gen/
Bump the BSR commit pin in buf.lock only via a dedicated, auditable PR.
Related docs: