Destroy environment
Forcefully destroys the VM and marks its task failed. Not
idempotent: a second call on an already-gone VM returns 404
not_found in the standard error envelope, and SDKs raise on it
like any other 4xx. A caller that retries destroys should treat
404 as success itself rather than expecting the server to absorb
the repeat. A lifecycle hitl gate matching destroy can hold
it (202) or deny it (403 hitl_denied).
DELETE
/v1/environments/{vmId}Authorization
AuthorizationBearer token · headerrequired`Authorization: Bearer <token>` — either the static master token
(`ORCH_AUTH_TOKEN`) or a revocable API key issued via
/v1/api-keys (API keys require Postgres; without a database only
the master token is accepted). Master-only surfaces (exec,
attach, API key management) refuse API keys with 403. An expired
key is refused with 401 like an unknown one.
A key minted with `scopes` reaches only the hitl routes
(`/v1/interventions`, `/v1/hitl/*`, and POST /v1/api-keys to mint
a narrower key). Any other route is 403 code `forbidden`, reason
`env_scope`, except an `/v1/environments/{vmId}` route for an
environment the key does not cover, which is 404 so the key
cannot probe which environments exist.
**Authentication can be disabled entirely.** When neither
`ORCH_AUTH_TOKEN` nor an API key store (`DATABASE_URL`) is
configured — the default local-development posture — the bearer
middleware becomes a pass-through: every operation this document
marks as secured is reachable with no credentials, requests carry
no principal, and master-only surfaces therefore admit everyone.
Never run that configuration on a reachable network; set
`ORCH_REQUIRE_AUTH=true` to make the orchestrator refuse to start
without a master token.
or
fuse_sessionAPI key · cookierequiredHttpOnly session cookie set by POST /login for browser callers.
Consulted only when no Authorization header is present.
Path parameters
vmIdstringrequiredVM identifier assigned by the orchestrator.
Responses
202A hitl gate holds the action. Nothing ran yet. The body
is a HeldResponse naming the pending intervention, and
`Location` points at it. Wait on it with
GET /v1/interventions/{interventionId}?wait=; once approved the
orchestrator performs the action and stores the outcome in the
intervention's `result`.
intervention_idstringrequiredinterventionInterventionrequiredShow propertiesHide properties
idstringrequiredenv_idstringrequiredkindstringrequiredAllowed:
asksecrettakeoverreviewexeclifecyclecomputerstallexpirygatestringThe gate that raised it. Empty for a request.
modestringThe gate's mode. Notify and deny records are born terminal.
Allowed:
asknotifydenystatestringrequiredAllowed:
pendingapprovedrejectedexpiredcancelledpayloadobjectrequiredWhat was asked or attempted: `question` for an ask, `secret`,
`takeover` or `review` for those requests, `exec`, `lifecycle`
or `computer` for a gate, `signal` for a stall or expiry.
`decider` is set when a gate's decider sent the action on to
a human.
Show propertiesHide properties
questionstringchoicesstring[]execExecPayloadA held exec.
Show propertiesHide properties
argvstring[]requiredshellstringThe script when the caller sent `shell`; argv is then the sh -lc that runs it.
timeout_msinteger<int64>lifecycleLifecyclePayloadA held environment action.
Show propertiesHide properties
actionstringrequiredAllowed:
destroyforkmigratedrainsnapshotrotate-tokensecretInterventionSecretA secret request. It never holds the value.
Show propertiesHide properties
targetstringrequiredThe declared target's `env` name or `file` path.
labelstringrequiredThe target's label from the policy. Show it first: the agent
writes `message`, so `message` alone could claim to be
anything.
messagestringThe agent's own text.
takeoverInterventionTakeoverA takeover. `holder` and `started_at` are set while a human holds
the environment, which is also when the agent's exec and computer
calls get 423. The intervention stays `pending` until release.
Show propertiesHide properties
viastringrequiredAllowed:
terminaldesktopreasonstringholderActorShow propertiesHide properties
idstringrequiredA pinned or asserted actor id, `key:<key_id>`, `master`,
`system` for fuse itself, or `decider:<gate>`.
namestringsourcestringrequired`pinned`: fixed on the key at mint time. `asserted`: named in
`Fuse-Actor` by a `hitl:act-as` key or the master token, and only
as true as that caller's own auth. `key`: derived from the
credential. `system`: expiry and cancellation. `decider`: a
gate's decider allowed or denied the action; the id is
`decider:<gate>`.
Allowed:
pinnedassertedkeysystemdeciderkey_idstringThe key that authenticated the request, including the key that
asserted an actor. Omitted for the master token.
started_atstring<date-time>signalInterventionSignalWhat fuse saw when it raised a stall or expiry. A stall carries
`failures` and `last_exit_code`, or `quiet_seconds`. An expiry
carries `reaper` and `reap_at`, and once approved
`extended_until`.
Show propertiesHide properties
failuresintegerThe run of consecutive non-zero exec exits.
last_exit_codeintegerThe exit code that completed the run.
quiet_secondsinteger<int64>How long the agent had made no exec or computer call.
reaperstringWhat will tear the environment down.
Allowed:
idle_timeoutmax_runtimereap_atstring<date-time>When. The expiry's own deadline is capped at this, with a 10s floor.
extended_untilstring<date-time>Set on approval. The reapers leave the environment alone until then.
computerComputerPayloadA held computer action. On approval the orchestrator replays
`input` to the guest, with the approver's `edited_text` in place
of `text` when there is one.
Show propertiesHide properties
actionstringrequiredThe computer action name.
textstringThe text of a `type` (or the keys of a `key`), as sent.
inputobjectrequiredThe whole action body as the caller sent it (a ComputerActionRequest).
reviewInterventionReviewA review request. When `path` is set, `content` is that file as
fuse read it at request time, so the human reviews what the
agent submitted even if the file changed afterwards.
Show propertiesHide properties
pathstringcontentstringrequiredformatstringrequiredAllowed:
textdiffmessagestringThe agent's note to the reviewer.
truncatedbooleanSet when the file was longer than 1 MiB and was cut off.
deciderInterventionDeciderWhat a gate's decider said about an action it sent on to a
human: `verdict` `ask` with its `reason`, or the `error` that
made fuse fall through to a human.
Show propertiesHide properties
verdictstringrequiredAllowed:
askreasonstringerrorstringSet when the decider call failed.
triggered_byActorrequiredShow propertiesHide properties
idstringrequiredA pinned or asserted actor id, `key:<key_id>`, `master`,
`system` for fuse itself, or `decider:<gate>`.
namestringsourcestringrequired`pinned`: fixed on the key at mint time. `asserted`: named in
`Fuse-Actor` by a `hitl:act-as` key or the master token, and only
as true as that caller's own auth. `key`: derived from the
credential. `system`: expiry and cancellation. `decider`: a
gate's decider allowed or denied the action; the id is
`decider:<gate>`.
Allowed:
pinnedassertedkeysystemdeciderkey_idstringThe key that authenticated the request, including the key that
asserted an actor. Omitted for the master token.
deadlinestring<date-time>requiredon_timeoutstringrequiredAllowed:
rejectallowdecisionobjectPresent once terminal. An expired intervention carries the
on_timeout outcome and a cancelled one a reject, both decided
by "system".
Show propertiesHide properties
outcomestringrequiredAllowed:
approverejectanswerstringreasonstringdecided_byActorrequiredShow propertiesHide properties
idstringrequiredA pinned or asserted actor id, `key:<key_id>`, `master`,
`system` for fuse itself, or `decider:<gate>`.
namestringsourcestringrequired`pinned`: fixed on the key at mint time. `asserted`: named in
`Fuse-Actor` by a `hitl:act-as` key or the master token, and only
as true as that caller's own auth. `key`: derived from the
credential. `system`: expiry and cancellation. `decider`: a
gate's decider allowed or denied the action; the id is
`decider:<gate>`.
Allowed:
pinnedassertedkeysystemdeciderkey_idstringThe key that authenticated the request, including the key that
asserted an actor. Omitted for the master token.
decided_atstring<date-time>requirededited_argvstring[]The argv the approver replaced a held exec's with.
edited_textstringThe text the approver replaced a held `type` action's with.
grantstringHow far an approval of a gated action reaches.
resultInterventionResultWhat performing an approved gated action produced.
Show propertiesHide properties
execExecEnvironmentResponseThe outcome of a guest command.
A non-zero `exit_code` arrives with **HTTP 200**: the command
ran and failed, which is a successful answer to the question the
caller asked. It is not an error and must not be raised by an
SDK. HTTP errors mean the command could not be run at all.
`stdout` and `stderr` are kept apart, and are plain strings
rather than base64 — exec output is overwhelmingly text, and
encoding it would make every caller pay a decoding tax for the
rare binary case.
Show propertiesHide properties
exit_codeintegerrequiredThe guest command's own exit status. Non-zero is a normal
result, delivered with HTTP 200.
stdoutstringrequiredstderrstringrequiredcomputerComputerActionResponseThe guest's answer to one action.
Show propertiesHide properties
outputstringTextual output, e.g. the pointer location for `cursor_position`.
screenshotstringBase64 PNG of the display after the action settled. Present on
every action that implies one; for `zoom` it is the cropped
region at full resolution.
env_idstringThe environment a fork or migrate produced.
snapshot_idstringThe snapshot a snapshot action produced.
errorstringSet when the approved action could not be performed. A
non-zero exec exit code is a result in `exec`, not an error.
finished_atstring<date-time>requiredcreated_atstring<date-time>requiredupdated_atstring<date-time>required204VM destroyed.
403A hitl gate in `deny` mode refused the action (code
`forbidden`, `details.reason` `hitl_denied`, `details.gate` the
gate's name, `details.intervention_id` the terminal record; the
message is the gate's `reason`), or the caller may not use the
route.
errorobjectrequiredShow propertiesHide properties
codestringrequiredStable machine-readable code. `route_not_found` (404)
means the URL matches no route this server exposes —
usually a wrong host, port, or path prefix — as opposed
to `not_found`, where the route exists but the resource
does not. `forbidden` is emitted by CIDR-allowlist
rejections and by hitl access checks, which set
`details.reason` (see the Forbidden response);
master-only refusals (exec, attach, listing and revoking
API keys) return 403 with code `unauthorized`.
Allowed:
not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedlockedmessagestringrequiredHuman-readable description.
detailsobjectOptional stable, non-sensitive metadata (e.g. ids,
counts). Omitted when empty. A 403 `forbidden` from a
hitl access check carries `reason` (`missing_scope`,
`env_scope`, `self_approval`, `actor_required`,
`actor_mismatch`, `actor_not_allowed`,
`mint_escalation`, `hitl_denied`), plus `scope` for
`missing_scope`, and `gate` and `intervention_id` for
`hitl_denied`. A 423 `locked` carries `intervention_id`
and `kind` (`takeover` or `stall`).
404Resource does not exist. Note the distinct code
`route_not_found`, returned when the URL matches no registered
route at all (wrong host, port, or path prefix) rather than a
known route with a missing resource.
errorobjectrequiredShow propertiesHide properties
codestringrequiredStable machine-readable code. `route_not_found` (404)
means the URL matches no route this server exposes —
usually a wrong host, port, or path prefix — as opposed
to `not_found`, where the route exists but the resource
does not. `forbidden` is emitted by CIDR-allowlist
rejections and by hitl access checks, which set
`details.reason` (see the Forbidden response);
master-only refusals (exec, attach, listing and revoking
API keys) return 403 with code `unauthorized`.
Allowed:
not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedlockedmessagestringrequiredHuman-readable description.
detailsobjectOptional stable, non-sensitive metadata (e.g. ids,
counts). Omitted when empty. A 403 `forbidden` from a
hitl access check carries `reason` (`missing_scope`,
`env_scope`, `self_approval`, `actor_required`,
`actor_mismatch`, `actor_not_allowed`,
`mint_escalation`, `hitl_denied`), plus `scope` for
`missing_scope`, and `gate` and `intervention_id` for
`hitl_denied`. A 423 `locked` carries `intervention_id`
and `kind` (`takeover` or `stall`).
500Unexpected server error.
errorobjectrequiredShow propertiesHide properties
codestringrequiredStable machine-readable code. `route_not_found` (404)
means the URL matches no route this server exposes —
usually a wrong host, port, or path prefix — as opposed
to `not_found`, where the route exists but the resource
does not. `forbidden` is emitted by CIDR-allowlist
rejections and by hitl access checks, which set
`details.reason` (see the Forbidden response);
master-only refusals (exec, attach, listing and revoking
API keys) return 403 with code `unauthorized`.
Allowed:
not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedlockedmessagestringrequiredHuman-readable description.
detailsobjectOptional stable, non-sensitive metadata (e.g. ids,
counts). Omitted when empty. A 403 `forbidden` from a
hitl access check carries `reason` (`missing_scope`,
`env_scope`, `self_approval`, `actor_required`,
`actor_mismatch`, `actor_not_allowed`,
`mint_escalation`, `hitl_denied`), plus `scope` for
`missing_scope`, and `gate` and `intervention_id` for
`hitl_denied`. A 423 `locked` carries `intervention_id`
and `kind` (`takeover` or `stall`).
Request
curl -X DELETE "http://localhost:8080/v1/environments/string" \
-H "Authorization: Bearer YOUR_TOKEN"const response = await fetch("http://localhost:8080/v1/environments/string", {
method: "DELETE",
headers: {
"Authorization": "Bearer YOUR_TOKEN"
}
});import requests
response = requests.delete(
"http://localhost:8080/v1/environments/string",
headers={
"Authorization": "Bearer YOUR_TOKEN"
},
)Response
{
"intervention_id": "string",
"intervention": {
"id": "string",
"env_id": "string",
"kind": "ask",
"gate": "string",
"mode": "ask",
"state": "pending",
"payload": {
"question": "string",
"choices": [
"string"
],
"exec": {
"argv": [
"string"
],
"shell": "string",
"timeout_ms": 0
},
"lifecycle": {
"action": "destroy"
},
"secret": {
"target": "string",
"label": "string",
"message": "string"
},
"takeover": {
"via": "terminal",
"reason": "string",
"holder": {
"id": "string",
"name": "string",
"source": "pinned",
"key_id": "string"
},
"started_at": "2024-01-01T00:00:00Z"
},
"signal": {
"failures": 0,
"last_exit_code": 0,
"quiet_seconds": 0,
"reaper": "idle_timeout",
"reap_at": "2024-01-01T00:00:00Z",
"extended_until": "2024-01-01T00:00:00Z"
},
"computer": {
"action": "string",
"text": "string",
"input": {}
},
"review": {
"path": "string",
"content": "string",
"format": "text",
"message": "string",
"truncated": true
},
"decider": {
"verdict": "ask",
"reason": "string",
"error": "string"
}
},
"triggered_by": {
"id": "string",
"name": "string",
"source": "pinned",
"key_id": "string"
},
"deadline": "2024-01-01T00:00:00Z",
"on_timeout": "reject",
"decision": {
"outcome": "approve",
"answer": "string",
"reason": "string",
"decided_by": {
"id": "string",
"name": "string",
"source": "pinned",
"key_id": "string"
},
"decided_at": "2024-01-01T00:00:00Z",
"edited_argv": [
"string"
],
"edited_text": "string",
"grant": "string"
},
"result": {
"exec": {
"exit_code": 0,
"stdout": "hi\n",
"stderr": ""
},
"computer": {
"output": "string",
"screenshot": "string"
},
"env_id": "string",
"snapshot_id": "string",
"error": "string",
"finished_at": "2024-01-01T00:00:00Z"
},
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
}VM destroyed.
{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}