Every tool call the Gateway decides becomes a protected action: a record of the call, its decision and what happened next. The action's status tells you where it is in its life, whether it can still change, and whether a signed receipt exists for it.
This page lists every status in the current implementation. The same values appear in the Cloud API (status on GET /api/v1/orgs/<org-id>/actions, also usable as a ?status= filter) and in the dashboard's Status column and filter. Webhook events report most of the transitions. Agents see a different vocabulary, described in What the agent sees.
Statuses at a glance
| Status | Dashboard label | Meaning | Can still change | Receipt |
|---|---|---|---|---|
denied | Denied | The decision refused the call. Nothing ran. | No | No |
pending_approval | Pending approval | Waiting for an approver to decide the approval request. | Yes | Not yet |
approved | Approved | Allowed to run, but not run yet: either the policy allowed it, or an approver approved it. | Yes | Not yet |
executing | Executing | The Gateway consumed the approval and is calling the upstream, or has not recorded the outcome yet. | Yes | Not yet |
succeeded | Succeeded | The upstream call completed and its result is recorded. | No | Yes |
failed | Failed | The execution started but did not succeed. | No | Yes, in almost every case |
rejected | Rejected | An approver rejected the request. Nothing ran. | No | Yes |
cancelled | Cancelled | An owner or admin cancelled it before it ran. | No | Yes |
expired | Expired | Closed without running: it timed out or was superseded. | No | No |
authorized | Authorized (decision only) | Decision only: K-Block authorized the exact call and handed the authorization to the caller, which is responsible for executing it. K-Block executed nothing, records no execution and cannot confirm whether the caller executed it. | No | Yes (an authorization receipt) |
These ten values are the complete set: K-Block never records an action with any other status. There is no separate "outcome unknown" status; see Failed.
Decision and status are different things
Each action also has a decision, fixed when the call arrives: allow, require_approval or deny. The dashboard shows it in the Decision column as Allowed, Requires approval or Denied.
The status approved has two origins, and only the decision tells them apart:
- decision
allow: the policy allowed the call without a person. The Gateway executes it in the same request, so you rarely see it in this state for long. - decision
require_approval: an approver approved it. It runs when the agent repeats the identical call, or while the agent is still waiting for the decision.
Lifecycle
┌──> denied
│
call arrives ───┼──> approved (decision allow) ──────────┐
│ │
└──> pending_approval ──┬──> approved ───┼──> executing ──┬──> succeeded
│ │ └──> failed
├──> rejected ├──> expired
├──> expired └──> cancelled
└──> cancelledAn action of a decision-only tool never reaches executing: when the caller asks again for an approved action, it becomes authorized instead, and its receipt covers the decision, not an execution.
denied, rejected, expired, cancelled, succeeded, failed and authorized are final: nothing moves an action out of them. An identical call made later without an idempotency key becomes a new action with a new decision. An identical call that reuses the idempotency key of a closed action gets that action's stored outcome back instead. While an action is pending_approval or approved, an identical call without an idempotency key, or with the same one, resumes it rather than creating a new one.
Transitions
| From | To | What causes it |
|---|---|---|
| (new call) | denied | The policy denies the call, or a check fails first: no policy, no delegation granting the action, no principal, no eligible approvers, an invalid amount, the engine refusing the evidence, and similar. |
| (new call) | approved | The policy allows the call (decision allow). |
| (new call) | pending_approval | The policy requires approval. An approval request is created with the eligible approvers and an expiry. |
pending_approval | approved | An eligible approver signs an approval. See Review and decide. |
pending_approval | rejected | An eligible approver signs a rejection. |
pending_approval | expired | Nobody decided before the request expired (APPROVAL_EXPIRED), or the action was superseded (SUPERSEDED). |
pending_approval or approved | cancelled | An owner or admin submits a cancellation signed with the organization's principal key. |
approved | expired | The approved call was not executed before the action expired (TASK_EXPIRED), or it was superseded (SUPERSEDED). |
approved | executing | The Gateway checks everything again and consumes the approval (or the allow decision) exactly once, even when the same call arrives several times at once. |
approved | authorized | Decision only: the Gateway checks everything again, as for an execution, and hands the authorization to the caller exactly once, with a receipt. |
executing | succeeded | The upstream call returned a result and it was recorded. |
executing | failed | The upstream reported an error or the Gateway could not complete (UPSTREAM_FAILED), or the execution was interrupted and recovered later (INTERRUPTED). |
An executing action cannot be cancelled.
When actions expire
An action's expiry is set when it is decided: the rule's own approval expiry if it has one, otherwise the organization's Default approval lifetime (seconds) in Settings (24 hours unless an owner or admin changed it). It is never later than the end of the agent's delegation, nor, for a call an observe window relaxed, the end of that window. K-Block closes a due action as expired within about 15 seconds, so for those few seconds it can still show Pending approval or Approved. If the agent repeats the call first, the action is closed at once.
When actions are superseded
An open action is closed as expired with code SUPERSEDED when it can no longer run as it was decided. For example: the tool's upstream binding was changed and re-authorized, the delegation it relied on was revoked, the organization's principal identity was replaced, or (for allow decisions) the policy inputs changed. A policy rollback or emergency stop can also close open actions. The identical call then gets a new decision instead of resuming the old one.
Codes on closed actions
Expired, failed and denied actions carry an error_code that says why; rejected, cancelled and succeeded actions have none. The dashboard shows the code under the status badge and explains the common ones on the action page.
| Status | Code | Meaning |
|---|---|---|
expired | APPROVAL_EXPIRED | Nobody decided the approval request in time. Nothing ran. |
expired | TASK_EXPIRED | The call was approved, but not executed before it expired. Nothing ran. |
expired | SUPERSEDED | It could no longer run as decided (see above). Nothing ran. |
failed | UPSTREAM_FAILED | Recorded for every completed failure, including failures on the Gateway's side. When the Gateway detected the failure, error_detail starts with the precise code, as CODE: message. |
failed | INTERRUPTED | The execution started but its outcome was never recorded (for example, the Gateway stopped). Whether the upstream acted is unknown. |
denied | a reason code | Why the decision refused the call, for example POLICY_DENIED or NO_DELEGATION. When the workflow engine refused the evidence, the code is the engine's own error code. |
See Error codes for every reason code.
Failed
failed means the execution started and did not end in a recorded success. Check error_code before acting:
UPSTREAM_FAILEDmeans the upstream server reported an error, or the Gateway could not complete the call. A detail such asUPSTREAM_UNREACHABLE: …names the precise cause. Several of these causes do not mean that nothing happened: after a timeout,GATEWAY_ERROR, or a result that could not be accepted or recorded (RESULT_NOT_STORABLE,ATTESTATION_*,OUTPUT_*), the upstream may have acted, andRESULT_NOT_STORABLEcan even follow an upstream success.INTERRUPTEDmeans the outcome is unknown: the upstream may have carried out the call. Check the upstream system before the agent retries.
K-Block recovers interrupted executions automatically: the action shows Executing until recovery marks it Failed with code INTERRUPTED, normally no later than about 15 minutes after the execution started. If an action still shows Executing long after that, contact K-Block support with the action's ID (the last part of the action page's address).
Receipts by status
A receipt is a signed record of how the action ended. It is issued for these final statuses:
| Status | Receipt | Receipt outcome |
|---|---|---|
succeeded | Yes | succeeded |
failed | Yes; for INTERRUPTED only when K-Block can still sign one at recovery | failed |
rejected | Yes | final |
cancelled | Yes | final |
authorized | Yes: an authorization receipt, which proves the authorization, not an execution | pending (no approval was required: the receipt ends at the PROPOSAL) or granted (it ends at the person's APPROVAL) |
denied | No: nothing was signed | — |
expired | No | — |
pending_approval, approved, executing | Not yet | — |
The receipts list, the receipt page's header and the Receipt card on the action page show a final outcome as the action's status (Rejected or Cancelled). The Receipt card on the receipt page shows Final with the action's status beside it. An authorization receipt's pending or granted is shown as Authorized (decision only), with the signed outcome beside it on the receipt page: it is the state of the receipt's last signed object, not a request still waiting. See Receipt fields.
A receipt is hosted for the organization's retention period; after that, K-Block Cloud keeps only its record (IDs, outcome, SHA-256), and a bundle downloaded before then stays verifiable.
What the agent sees
The Gateway answers the agent with its own status names. The TypeScript client uses the Gateway's names, except that a successful call is completed.
| Action status | Gateway answer (status / code) | Client result status |
|---|---|---|
denied | denied / the reason code | denied |
pending_approval | approval_pending / APPROVAL_PENDING | approval_pending |
approved | the call executes; a check that fails before anything is consumed answers with its own refusal (for example denied / UPSTREAM_CHANGED) | — |
executing | replay / EXECUTION_IN_PROGRESS | replay |
succeeded | the tool's result, also when the call is repeated with the same idempotency key | completed |
failed | upstream_error with the recorded code, also when repeated with the same idempotency key | upstream_error |
rejected | rejected / REJECTED | rejected |
cancelled | cancelled / CANCELLED | cancelled |
expired | expired / APPROVAL_EXPIRED, TASK_EXPIRED or SUPERSEDED | expired |
authorized | POST /v1/authorize answers "allowed": true, status authorized, "execution": "caller"; repeated with the same idempotency key after its expires_at, "allowed": false, expired / AUTHORIZATION_EXPIRED | authorized (TypeScript authorizeAction) |
For a decision-only tool, an approved action is handed to the caller (authorized) when the caller asks again, instead of executing.
A request that finds the action already executed by another request is answered replay / REPLAY. The refusals plan_limit, invalid_request, unauthorized and unavailable record no new action. See Error codes.
Approval request statuses
An action with decision require_approval has one approval request. The Approvals page shows its status with these labels:
| Request status | Label | Meaning |
|---|---|---|
pending | Pending | Waiting for a decision |
approved | Approved | One eligible approver approved |
rejected | Rejected | One eligible approver rejected |
expired | Expired | It expired, or its action was superseded (also by a policy rollback or emergency stop) |
cancelled | Cancelled | Its action was cancelled while the request was pending |
One decision closes a request: there is no quorum, and the first valid decision wins.
A request stays approved after its action has run, and also when the approved action later expired, was superseded or was cancelled without running. To know whether an approved call actually ran, look at the action's status. The approval request's page shows the action's closing code (for example TASK_EXPIRED) when an approved call expired without running.
Execution statuses
The action page lists the execution, created when the Gateway consumes an approved action:
| Execution status | Meaning |
|---|---|
started | The upstream call is in progress (the action is executing) |
succeeded | The upstream call succeeded |
failed | It failed or was interrupted |
Known display quirk
In the Actions list, the explanation shown when you hover the code UPSTREAM_FAILED says that the upstream reported an error, even when the Gateway detected the failure itself. The action page names the precise code from the start of the detail; use it.