Skip to content

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:

FieldValue todayUse
supported_modespoll, webhook, mcp_taskPick one your runtime can actually use.
max_warm_wait_seconds25Upper bound for one in-session warm wait.
default_retry_after_seconds15Poll interval when a status omits retry_after_seconds.
resume_actororiginal_agentOnly 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:

RuntimeDuring approvalHow work resumes
Live agent with time remainingUse 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 schedulerStore 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 executionReturn 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.
ts
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.

ts
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.

sh
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:

text
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_01kd0m7s2v8x9yz3abcdefghjk

At 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.

Developer preview. Contract version 2026-11-14.