Waiting for a decision
A pending action can wait minutes or hours for a person. How your agent waits depends on what your runtime can do, not on Axiom: the action record is durable, and the same status read and resume work whether you come back in ten seconds or tomorrow.
Read the supported modes first
GET /v1/capabilities tells you what this deployment supports:
| Field | Value today | Use |
|---|---|---|
supported_modes | poll, webhook, mcp_task | Pick one your runtime can actually use. |
max_warm_wait_seconds | 25 | Upper bound for one in-session warm wait. |
default_retry_after_seconds | 15 | Poll interval when a status omits retry_after_seconds. |
resume_actor | original_agent | Only the agent that submitted can resume. |
sse exists in the contract's WaitMode type but is not offered: neither the API nor the MCP endpoints stream.
The runtime table
This is the brief's guidance (§5), which the SDK, the CLI and the agent skill follow:
| Runtime | During approval | How work resumes |
|---|---|---|
| Live agent with time remaining | Use a bounded warm wait and honor the retry interval. | Read status and resume in the current session. Persist the ID before the wait budget expires. |
| Runtime with a durable scheduler | Store the action ID and register a supported event consumer, or schedule a status check. | The customer’s scheduler wakes the workload. It authenticates as the original agent, including after legitimate key rotation. |
| CLI or agent with no background execution | Return the pending ID and a human-readable way to check it. Capture no implicit promise that a webhook can restart this process. | At the next invocation, the user or runtime supplies the saved ID. The authenticated original agent reads status and resumes. |
Whatever you choose, persist {action_id, operation_key, agent_id, resource, params, deadline} as soon as you see pending_approval, and tell the user which action is waiting (summary, action_id), who can review it (approvals[].next_party) and the deadline (decision_deadline). No business write has started.
Bounded warm wait
A live agent can wait briefly in-session. The rules:
- Never wait longer than
max_warm_wait_seconds(25 s) in one go, and only if you have that much time left. - Sleep at least
retry_after_seconds(15 s today) between status reads. - Never start a read that would end after your budget.
- When the budget ends, the record is already persisted; return the pending ID.
const w = await agent.waitForDecision("act_01kd0m7s2v8x9yz3abcdefghjk", { budgetSeconds: 25 });
if (!w.done) {
// w.checkAfter: when to look again. w.message: a safe sentence to show the user.
console.log(w.message);
}waitForDecision polls while the state is pending_approval; transport errors count as "no news". trackOutcome does the same while the state is executing or outcome_unknown, and never resumes or resubmits.
The whole loop
run submits, warm-waits, resumes once approved and tracks to a confirmed outcome, all within one budget. continue picks up a persisted record after a restart.
import { AxiomAgent, MemoryActionPersistence, newOperationKey } from "@sectigo/axiom-sdk";
const agent = new AxiomAgent({ baseUrl, agentId, signer, persistence: new MemoryActionPersistence() });
const r = await agent.run({
operation_key: newOperationKey("refund-417"),
operation: "billing.refund.create",
service,
tenant,
resource: { type: "invoice", id: "417" },
params: { amount: "25000", currency: "USD", beneficiary: "acct_acme_ops" },
});
switch (r.kind) {
case "completed":
/* succeeded or failed: read r.status.outcome and the receipt */ break;
case "stopped":
/* denied, expired, revoked, cancelled: report r.status.reason_code */ break;
case "waiting":
/* still pending: r.record is persisted; show r.message */ break;
case "tracking":
/* dispatched but unconfirmed: keep reading status by ID */ break;
}
// Later, perhaps in a new process, as the same agent (even after key rotation):
const later = await agent.continue(r.kind === "waiting" ? r.record : savedRecord);Use a durable ActionPersistence in production; MemoryActionPersistence is for tests. save must be durable before it resolves, because the SDK relies on it before ending a warm wait. run resumes at most twice while a status read still says approved and then returns tracking, so an embedded provider that never claims cannot cause a resume loop.
Polling
Polling is the mode every runtime can use: GET /v1/actions/{id} with backoff, never faster than retry_after_seconds. Each read is authenticated and recorded, so an admin can see on the action timeline when your agent last looked. A read also closes an action whose deadline has passed.
curl -sS -K <(npx tsx axiom-headers.ts GET "$AXIOM_API/v1/actions/$ID") "$AXIOM_API/v1/actions/$ID"Resume before resume_deadline. The resume window is the shortest resume_ttl_seconds of the satisfied approval rules (one hour in the sample), capped by the request's not_after and the grant's expiry. After it the action expires and a fresh request needs fresh approval.
Webhooks and relay
A runtime with a durable scheduler can register a webhook and sleep. Axiom sends a signed, data-minimised wake event when the action changes; the consumer verifies it and then reads status. The event is a hint, never authority. See webhooks and relay.
MCP tasks
Through the hosted MCP proxy, a client that negotiates tasks (the 2026-07-28 tasks extension or 2025-11-25 core tasks) gets a task whose taskId is the action ID and polls tasks/get. Other clients get a structured pending result and use the proxy's axiom_action_status and axiom_action_resume tools. See MCP.
CLI and agents without background execution
The axiom CLI never runs in the background. axiom submit without --wait submits, saves the record to actions.json in the config directory and prints how to check it:
act_01kd0m7s2v8x9yz3abcdefghjk pending_approval (finance_approval_required)
Action act_01kd0m7s2v8x9yz3abcdefghjk is waiting for approval: Billing agent requests USD 25,000 against invoice 417 for customer Acme Corp (sample customer). Waiting on finance_approver in axiom. A decision is needed by 2026-11-14T22:00:00.000Z. Check it with: axiom status act_01kd0m7s2v8x9yz3abcdefghjk
Saved. This command does not keep running; check again later with:
axiom status act_01kd0m7s2v8x9yz3abcdefghjk
Once approved, resume it as this agent with:
axiom resume act_01kd0m7s2v8x9yz3abcdefghjkAt the next invocation axiom status and axiom resume re-authenticate as the same agent and carry on from the saved record. See the CLI reference.