Environment lifecycle
The task-environment state machine — how a `POST /environments` advances from build → provision → ready, and how clients observe it.
POST /environments returns immediately with state="building" and an id. The
platform provisions the task sandbox asynchronously; clients poll
GET /environments/{id}/status until the state is terminal. The synchronous
behavior — HTTP holding open for the full provision — was retired because it
broke under fan-out (the CapabilityEnvAdapter pattern) and tripped client-side
timeouts on cold image pulls.
dn env create security-mutillidae-sqli-login-bypass --wait# state=building # fast initial response# state=provisioning# state=ready # service_urls + execute_token populatedStates
Section titled “States”The execute_token is delivered in the POST /environments 201 response and
never appears in subsequent polls — the server only stores its hash. Stash it
on receipt; you cannot recover it from GET /environments/{id} or /status.
| State | Meaning | service_urls | execute_token (in POST response) | error |
|---|---|---|---|---|
building | Task image isn’t cached; SandboxBuildsWorker is compiling it. | null | populated | null |
provisioning | Build is ready; the provider is bringing the sandbox up. | null | populated | null |
ready | Sandbox is reachable. Run execute, read instructions, drive the agent. | populated | populated | null |
paused | Sandbox is suspended (cost-saving, user action). | populated | n/a (delivered earlier) | null |
torn_down | Sandbox is terminated. Final state after DELETE. | null | n/a (delivered earlier) | null |
failed | Build or provision failed. Inspect error and retry. | null | n/a (delivered earlier) | populated |
Transitions are monotonic with one exception: paused → ready when a paused
sandbox resumes. Everything else flows forward.
Polling contract
Section titled “Polling contract”GET /environments/{id}/status is the cheap polling endpoint — returns just the
state snapshot. GET /environments/{id} returns the full resource with the same
state-aware fields.
dn env status <env-id> --json# {"id": "...", "state": "provisioning", "expires_at": null, "service_urls": null}The SDK (dn.task_env(...) / TaskEnvironment.setup()) and the CLI (dn env create --wait) both poll transparently with exponential backoff (1s → 5s
cap). Client-side deadline is the caller’s timeout_sec when set, else 15
minutes. A failed state raises RuntimeError with the server-provided error.
Fan-out
Section titled “Fan-out”Peak concurrent task sandboxes for a CapabilityEnvAdapter run is
concurrency × parallel_rows (candidates in parallel × dataset rows scored
concurrently per candidate). The async POST /environments is what makes this
composable — each provision returns quickly and the SDK handles the polling in
the background, so a fan-out of 10 concurrent provisions doesn’t saturate the
HTTP connection pool.
Failure modes
Section titled “Failure modes”| Symptom | Where to look |
|---|---|
state="failed" with error: "task build failed: ..." | Task image didn’t compile. Inspect dn task info <ref> or the task’s build logs. |
state="failed" with error: "BadGatewayError: ..." | Provider rejected the sandbox (resource limits, image missing architecture). Check the host Docker daemon or E2B provider. |
state stuck in building past deadline | The API pod that owned the provision crashed mid-flight. Reprovision; the original env id is no longer recoverable. |
execute_token missing | The token is only returned in the POST /environments 201 response — polls never carry it. Stash it on receipt; if you lost it, DELETE and reprovision. |
Related
Section titled “Related”- Tasks — how a task becomes a build becomes a sandbox.
- Task-Environment Optimization — uses this lifecycle under
CapabilityEnvAdapter. - Sandboxes — the compute ledger the env sandbox writes to.