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

# Sandbox lifecycle

> Lifecycle states, asynchronous mutations, TTLs, and failure semantics.

Lifecycle mutations are asynchronous. Create, update, and delete are accepted immediately; the
sandbox record then converges, and its `state` field reports what has actually been observed,
never what was merely requested. Poll `GET /v1/sandboxes/{id}` (or let the CLI wait) until the
state you need is observed.

## States

| State           | Meaning                                                                                       |
| --------------- | --------------------------------------------------------------------------------------------- |
| `requested`     | The create request has been accepted.                                                         |
| `reserved`      | Capacity has been reserved.                                                                   |
| `materializing` | The image or snapshot is being materialized.                                                  |
| `ready`         | The sandbox is ready to start its workload.                                                   |
| `running`       | The workload is running.                                                                      |
| `stopped`       | The sandbox is sealed and stopped.                                                            |
| `terminating`   | The sandbox is being permanently deleted.                                                     |
| `terminated`    | The sandbox and its runtime resources were permanently deleted.                               |
| `failed`        | A terminal failure; `state_reason` names it.                                                  |
| `quarantined`   | Held after an observed contradiction; every mutating verb returns `409 quarantined`.          |
| `attention`     | The runtime state cannot be derived and needs intervention; `state_reason` names the anomaly. |

Failed and terminated records stay readable through `GET /v1/sandboxes/{id}` for a retention
window, then return `404 not_found`.

## Create

```sh theme={null}
hiloop sandbox create my-sandbox \
  --image ghcr.io/acme/workload@sha256:4f5c0f9a2e3d... \
  --ttl 3600
```

Create names at most one source, `--image` or `--from <snapshot>`; omitting both selects the
[platform default image](/sandboxes/images#the-platform-default-image). Passing both flags does not
name two sources: the snapshot is still the source, and the image is the base its workspace lands
on — see
[restore onto a different image](/sandboxes/images#restore-onto-a-different-image). It returns once
the API accepts the request; the CLI then waits until the sandbox is `running`. Names are unique
among the project's sandboxes that have not finished deleting (1–63 characters, lowercase letters,
digits, interior hyphens); a duplicate returns `409 name_conflict`. A sandbox still `terminating`
holds its name until it reaches `terminated`, and a `failed` or `quarantined` sandbox keeps its name
for as long as its record is retained. Retries are safe: the CLI generates an idempotency key per
invocation, or pass `--idempotency-key` so an automated caller's retry replays the original sandbox
instead of creating another — reuse a name with a fresh key, since replaying the old key returns the
original sandbox rather than creating a successor.

Pin images by digest when reproducibility matters; a tag is not a stable identity.

## TTL

`--ttl <seconds>` bounds the sandbox lifetime; omitted, the deployment default applies. The record
reports the expiry as `expires_at`. Updating the TTL restarts the clock from the time of the
update. Expiry is terminal for the runtime.

## Stop and start

Stop seals and stops the workload; start wakes a stopped sandbox and is a no-op on one already
running:

```sh theme={null}
hiloop sandbox stop my-sandbox
hiloop sandbox start my-sandbox
```

The contract: stop is accepted from `ready` or `running` and is idempotent from `stopped`; start
wakes `stopped` and is idempotent from `running`; a start racing an in-flight stop waits for the
stop to win. Anything outside that is refused by state, so a stop can never wedge a sandbox behind a
transition nothing completes.

Processes and memory are not resumed across a stop: a stop captures the process tree and records that
image as the sandbox's restore point, but a start does not replay it, so the workload begins again
from its image (see [memory capture](/sandboxes/architecture#memory-capture)). What survives is the
sandbox's identity, its name, and —
on the `durable` storage class — its `/workspace`, which reattaches to the sandbox when it starts
again. Everything outside `/workspace` comes back from the image. On the default node-bound class,
nothing on disk survives either, so treat a stop there as a fresh start with the same identity.

## Delete

```sh theme={null}
hiloop sandbox delete my-sandbox
```

Delete is permanent and accepted once for any sandbox that still holds resources, `failed`
included; a second delete returns `404 not_found`, and a `quarantined` sandbox refuses with
`409 quarantined`. It destroys the runtime, its node-bound storage, and the durable workspace
volume if the sandbox has one. Snapshots are separate resources and outlive the sandboxes they
came from.

The deleted sandbox's name is free to reuse as soon as it reaches `terminated`, and its record is
retained so the project's history stays readable. A released name no longer addresses that record:
commands that take a name resolve it to the sandbox holding it now, and a deleted sandbox is
addressed by its id. List them with `hiloop sandbox list --all`.

## Failures

A failed or quarantined sandbox carries a stable `state_reason` code and a human-readable message.
Out-of-band runtime death converges to a terminal state rather than leaving the record
`running` while commands fail. Errors across all routes use a flat `{code, message, request_id}`
envelope with stable codes, for example `sandbox_not_running` (409), `unsupported_capability`
(422), and `quota_exceeded` (429, create admission only).

See [reliability](/sandboxes/reliability) for retry and durability semantics and
[troubleshooting](/sandboxes/troubleshooting) for diagnosis.
