Answer a pending permission or question request
Answers one pending request by request_id: a permission with action allow or deny (a denial needs a reason the model can act on), a question with one answer per question, by option ids or free text where the question allows it. The answer is stored and the request closes at once: the pending list drops it and a status event ends the wait. The worker then hands the answer to the engine, and the receipt settles when it reports: succeeded once delivered, failed if the request expired (REQUEST_EXPIRED) or was cancelled (REQUEST_STALE, with why in its message: an interrupt, a park, a shutdown, the worker refusing the answer, or the engine having closed the request already) first, unknown if the execution ended before it reported or the engine no longer knew the request, so it may or may not have acted on the answer.
A parked request (state: parked) is answered the same way, whichever worker asked. The answer is kept until every request of its group is answered or expired; the one that closes the group resumes the session (resumed: true), and the receipt settles once the turn that resumes it has the answer. waiting_for counts the group's requests still open. A session paused by a person rather than by its park keeps the answer and stays paused.
Seeing a session is not answering for it: only its creator, its agent's admins, the workspace's owners and admins, and the keys of its agent that hold sessions:approve answer. Anyone else the session is visible to gets 403 (reason_code: role) and the request stays open; anyone it is not visible to, 404. No workspace key (personal or agent) answers a session that key started: 403 (reason_code: self_approval) with a failed answer receipt named by error.details.receipt_id, and the request stays open for another key or a person.
Scope: sessions:approve (API key or cookie session). Idempotency-Key: required.
AuthorizationBearer <token>For servers and scripts: an API key sent as an HTTP bearer token, Bearer <key>. It holds exactly the scopes it was issued with; a key issued before scopes existed holds none. It never needs the CSRF header, and it cannot manage agents, members, teams or API keys. Issue one in the web console under Settings → API keys; each operation names the scope it needs.
Scope: sessions:approve
id*stringThe session's id.
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$uuidIdempotency-Key*stringRequired, 1–255 characters; a UUID per user intent works. A retry with the same key and the same body returns the original response and runs the command once; the same key with a different body answers 409 IDEMPOTENCY_CONFLICT. A missing or invalid key answers 400 BAD_REQUEST, after the body is read.
1 <= length <= 255X-Requested-With?"werft-web"Required with a cookie session: the literal werft-web.
"werft-web"application/json- body
request_id*string1 <= lengthkind*stringreason?string1 <= lengthremember?stringaction*string"allow""deny"The answer is stored; the receipt tracks its delivery, and approval records who answered and the decision that let them.
application/json- response
receipt_id*string^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$uuidreceipt_status*string"accepted""succeeded""failed""unknown"approval?resumed?booleanWhether this answer resumed a parked session: it closed the last open request of the parked turn's group, and the session went resuming. False for an answer to a turn still waiting, which the worker hands over as before.
waiting_for?integerHow many requests of the same group are still neither answered nor expired. A parked turn resumes when this reaches 0.
0 <= value <= 9007199254740991curl -X POST 'https://example.com/v1/sessions/497f6eca-6276-4993-bfeb-53cbbbba6f08/answers' \ -H 'Idempotency-Key: string' \ -H 'Content-Type: application/json' \ -d '{ "request_id": "req_7f3a", "kind": "permission", "action": "allow"}'{ "receipt_id": "c4a1e9d2-7b3f-4e8a-a6c5-1d2e3f4a5b6c", "receipt_status": "accepted", "approval": { "answered_by": { "principal": { "kind": "user", "id": "3e7f1a90-5c2d-4b8e-8f61-2a9d0c4b7e35" }, "actor_user_id": "3e7f1a90-5c2d-4b8e-8f61-2a9d0c4b7e35", "agent_id": null }, "surface": "web", "decision_id": "5b9e2d7a-1c4f-4a83-b6e0-8d3f7a2c1e94" }}