Storage, health, and revisions#
Three features make a sandbox something you can run for weeks rather than minutes: a disk that survives restarts, a probe that tells you whether the agent is actually working, and a revision history you can roll back.
Persistent volumes#
A sandbox's container filesystem is discarded when it stops. A persistent volume is not.
volumes:
- mountPath: /data
Or with a flag:
Create a sandbox in production from ghcr.io/acme/agent:1.2 running
"./start.sh" with 500m CPU and 2Gi memory, and give it a persistent
volume mounted at /data.
nexusctl sandbox create --project production \
--image ghcr.io/acme/agent:1.2 \
--command "./start.sh" \
--cpu 500m --memory 2Gi \
--volume /data
The path must be absolute. A sandbox supports one volume today.
What the volume gets you:
- Survives stop and start. Stop a sandbox to release compute, start it later, and the agent resumes on the same disk.
- Survives image upgrades. A new revision reuses the volume, so an agent's memory, checkpoints, and working files outlive the version that wrote them.
- Deleted with the sandbox. The volume is part of the sandbox's lifecycle, not separate from it.
Put anything the agent must not lose under the mount path — its memory store, its task state, its workspace. Anything outside it is scratch.
The storage class comes from sandbox.k8s.agentVolumeStorageClass, falling back to the cluster default. See Install on Kubernetes.
Health checks#
Without a probe, "running" means the process has not exited. That is a weak signal for an agent that has hung, wedged on a lock, or crashed its HTTP server while its supervisor stays up.
healthCheck:
type: http
http:
path: /healthz
port: 8080
--health-check path=/healthz,port=8080,interval=10,initial-delay=30,timeout=5,failures=3
Pass --health-check none to leave probing off.
| Field | Default | Range |
|---|---|---|
type |
none |
http or none |
intervalSeconds |
10 | 1–3600 |
initialDelaySeconds |
30 | 0–3600 |
timeoutSeconds |
5 | 1–300 |
failureThreshold |
3 | 1–100 |
Give initialDelaySeconds enough room for the agent to start. An agent that pulls models or warms a cache on boot will fail a probe that starts checking too early, and get restarted before it ever becomes ready.
Reading health#
nexusctl sandbox describe surfaces the latest health snapshot the pod watcher pushed:
| Field | Tells you |
|---|---|
agentRunning |
Whether the agent process is up. |
startedAt / lastActivityAt |
When it started, and when it last did something. |
exitStatus |
Exit code and signal, when it has exited. |
probe.status |
Result of the most recent HTTP probe. |
probe.restartCount |
How many times the container has restarted. |
probe.lastError |
Why the last probe failed. |
imageDigest |
The resolved digest actually running — the answer to "is this really the image I pushed?". |
errorReason |
Provisioner error for a sandbox in error. |
Revisions#
Every change to a sandbox's image, command, resources, environment, health check, or exposed ports creates a numbered revision and restarts the sandbox on it. Label-only and policy-only changes are metadata and do not restart anything.
curl -fsS -H "Authorization: Bearer $LENS_AGENTS_TOKEN" \
https://agents.example.com/v1/projects/$PROJECT_ID/sandboxes/$SANDBOX_ID/revisions
List the revisions of the nightly-refactor sandbox in production
and tell me what changed between the last two.
Each revision is a full snapshot of the configuration that was live, so the history answers "what was this agent running last Tuesday?" without a separate change log.
Rollback#
curl -fsS -X POST \
-H "Authorization: Bearer $LENS_AGENTS_TOKEN" \
-H "Content-Type: application/json" \
https://agents.example.com/v1/projects/$PROJECT_ID/sandboxes/$SANDBOX_ID/rollback \
-d '{"revisionNum": 3}'
Roll the nightly-refactor sandbox in production back to revision 3.
Rollback restores the image, command, resources, environment, health check, and exposed ports of that revision together. The persistent volume is not rolled back — the disk stays as the newer version left it.
Revisions and rollback are API and MCP surfaces
nexusctl has no revisions or rollback verb today. Use the REST endpoints above, or the list_sandbox_revisions and rollback_sandbox tools over MCP.
Spend#
An agent that runs for weeks spends money for weeks. Cap it per sandbox:
curl -fsS -X PUT \
-H "Authorization: Bearer $LENS_AGENTS_TOKEN" \
-H "Content-Type: application/json" \
https://agents.example.com/v1/orgs/$ORG_ID/spending-limits \
-d '{"actorType": "sandbox", "actorId": "'"$SANDBOX_ID"'",
"period": "month", "limitCents": 5000}'
Cap the nightly-refactor sandbox in production at $50 a month.
nexusctl sandbox set-limit nightly-refactor \
--project production --org acme \
--period month --limit-cents 5000
On breach, the inference proxy returns 429 and the sandbox keeps running — it loses model access, not its process and not its disk.
Check what it has spent:
curl -fsS -G -H "Authorization: Bearer $LENS_AGENTS_TOKEN" \
https://agents.example.com/v1/orgs/$ORG_ID/usage-costs \
-d actorType=sandbox -d actorId=$SANDBOX_ID
How much has the nightly-refactor sandbox spent this month?
nexusctl sandbox spend nightly-refactor --project production --org acme
See Spending limits for org, user, and agent scopes.
Related#
- Sandbox spec — declaring volumes and probes in a file
- Exposed ports — the port a health check usually probes
- Spending limits — budgets by org, user, agent, and sandbox
- Install on Kubernetes — storage classes and sandbox ceilings