Skip to content

Action state machine ​

Every protected request becomes a durable action with an ID (act_…), a state and a reason code. The action outlives the agent's process, its token, its MCP session and any notification. An action ID alone never proves permission: status and resume need the original agent's own authenticated, DPoP-bound credential.

text
submit ──► denied
  │
  ├──► pending_approval ──► approved ──► (resume) ──► executing ──► succeeded
  │          │                 │                          │
  │          ├► denied         ├► expired                 ├──► failed
  │          ├► expired        ├► revoked                 │
  │          ├► revoked        ├► cancelled               └──► outcome_unknown ──► succeeded | failed
  │          └► cancelled      └► denied                        (reconciliation only)
  │
  └──► approved   (allowed within the standing grant)

States and what to do ​

StateWhat the agent or operator should doExecution semantics
pending_approvalPersist the ID, display a safe summary, then wait for a verified event or poll with backoff.No business write. Approval system retries reuse the same correlation ID.
approvedOriginal agent authenticates and calls resume with the same action ID and approved parameters.Grant is eligible for one execution after policy and freshness checks.
executingPoll the existing ID.Atomic claim prevents parallel resumes from dispatching a second execution.
succeeded / failedRead the recorded outcome and receipt.A completed write returns its prior result on retry. Mark a failure definitive only when the target can establish that outcome.
outcome_unknownReconcile with the target by operation key and surface the status to the operator.No blind retries. Restore a final state from authoritative evidence.
denied / expired / revoked / cancelledStop. A material change or a fresh approval requires a newly authorized request.These states close a request before dispatch. In-flight work is reconciled separately.

Transitions ​

Only these transitions exist (packages/core/src/states.ts). Each is a conditional update on the current state, so concurrent writers converge and a late callback cannot revive a closed record.

FromToCaused byReason code set
(submit)deniedNo usable grant, a policy deny, a ceiling or an emergency deny.no_grant, grant_*, operation_not_permitted, resource_not_permitted, ceiling_exceeded, policy_deny, emergency_deny, …
(submit)pending_approvalA matching require_approval rule.The rule's reason, e.g. finance_approval_required, else approval_required
(submit)approvedAllowed within the standing grant.allowed_by_grant
pending_approvalapprovedEvery required approval received.awaiting_agent_resume
pending_approvaldeniedAn approver denied.approval_denied
pending_approvalexpiredThe decision deadline or the request's not_after passed.approval_expired
pending_approvalcancelledThe requesting agent cancelled.cancelled_by_requester
approvedexecutingThe original agent resumed and the single execution claim succeeded.dispatched
approvedrevokedOn resume: grant revoked, agent suspended, credential revoked or emergency deny.grant_revoked, agent_suspended, credential_revoked, emergency_deny
approveddeniedOn resume: current policy denies, or a required approval is no longer satisfied.e.g. policy_deny, policy_stale, approver_ineligible
approvedexpiredThe resume deadline or not_after passed.resume_expired
approvedcancelledThe requesting agent cancelled.cancelled_by_requester
executingsucceeded / failedA valid provider attestation; or, without one, a 2xx / 4xx the gateway observed.target_confirmed / target_failed; gateway_observed_success / gateway_observed_failure
executingoutcome_unknownTimeout, network error, 5xx, 408, 429, or an attestation that failed verification, after dispatch.target_timeout
outcome_unknownsucceeded / failedReconciliation found an authoritative, verified attestation for the operation key.reconciled

Notes:

  • An action allowed within the standing grant is created as approved and, on the API, proxy and MCP paths, resumed immediately on the same request by the same agent. Submit with "execute": false to record it as approved and resume later.
  • approved also carries progress: "awaiting_agent_resume". An approved action may simply be waiting for its agent to come back.
  • A resume after dispatch (executing, succeeded, failed, outcome_unknown) returns the existing record. It never dispatches again.
  • An expired resume window is resume_expired; a grant that expired or was revoked before resume shows up at resume as grant_expired or grant_revoked.
  • Immediate execution happens only when Axiom's hosted gateway is the project's executor and the service is not in embedded-SDK mode. Otherwise the allowed action stays approved: an embedded-SDK provider claims it through /v1/authorize, and after a cutover only the customer-hosted gateway holding the executor flag may claim it.

Reading the state ​

GET /v1/actions/{action_id} returns the status document (ActionStatus). The fields that drive an agent's next step:

FieldUse
state, reason_codeWhat happened and why.
progressWhy a pending action is still pending (see Approvals).
retry_after_secondsPresent while pending_approval, executing or outcome_unknown: poll no faster.
decision_deadlineLast time a verified decision can arrive.
resume_deadlineLast time the original agent can resume. Never after the grant expires.
expires_atThe deadline that matters now: resume deadline when approved, else decision deadline, else not_after.
approvals[]Per role: required, received, system and next_party while pending.
outcomeOnce dispatched: state, target_ref, recorded_at and the provider's result detail.
receipt_urlPresent once a receipt has been issued.
supported_modes, resume_actorpoll, webhook, mcp_task; always original_agent.

The SDK's nextStep(state) maps each state to wait_for_decision, resume, track, read_outcome or stop, and describeStatus(status) renders the safe summary an agent can show its user. The conformance fixtures in the agent skill give one response per state.

Cancel ​

POST /v1/actions/{action_id}/cancel by the requesting agent moves a pending_approval or approved action to cancelled and cancels its pending approvals. Cancelling an already cancelled action returns it unchanged; any other state is 409 invalid_state.

Developer preview. Contract version 2026-11-14.