AAgentis Docs

Operations and errors

Handle approvals, settlement, receipts and uncertain outcomes

Token transfers and paid API calls return an Operation. Its id identifies the request; operationHash binds the reviewed terms; status describes its current state.

Read and wait

const operation = await client.operations.get(operationId)
const requests = await client.operations.list()        // current credential's scope
const agentRequests = await client.operations.list(agentId)

const result = await client.operations.wait(operationId, {
  timeoutMs: 120_000,
  intervalMs: 1500,
  signal: AbortSignal.timeout(120_000),
})

wait polls while the operation is queued, submitting or submitted. It returns when approval is needed, the outcome is unknown, or the operation is terminal. It does not approve, sign again or resend a payment. Cancelling or timing out the polling request does not cancel the payment.

Statuses

StatusWhat your application should do
pending_approvalShow the owner approvalUrl; wait for their decision
queuedAuthorized and waiting for execution; track the same operation
submittingSigning/submission is in progress; do not create a replacement
submittedTransaction submitted; await reconciliation
unknownOutcome is unresolved; keep the original ID/key and inspect it
confirmedRead the settlement receipt and, for paid APIs, the HTTP response
failedInspect the error and receipt; actual network fees may have been spent
denied, rejected, expiredRead the reason; do not automatically request another payment

Owner approval

In Ask mode, the normal path is to give the owner the dashboard approval link. Agent credentials cannot approve or reject their own requests.

An owner-facing application can use a separate owner client after the user reviews the exact operation:

const reviewed = await ownerClient.operations.get(operationId)
// Present the recipient, amount, fees and expiry to the owner first.
const approved = await ownerClient.operations.approve(reviewed.id, reviewed.operationHash)
// Or, when the owner chooses rejection:
// await ownerClient.operations.reject(reviewed.id, reviewed.operationHash)

Use the hash of the operation the user actually reviewed. A policy change or expired approval requires a fresh review; do not silently approve a replacement request.

Receipts and responses

A settled operation can include:

  • transactionHash and receipt.chainId for the transaction.
  • receipt.blockNumber and receipt.success for settlement.
  • receipt.feeAtomic with receipt.feeAtomicDecimals for the fee in native/protocol precision.
  • receipt.feePayment for the fee asset, token precision and payer when applicable. Prefer its amountAtomic and decimals when displaying the token-denominated fee.
  • usdReservedMicros and usdSettledMicros for USD accounting.
  • httpResponse.status, headers and bodyBase64 for a paid API's response.
  • error for a request or execution problem.

feeAtomic and feePayment.amountAtomic describe the same charge at potentially different precisions; do not add them together. For example, on Tempo, feeAtomic: "16000000000000" with feeAtomicDecimals: 18 and feePayment: { amountAtomic: "16", decimals: 6, asset: "erc20:…" } both represent a fee of 0.000016 fee tokens. Solana's protocol precision is 9 decimals. Older server responses may omit feeAtomicDecimals; never assume it equals the payment token's decimals.

A successful chain payment does not guarantee a successful provider response. Likewise, an HTTP timeout does not prove that no payment happened. Operation polling tracks Agentis execution, not a provider's asynchronous job; use the returned provider job ID or link according to that provider's API.

Idempotency and retry behavior

SDK payment methods require { idempotencyKey }. Generate a UUID once for each intended payment and persist it with the task before the first request. A separate new payment needs a new key, even if its amount and recipient are identical. Users do not need to invent these keys.

After a lost response, read the original operation or repeat the request using the same credential, key and exact terms. The backend returns the existing operation rather than authorizing a replacement. Reusing a key with different terms is rejected. Unknown submissions retain their budget reservation until reconciled.

The CLI generates and saves keys and supports explicit retries. MCP accepts an optional key: when omitted, each tool call gets a fresh server-generated UUID and is not deduplicated against other calls. Never automatically repeat a keyless MCP payment after a timeout or missing result.

Handle API errors

import { AgentisApiError } from '@agentis-hq/sdk'

try {
  const operation = await client.operations.get(operationId)
} catch (error) {
  if (error instanceof AgentisApiError) {
    // error.status: HTTP status
    // error.code: machine-readable Agentis error code
    // error.message: explanation suitable for the request's caller
  } else {
    // Transport failure or timeout: inspect the original request before retrying.
  }
}

A missing permission, insufficient balance or policy denial requires the appropriate owner action, not another wallet or relaxed limits. Keep tokens, private approval links and payment credentials out of logs.

Card purchases use checkout IDs and card status methods, rather than crypto operation IDs.