Tasks & approvals
Human-in-the-loop: tool approvals, ask requests and suspend prompts.
On this page
List tasks and approvals
/agents/{id}/taskslimit default 200 (clamped 1–1000). pending_approval rows carry the live Always-approve affordance (canAlwaysApprove, alwaysApproveBlockedReason), derived from the executor holding the request and never persisted.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
Query parameters
| Name | Type | Description |
|---|---|---|
status | string | Only this status |
limit | integer | Maximum rows to return |
Responses
| Status | Description | Body | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Tasks | TasksResponse | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
canAlwaysApproveboolean | pending_approval rows: whether POST …/always-approve would be accepted alwaysApproveBlockedReasonstring | Why canAlwaysApprove is false | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Errors 400 · 401 · 403 · 404
| 400 | Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY | |
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) |
Error bodies use the error format.
Example
curl "http://127.0.0.1:7385/agents/agent-1/tasks" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN"Read one task
/agents/{id}/tasks/{taskId}Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
taskIdrequired | string | Task id (GET …/tasks) |
Responses
| Status | Description | Body | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Task | TaskResponse | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
canAlwaysApproveboolean | pending_approval rows: whether POST …/always-approve would be accepted alwaysApproveBlockedReasonstring | Why canAlwaysApprove is false | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Errors 401 · 403 · 404
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) |
Error bodies use the error format.
Example
curl "http://127.0.0.1:7385/agents/agent-1/tasks/TASK_ID" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN"Approve or deny a pending task
/agents/{id}/tasks/{taskId}/resolveapprove lets it run (optionally with modifiedArgs); deny refuses it: reason is stored as the task's error and handed back to the agent as the owner's feedback (a blocking call's tool result reads Tool call "<tool>" was rejected by authorizer. Feedback: <reason>); pending_approval marks a pending task as awaiting approval. Only pending / pending_approval tasks resolve; others answer 409. At load the runtime sweeps orphans from a crash: running tasks become failed and the executor's own pending_approval tasks cancelled, so resolving one of those is a 409. Requests parked by an inner loop are answered on that loop's executor.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
taskIdrequired | string | Task id (GET …/tasks) |
Request bodyapplication/json · TaskResolveBody · required
| Field | Type | Description |
|---|---|---|
actionrequired | string | |
reason | string | On deny: stored as the task error and handed back to the agent as the owner's feedback |
modifiedArgs | object | Approve with these arguments instead (alias: modified_args) |
modified_args | object |
Responses
| Status | Description | Body | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Resolved | TaskResolutionResponse | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
canAlwaysApproveboolean | pending_approval rows: whether POST …/always-approve would be accepted alwaysApproveBlockedReasonstring | Why canAlwaysApprove is false | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Errors 400 · 401 · 403 · 404 · 409 · 500
| 400 | Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY | |
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) | |
| 409 | The resource is in a state that does not allow this now | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl -X POST "http://127.0.0.1:7385/agents/agent-1/tasks/TASK_ID/resolve" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"approve"}'Always approve: un-restrict the tool and approve the request
/agents/{id}/tasks/{taskId}/always-approveStudio's Approve ▸ Always approve. The host tool declaration (taken from the pending request, never the client) becomes enabled and unrestricted, persisted like PUT …/config; then the request is approved. 409 for protection overrides, one-shot approvals, locked declarations or a request no executor holds. No body.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
taskIdrequired | string | Task id (GET …/tasks) |
Responses
| Status | Description | Body | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Approved | TaskAlwaysApproveResponse | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
canAlwaysApproveboolean | pending_approval rows: whether POST …/always-approve would be accepted alwaysApproveBlockedReasonstring | Why canAlwaysApprove is false | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Errors 401 · 403 · 404 · 409 · 500
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) | |
| 409 | The resource is in a state that does not allow this now | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl -X POST "http://127.0.0.1:7385/agents/agent-1/tasks/TASK_ID/always-approve" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN"Approve every pending gated approval
/agents/{id}/tasks/approve-allStudio's Approve all: main and every running inner loop (or only loop, from the body or query). Protection overrides are never approved; they are counted in skippedProtection.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
Query parameters
| Name | Type | Description |
|---|---|---|
loop | string | Cognition loop to address. Absent = main. Unknown loops answer 404. |
Request bodyapplication/json · ApproveAllBody · optional
| Field | Type | Description |
|---|---|---|
loop | string | Only this loop's approvals |
Responses
| Status | Description | Body | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Counts | ApproveAllResponse | ||||||||||||
| ||||||||||||||
Errors 400 · 401 · 403 · 404 · 409 · 500
| 400 | Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY | |
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) | |
| 409 | The resource is in a state that does not allow this now | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl -X POST "http://127.0.0.1:7385/agents/agent-1/tasks/approve-all" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'{
"agentId": "Xk3v9QpLm2",
"approved": 2,
"skippedProtection": 1
}List pending ask requests
/agents/{id}/asksEvery loop's (main and each running inner loop); loop names the loop whose turn is waiting.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
Responses
| Status | Description | Body | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Asks | AsksResponse | ||||||||||||||||||
| ||||||||||||||||||||
Errors 401 · 403 · 404
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) |
Error bodies use the error format.
Example
curl "http://127.0.0.1:7385/agents/agent-1/asks" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN"Answer an ask request
/agents/{id}/asks/{requestId}/respondRequest ids are numbered per loop: pass the loop from GET …/asks when two loops ask at once; without it the first loop holding the id is answered. An id no loop holds (already answered, or never asked) answers 404 ask_not_found.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
requestIdrequired | string | Ask request id (GET …/asks) |
Request bodyapplication/json · AskRespondBody · required
| Field | Type | Description |
|---|---|---|
answerrequired | string | |
loop | string | The loop that asked (GET …/asks lists it); absent = the first loop holding the id |
Responses
| Status | Description | Body | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | answered is false when no loop held the request | AskRespondResponse | ||||||||||||
| ||||||||||||||
Errors 400 · 401 · 403 · 404 · 500
| 400 | Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY | |
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (not_found), or no loop holds this ask (ask_not_found)ask_not_foundnot_found | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl -X POST "http://127.0.0.1:7385/agents/agent-1/asks/REQUEST_ID/respond" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
-H "Content-Type: application/json" \
-d '{"answer":"Yes, go ahead."}'Resume or stop after a suspend prompt
/agents/{id}/suspend/respondPath parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
Request bodyapplication/json · SuspendRespondBody · required
| Field | Type | Description |
|---|---|---|
resumerequired | boolean |
Responses
| Status | Description | Body | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Resolved | SuspendRespondResponse | |||||||||
| |||||||||||
Errors 400 · 401 · 403 · 404 · 500
| 400 | Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY | |
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl -X POST "http://127.0.0.1:7385/agents/agent-1/suspend/respond" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
-H "Content-Type: application/json" \
-d '{"resume":true}'