Decide intervention
Approves or rejects a pending intervention. Approving an ask needs
an answer (one of choices when the ask set them). A reject
always carries a reason; one is filled in when omitted. Deciding a
resolved intervention, including one whose deadline passed before
the decision arrived, is 409.
Requires the hitl:decide scope or the master token. Full-access
keys never hold hitl:decide, so an agent driving Fuse with its
own key cannot answer its own request; mint a scoped key for the
human instead (fuse hitl invite). Every refusal is 403 with code
forbidden and a details.reason:
missing_scope: the key lackshitl:decide(details.scopenames it).self_approval: the deciding key, or the deciding actor, is the one that raised the intervention. The master token naming no actor is exempt from the actor half of this check.actor_required: the environment’s policy setsrequire_actorand the decision carries neither a pinned nor an asserted actor.actor_mismatch/actor_not_allowed: theFuse-Actorheader was refused (see the FuseActor parameter).
Signals. A stall is acked with a plain approve or reject;
either one lifts the lock on the agent. Approving an expiry
keeps the environment away from the reaper that was due for
extend_seconds (60 to 86400), or one more full window of that
reaper (capped at 24h) when it is omitted; the decision’s
answer reads extended until <time> and
payload.signal.extended_until holds the time. Rejecting an
expiry lets the reap go ahead. extend_seconds on anything but
an expiry approval is 400, and so are edited_argv,
edited_text and grant on a signal.
Gated actions. edited_argv (a held exec) and edited_text
(a held computer type) replace the action before the
orchestrator performs it. Either is re-checked against the
deny gates, a match being 403 hitl_denied. An edit cannot be
combined with an explicit grant (400), and a gate’s default
grant drops to once with one. Both are 400 on a reject.
Reviews. A review is approved or rejected with the
reviewer’s comments in reason, which the agent reads on both
outcomes. It takes no answer, edit or grant.
Secrets. ?action=secret answers a secret request with an
AnswerSecretRequest body instead of deciding it. It needs
hitl:secret rather than hitl:decide (full-access keys hold
neither) and is subject to the same self_approval and
actor_required checks. The value is written into the guest at
the declared target, then dropped: it is never stored, logged,
returned or put on the event stream, and it never appears in an
error message. The intervention is approved with
decision.answer "done", which is all the agent reads. 400
when the intervention is not a secret request, the value is
empty or over 64 KiB, the target is no longer declared, or the
orchestrator has no TOKEN_ENCRYPTION_KEY. 409 when it is
already resolved, or another answer to it is being written right
now. Once the value is in the guest the request counts as
answered, even if its deadline passed during the write.
/v1/interventions/{interventionId}AuthorizationBearer token · headerrequiredfuse_sessionAPI key · cookierequiredinterventionIdstringrequiredactionstringrequiredapproverejectsecretFuse-ActorstringFuse-Actor-Namestringapplication/jsonanswerstringreasonstringedited_argvstring[]edited_textstringgrantstringextend_secondsinteger<int64>valuestringrequiredidstringrequiredenv_idstringrequiredkindstringrequiredasksecrettakeoverreviewexeclifecyclecomputerstallexpirygatestringmodestringasknotifydenystatestringrequiredpendingapprovedrejectedexpiredcancelledpayloadobjectrequiredShow propertiesHide properties
questionstringchoicesstring[]execExecPayloadShow propertiesHide properties
argvstring[]requiredshellstringtimeout_msinteger<int64>lifecycleLifecyclePayloadShow propertiesHide properties
actionstringrequireddestroyforkmigratedrainsnapshotrotate-tokensecretInterventionSecretShow propertiesHide properties
targetstringrequiredlabelstringrequiredmessagestringtakeoverInterventionTakeoverShow propertiesHide properties
viastringrequiredterminaldesktopreasonstringholderActorShow propertiesHide properties
idstringrequirednamestringsourcestringrequiredpinnedassertedkeysystemdeciderkey_idstringstarted_atstring<date-time>signalInterventionSignalShow propertiesHide properties
failuresintegerlast_exit_codeintegerquiet_secondsinteger<int64>reaperstringidle_timeoutmax_runtimereap_atstring<date-time>extended_untilstring<date-time>computerComputerPayloadShow propertiesHide properties
actionstringrequiredtextstringinputobjectrequiredreviewInterventionReviewShow propertiesHide properties
pathstringcontentstringrequiredformatstringrequiredtextdiffmessagestringtruncatedbooleandeciderInterventionDeciderShow propertiesHide properties
verdictstringrequiredaskreasonstringerrorstringtriggered_byActorrequiredShow propertiesHide properties
idstringrequirednamestringsourcestringrequiredpinnedassertedkeysystemdeciderkey_idstringdeadlinestring<date-time>requiredon_timeoutstringrequiredrejectallowdecisionobjectShow propertiesHide properties
outcomestringrequiredapproverejectanswerstringreasonstringdecided_byActorrequiredShow propertiesHide properties
idstringrequirednamestringsourcestringrequiredpinnedassertedkeysystemdeciderkey_idstringdecided_atstring<date-time>requirededited_argvstring[]edited_textstringgrantstringresultInterventionResultShow propertiesHide properties
execExecEnvironmentResponseShow propertiesHide properties
exit_codeintegerrequiredstdoutstringrequiredstderrstringrequiredcomputerComputerActionResponseShow propertiesHide properties
outputstringscreenshotstringenv_idstringsnapshot_idstringerrorstringfinished_atstring<date-time>requiredcreated_atstring<date-time>requiredupdated_atstring<date-time>requirederrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedlockedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedlockedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedlockedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedlockedmessagestringrequireddetailsobjectcurl -X POST "http://localhost:8080/v1/interventions/string?action=approve" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"answer": "string",
"reason": "string",
"edited_argv": [
"string"
],
"edited_text": "string",
"grant": "string",
"extend_seconds": 0
}'const response = await fetch("http://localhost:8080/v1/interventions/string?action=approve", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
"answer": "string",
"reason": "string",
"edited_argv": [
"string"
],
"edited_text": "string",
"grant": "string",
"extend_seconds": 0
})
});import requests
response = requests.post(
"http://localhost:8080/v1/interventions/string?action=approve",
headers={
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
json={
"answer": "string",
"reason": "string",
"edited_argv": [
"string"
],
"edited_text": "string",
"grant": "string",
"extend_seconds": 0
},
){
"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"
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}