sandbox_status

Everything about one box: its state, goal, the last 30 steps done in it, whether the conversation using it is still at it, its wiring, services, running commands and credits. It only reads.

Input Output
id, fields (optional) status, goal, steps[] (the last 30 things done in the box, oldest first), agent (whether the conversation that last used it is still at it), placement, boxd health, wiring table, services (each web service with its url, each published version with its run), externalBaseUrl, environment (the same summary sandbox_start returns, read again on each call: connections with rttMs, each service's keysCount and notable, and activeBoxes), running (foreground and background commands, busiest processes, containers), sceneUrl, webUrl, takeoverUrl, the open takeover, registry, credits, interrupted reason, links (this box's links to other boxes), linkedFrom (the boxes linked to this one), stopsAt (when the idle rules stop it for good unless it is used before then), restorableUntil (on a stopped box that sandbox_start with restore can still bring back), freeze (when it freezes and what keeps it awake), boxdVersion, imageId

Returns everything the table above lists for one box. It only reads: it does not wake a frozen box, and it does not make the box yours (nor does it push stopsAt back; see Box states). Three of its fields are for whoever continues the work:

  • goal: what the box is for, as given to sandbox_start; absent on a box started without one (over REST, or before goal was required).
  • steps[]: the last 30 things done in the box, oldest first: commands, directories and the notes given with them, never their output, screenshots or recordings. Each step's screenshots and recordings are in a separate list: REST's GET /v1/boxes/{id}/media, which has only the steps with pictures, from the last 7 days, the newest 200 at most (see REST). Each step has:
    • at: when, RFC3339.
    • kind: exec, build, sync, wire, shot, device, start, stop, takeover, review, return or say.
    • summary: what was done (the command, the service name, the message), at most 200 characters; a longer one is cut and ends in ….
    • target (optional): the directory uploaded (sync) or built (build).
    • note (optional): the note given with the call.
    • actor (optional): human when a person did it; absent for agents and ParallelSandbox.
    • detail (optional): background for a command started with background: true, reused for a build whose output was restored, record for a sandbox_shot recording; for wire, the mode (box or external), link to <box> or version <label>.
    • ms (optional): how long it took.
    • ok: whether ParallelSandbox carried it out (the box answered); a command that ran and failed is still ok, with its exitCode.
    • exitCode, signal, timedOut (foreground commands only): how the command ended, as its sandbox_exec returned it. A background command has none here (it had just started); sandbox_procs has its end.
    • error (optional): one line on what failed on ParallelSandbox's side, never the command's output: the box did not respond, a person had taken the box over, or the call was closed before the command finished (with the execId to fetch its result with sandbox_procs).
  • The adapter's own housekeeping (the commands and uploads under /work/.psbx-sync/ that sandbox_sync uses to compare files) is left out. Steps are kept 7 days.
  • agent (live boxes only): whether the conversation that last used the box is still at it, { "state": "left", "idleSec": 5400 }. state is working, away (the conversation is still open but has not used this box for 10 minutes), left (the conversation closed) or idle (the box has been unused for 1 hour); the rules are in Which conversation is using a box. thisConversation: true is added when that conversation is the one calling. untracked: true means the calls that last used it carried no conversation id (an API-key script, REST, or a remote connection without the stdio adapter): its state is then only a guess from idle time, not a sign that another conversation is at it. Restarting your own client (Claude Code, Codex…) starts a new conversation identity, so a box you used before the restart shows left without thisConversation until you use it again; it is yours to continue.
  • disk (running boxes only): what fills the box, for when several agents share it and space runs low. filesystems gives sizeGb, usedGb and freeGb for /work, Docker's storage, /, /tmp and /dev/shm (a path on the same disk as one before it shows only sameAs; do not add those up); work the size in MB of each entry directly under /work (usually one project or one agent's directory each), largest first; caches the package caches and shared browsers (/root/.cache, /root/.npm, /root/go, Gradle, pnpm, Playwright's browsers and the like); temp what is over 1 MB in /dev/shm and /tmp; docker the lines of docker system df (images, containers, volumes, build cache, each with what is reclaimable). sandbox_status waits at most about 5 seconds for it: what is not measured yet is listed in notMeasured, with measuring: true, and goes on being measured, so calling again a few seconds later gives the rest. A result is kept 30 seconds (measuredAt). Nothing is cleaned for you: delete only what is yours, and ask before removing another directory in a shared box. A box started before this field shipped has no disk.
  • fields: ["goal", "agent", "steps"] returns only those top-level fields, plus id and status; a field name it does not know comes back in unknownFields. A message the person left for you (fromHuman) still comes with it. Use it when you look through several boxes another conversation left.
  • freeze (boxes that freeze when idle, while ready or taken over): at is when the idle rules freeze it if nothing changes, and blockedBy[] what keeps it awake now beyond the usual 10 idle minutes. background (commands started with background: true), url (requests through its URLs after your last call) and recording count only until their until; takeover, foreground (a sandbox_exec still running), link (another box connected to it) and phone (an attached phone freezes first, then the box) last until they end, and at is then absent. See Box states.
  • boxdVersion: the version of boxd in the box, asked live (correct right after a boxd restart too). imageId: the box image it started from (for a microVM box the image id, box-…). Boxes started before these were recorded have no imageId.
  • services[].lastProxyError: when a request through that service's URL could not get through in the last 30 minutes, the box's last attempt: at, status (503 when nothing answered on its port, after the box retried for 3 seconds in case it was restarting; 502 for other failures; or the 5xx the service itself returned), error (dial tcp 127.0.0.1:5173: connect: connection refused, a timeout) and count. A 503 box is frozen (or another state) or a 502 box unreachable comes from in front of the box and says so in the response itself. The same records, with any URL that matched no service, are in health.sceneErrors.
  • running.containers[]: each Docker container's name, image, status and ports; a database started with psbx-testdb also has envFile, the file with its connection settings (. /work/.sbx/testdb/<name>.env exports DATABASE_URL and the rest).

Every tool and topic is listed in the tool reference.