ctx.suspend(), a decision on an approval step, an edit to the payload under review, a signal a step waits on, and the reassignment of one person’s approvals and schedules to another. Acting on a run needs workflows:execute on the agent; reading a payload needs workflows:read. Approving, denying, editing a payload, and reassigning are human-only: a typed API credential is refused with 403 APPROVAL_REQUIRES_HUMAN. Starting, listing, and recovering runs are on Workflows, which also holds the error codes and the base URL, scopes, and envelope pointer; the ledger these decisions land in is on Workflow events.
Verified against lua-cli 3.33.0.
Step input
POST /workflows/:agentId/runs/:runId/steps/:stepId/resume
Resumes a step that calledctx.suspend() and is waiting for input. Creator or a workflows:execute holder.
any
required
Validated against the step’s
resumeSchema; at most 256 KB.200 with { "resumed": true, "runStatus" }, or the no-op { "resumed": false, "reason": "already_resumed", "recorded"?, "runStatus" } when someone got there first.
Errors
Equivalent:
lua workflows resume <runId> --step <stepId> --data '{"answer":42}', Workflows.resume().
Approvals
POST /workflows/:agentId/runs/:runId/approvals/:approvalId/resolve
Approves or denies an approval step. TheapprovalId (wfa_...) is on the run’s suspensions[].suspend.approvalId, on the approval.requested event, and on the inbox card. Person only.
string
default:"api"
Where the decision is made:
desktop, inbox, cli, or chat. The organization’s approval policy can restrict surfaces and demand a recent sign-in, which only desktop and inbox satisfy.string
required
approve or deny.string
At most 2,000 characters.
object
A replacement payload; only when the step declared
editable: true and editablePaths.string
The
payloadFingerprint of the revision you looked at (at most 128 characters). Required once the payload has been edited; a stale value is 409 PAYLOAD_MISMATCH.string[]
At most 5 artifact ids uploaded for this run.
200 with { "resolved": true, "outcome": "approved" | "denied", "runStatus", "stepId"? }, or the no-op { "resolved": false, "outcome": "noop", "reason": "already_resolved" | "expired" | "cancelled" | "run_gone", "decision"?, "decidedBy"? }.
Errors
Equivalent:
lua workflows approve <runId> --approval <id> --decision approve --note "Go ahead".
GET /workflows/:agentId/runs/:runId/approvals/:approvalId/payload
Reads the current approval payload, whole or paged. Needsworkflows:read.
string
A dotted path to an array inside the payload, for example
drafts, to page that array; any other target is 400 VALIDATION_FAILED.string
The index to start the page at;
nextCursor from the previous page.integer
default:"100"
Items per page, at most 100.
200 with { approvalId, editRevision, payloadFingerprint?, editable, editablePaths, size } and either kind: "whole" with payload (payloads up to 1 MB), kind: "paged" with arrays { <key>: { totalItems } } for a larger payload, or, with path, { path, items: [{ index, value }], nextCursor?, totalItems }. 404 RUN_NOT_FOUND or APPROVAL_NOT_FOUND; 413 PAYLOAD_PAGE_REQUIRED (offloaded: true) when the original payload is stored out of line and cannot be returned whole.
Equivalent: lua workflows approval-payload <runId> --approval <id>.
PATCH /workflows/:agentId/runs/:runId/approvals/:approvalId/payload
Edits the payload with a JSON Patch before deciding. Person only.string
required
The fingerprint the editor loaded; at most 128 characters.
array
required
At most 200 operations of
{ op: "replace" | "add" | "remove", path, value? } with RFC 6901 paths of at most 1,024 characters.string
At most 2,000 characters.
200 with { "applied": true, "editRevision", "payloadFingerprint" }; use the new fingerprint to resolve. 400 PATCH_INVALID or RESUME_SCHEMA_INVALID; 403 APPROVAL_REQUIRES_HUMAN, NOT_AN_APPROVER, or APPROVAL_SURFACE_DENIED; 404 RUN_NOT_FOUND or APPROVAL_NOT_FOUND; 409 PAYLOAD_MISMATCH, EDIT_NOT_ALLOWED, or NOT_SUSPENDED; 503 CONTROL_UNAVAILABLE.
Equivalent: lua workflows approve <runId> --approval <id> --edit @file --fingerprint <f> edits and decides in one step.
GET /workflows/:agentId/runs/:runId/approvals/:approvalId/items
Lists the per-item approvals fanned out under a parent approval. Needsworkflows:read.
Response
200 with { approvalId, items: [{ index, approvalId, itemKey?, status, decision?, decidedBy?, itemPayloadFingerprint?, editRevision?, payload }], totalItems }. 404 RUN_NOT_FOUND or APPROVAL_NOT_FOUND; 503 CONTROL_UNAVAILABLE.
POST /workflows/:agentId/runs/:runId/approvals/:approvalId/items/:index
Decides one fanned-out item. Person only; theX-Lua-Surface header applies as on resolve.
string
required
approve or deny.string
At most 2,000 characters.
string
The item’s
itemPayloadFingerprint; a mismatch is 409 PAYLOAD_FINGERPRINT_STALE.200 with { "resolved": true, "item", "decision", "parentResolved", "runStatus"? }. 400 VALIDATION_FAILED for a bad index or decision; 403 APPROVAL_REQUIRES_HUMAN, NOT_ITEM_APPROVER, or CUSTOMER_PRINCIPAL_CANNOT_APPROVE; 404 RUN_NOT_FOUND, APPROVAL_NOT_FOUND, or ITEM_NOT_FOUND; 409 PAYLOAD_FINGERPRINT_STALE, ITEM_ALREADY_DECIDED, or NOT_SUSPENDED; 503 CONTROL_UNAVAILABLE.
Signals
POST /workflows/:agentId/runs/:runId/signals/:name
Delivers a named signal to a run.string
required
The signal name, from 1 to 64 characters.
any
At most 64 KB; validated against the waiting step’s schema.
string
At most 128 characters; a repeat answers
200 with duplicate: true and delivers nothing.
Errors
400 VALIDATION_FAILED (an empty or over-long name) or SIGNAL_SCHEMA_INVALID (stepId, issues; the rejected payload keeps its dedupeKey free for a corrected retry); 404 RUN_NOT_FOUND; 409 RUN_TERMINAL; 413 PAYLOAD_TOO_LARGE; 422 SIGNAL_SCHEMA_UNCOMPILABLE; 429 SIGNAL_INBOX_FULL; 503 CONTROL_UNAVAILABLE.
Equivalent: lua workflows signal <runId> <name> --payload '{"ok":true}', Workflows.signal().
POST /workflows/:agentId/signals/by-key
Delivers a signal to the live runs of a workflow started with acorrelationKey, without knowing their ids.
string
required
The definition.
string
required
The key the runs were started with.
string
required
Signal name, at most 64 characters.
any
At most 64 KB.
boolean
Fan out to every matching run instead of refusing when several match.
string
At most 128 characters.
200 with { "runIds", "delivered", "results": [{ runId, accepted, consumed?, duplicate?, signalId?, code? }] }; a per-run refusal is reported in code and never fails the call.
Errors
400 CORRELATION_KEY_INVALID, SIGNAL_SCHEMA_INVALID, or VALIDATION_FAILED; 404 CORRELATION_KEY_NOT_FOUND (no live run); 409 CORRELATION_KEY_AMBIGUOUS with runIds when several match and allowMultiple is not set; 413, 422, 503 as on the per-run route.
Equivalent: Workflows.signalByKey().
Gates
Agated or suspended run carries gate.kind, and each kind has one way out:
The recovery verbs are on Workflows. A step waiting on a person shows as
suspensions[].suspend.kind: input answers to the resume route, approval to the resolve route, and signal to the signal routes; using the wrong one is 409 USE_SIGNAL_ROUTE or APPROVAL_REQUIRES_HUMAN.
Reassignment
POST /workflows/reassign
Moves one user’s workflow assets to another user in the organization. Needsworkflows:write on the organization, an organization admin (org:manage), and a person.
string
required
The organization; at most 128 characters.
string
required
The user leaving.
string
required
The user taking over; must be an organization member and, to inherit approvals, hold
workflows:execute.string[]
A subset of
schedules, approvals, connections, drafts; defaults to all four.boolean
Report what would move without moving it.
200 with { "schedules": { moved, skipped }, "approvals": { rerouted, skipped, detail? }, "connections": { remounted, unmountable[] }, "drafts": { moved }, "dryRun", "unavailable"? }; unavailable names blocks the server did not walk, whose zeros are not results. 400 VALIDATION_FAILED (a missing id) or REASSIGN_SAME_USER; 403 NOT_ORG_ADMIN or APPROVAL_REQUIRES_HUMAN; 404 USER_NOT_IN_ORG (userId) or WORKFLOWS_DISABLED; 409 REASSIGN_TARGET_LACKS_EXECUTE.
There is no CLI equivalent.
See also
- Workflows — the run model, the recovery verbs, and every error code
- Approvals and signals — designing the steps these routes answer
- Workflow builder —
approval(),waitForSignal(), andctx.suspend() lua workflows—resume,approve,approval-payload, andsignal- Workflow events — the
approval.*andsignal.*events these decisions append

