> ## Documentation Index
> Fetch the complete documentation index at: https://boxrouter.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# How a Sandbox Runs and Ends

> See the states a sandbox moves through, what each keeps and bills, and the four clocks that can stop work in it.

Four clocks can stop work in a sandbox, but only two end the sandbox itself. Which clock ran out
tells you whether your work stopped and whether the sandbox is still there.

![A sandbox is created, runs for a finite lifetime and is destroyed by default. A command timeout ends the command; a client timeout ends only the wait. Neither ends the sandbox.](https://mintcdn.com/nv-4965711d/RMVlH8Z1jdQT60zr/images/diagrams/lifecycle-light.svg?fit=max\&auto=format\&n=RMVlH8Z1jdQT60zr\&q=85\&s=a9c5434bf8524ba8235b8766d24dce04)

![A sandbox is created, runs for a finite lifetime and is destroyed by default. A command timeout ends the command; a client timeout ends only the wait. Neither ends the sandbox.](https://mintcdn.com/nv-4965711d/RMVlH8Z1jdQT60zr/images/diagrams/lifecycle-mobile-light.svg?fit=max\&auto=format\&n=RMVlH8Z1jdQT60zr\&q=85\&s=bdaa926ff240c5f12b274bbd03a26d3d)

With the default ending, BoxRouter destroys the sandbox at or after the end of its lifetime; the exact timing is not guaranteed. Files a later sandbox needs belong in a [Volume](https://boxrouter.ai/docs/volumes.md). The lifetime starts as sandbox creation begins on the selected route. A command or client timeout never ends the sandbox.

## States

`state` says which stage of its lifecycle a sandbox is in. Fetching one sandbox asks for a current
observation, and a list shows the last state BoxRouter recorded. After a sandbox ends, its record can remain
available even when a live observation is unavailable.

In a detail response, `observed_at` is when BoxRouter read the state and `state_recorded_at` is when
the state was last recorded. `state_recorded_at` can be `null` when no timestamp is available or a
lifecycle change overtook the read. Fetch again before relying on that state.

| Operation | Resulting State | What Is Kept | What Still Bills |
| - | - | - | - |
| Create | `creating`, then `running` | Files, processes, and memory | Compute at the granted size, as the provider meters it |
| Pause, or the lifetime's end with `at_end: pause` | `paused` | Files. Memory too when the pause reports `keeps: files_and_memory` | No compute. Storage, on providers that charge for a paused sandbox |
| Resume | `running` | Files. Processes too, unless the resume reports `cold_restart: true` | Compute again |
| Destroy, or the lifetime's end with the default `at_end` | `destroying`, then `destroyed` | Sandbox files can remain until destruction completes. An attached Volume survives | The sandbox can incur charges until destruction is confirmed. Volume storage is free during launch, up to its [workspace limit](https://boxrouter.ai/docs/volumes.md#what-it-holds) |

[Cost](https://boxrouter.ai/docs/cost.md) shows what each provider charges while paused. `state_reason` says what put the
sandbox in its state: `requested` (a call you made), `lifetime`, `idle_shutdown`, `retention`
(a paused sandbox passed `kept_until`) or `external` (a change made at the provider).

`state` can also have these values:

* `error`: the provider reported a failure. Read `failure` before acting.
* `unknown`: BoxRouter could not map the provider's state. `native_state` contains the state as the provider reported it.

New values can be added. Handle unfamiliar states instead of failing.

## The Four Clocks

| Clock | Set With | When It Runs out, It Stops | It Leaves Running |
| - | - | - | - |
| Command deadline | `timeout_seconds` on each command | The command's process group | Processes that left the group; the sandbox |
| Client wait | Your HTTP client's timeout | Your wait for the response | The command runs until it exits or reaches its deadline |
| Inactivity | `requirements.idle_shutdown` at creation | The sandbox: paused, stopped or destroyed, as the route's idle shutdown does | Files, if it pauses |
| Lifetime | `lifetime_seconds` and `at_end` at creation | The sandbox: destroyed, or paused with `at_end: pause` | Files if it pauses; an attached Volume |

[Create a sandbox](https://boxrouter.ai/docs/reference/create.md) and [Run a command](https://boxrouter.ai/docs/reference/exec.md) give each
field's default and limits.

### Command Deadline

At the deadline, the command's process group receives `TERM` and then `KILL`. The call still succeeds: the result has
`timed_out` set to `true`, no `exit_code`, and the output the command wrote before it was ended. A `504 timeout` with
`outcome: unknown` is left for a command whose answer BoxRouter lost. Its operation reads `completed` with
`settled_by: wait_timeout`, which means BoxRouter stopped waiting, not that the command ended.

A child started with `setsid` leaves the process group and keeps running after the deadline.
While it holds the command's output open, the call returns only when that child exits. Start long work as a
[process](https://boxrouter.ai/docs/processes.md) instead.

### Client Wait

A client that gives up early cancels nothing. The command keeps running until it exits or reaches its own deadline,
and its operation is still recorded. Read the operation before you send the command again, and make the
client wait longer than `timeout_seconds`.

### Inactivity

Set `requirements.idle_shutdown` at creation to pause or destroy a sandbox nobody is using. A route
that doesn't provide idle shutdown is not eligible.

When idle shutdown pauses a sandbox, its state is `paused`, the same as after you pause it yourself.

Each route decides which activity resets its idle timer, and a running command doesn't always count.
Set `idle_seconds` longer than your longest silent command, or don't use idle shutdown for that
sandbox.

### Lifetime

The lifetime starts when BoxRouter begins creating the sandbox on the selected route. Time spent
creating it counts, so less time may remain when the sandbox is ready.

Each surface has one default when you set no lifetime:

| You Create the Sandbox With | Default Lifetime |
| - | - |
| `create`, the SDKs, and the CLI | 300 seconds |
| `launch`, including the Claude Managed Agents worker | The `create` default: 300 seconds, or [run while funded](https://boxrouter.ai/docs/run-while-funded.md) on a credit-funded route that can extend a lifetime |
| The OpenAI Agents SDK integration | 900 seconds |
| The AI SDK integration | 1,800 seconds |

The default for `create` is the one the request `lifetime_seconds` falls back to. A route's longest run is
`lifetime.max_seconds`. With credits on a route that can extend a lifetime, you can leave out
`lifetime_seconds` and [run while funded](https://boxrouter.ai/docs/run-while-funded.md).

`lifetime.ends_at` is when the lifetime runs out. BoxRouter sets the provider's own timer for it, and the provider ends the
sandbox when that timer fires. Only routes whose timer gives your `at_end` are eligible.

BoxRouter states no exact end time, so the sandbox can run past `ends_at`. Paused time doesn't count against the lifetime.

While a sandbox is paused, watch `kept_until`: BoxRouter destroys the sandbox then unless you resume it. A paused sandbox has no `ends_at`.
Check `remaining_seconds` before resuming to see the lifetime budget left.

Each route has a longest single run, `lifetime.max_seconds`. A request for a longer lifetime rules that route out.
To run longer than you first asked, set `resources.extendable_lifetime` when you create the sandbox, then
[extend the lifetime](https://boxrouter.ai/docs/pause-resume.md) while it runs.

A command can finish successfully after `lifetime.ends_at` if the sandbox is still running. If the sandbox
ends during the command, the call can fail with `410 sandbox_ended` and an unknown outcome. Check what it
changed before you run it again in a new sandbox.

Once the sandbox has ended, any call other than get, list, and destroy answers `410 sandbox_ended`;
`details` names what ended it and when. The record still reads for its retention, and destroy
stays a safe resend.

## Next Steps

> [card] [Pause, Resume, and Extend](https://boxrouter.ai/docs/pause-resume.md)
>
> Pause, resume, extend and idle shutdown, step by step.

> [card] [Recover from Errors](https://boxrouter.ai/docs/errors.md)
>
> What to do after a timeout or an unknown outcome.

> [card] [Check Your Limits](https://boxrouter.ai/docs/limits.md)
>
> The lifetime and other limits your route sets.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.