Skip to main content
Moneda exposes actions to AI agents through four distinct patterns, picked based on what the action requires the user to do. Knowing the pattern up-front lets your agent handle each tool response correctly and set the right user expectations. This is the technical reference. For a consumer-facing version, see Working with your AI assistant.
Every pattern preserves Moneda’s self-custody guarantee: the user’s passkey is the only thing that can authorise value movement. The patterns differ only in when and how the user is involved.

At a glance

PatternWhen to useWhat the tool returnsWhat your agent does
InstantPure server state, no signature neededFinal resultShow result. Done.
HITL approvalEach invocation needs explicit user consent{ paymentRequestId, status: "PENDING_APPROVAL" }Tell user to approve in app, poll status until terminal.
Claim-linkOne-time device-bound setup (passkey, on-chain install){ activationUrl, expiresAt }Render the URL or QR for the user to open. Poll status if applicable.
Smart SessionRecurring, agent-initiated, bounded by static policy(Setup returns a claim-link; subsequent executions are transparent)Set up once via claim-link; thereafter call execution tools directly.
Does the action need a signature/biometric?
├─ No → Instant
└─ Yes
   ├─ Per-invocation user consent? → HITL approval
   ├─ One-time setup, then no further user action? → Claim-link
   └─ Recurring, bounded by static policy? → Smart Session

Pattern 1: Instant write

Direct server-side mutation. No signature, no biometric, no on-chain transaction. The tool runs the change and returns the final result in the same response. Examples: update_display_name, update_transaction_category, add_transaction_note, add_contact_moneda, add_contact_external, add_wallet, add_bank, batch variants of the above. Tool response shape:
{
  "success": true,
  "id": "..."
}
Agent behaviour: Show the result and continue. Don’t ask for further confirmation — the tool would have returned an error if anything was wrong, and these are reversible-by-the-user changes (categories can be re-categorised, contacts can be deleted, etc.). When NOT to use: If the action moves money, even a tiny amount, it’s not Pattern 1 — it’s HITL approval. Self-custody applies even to “small” payments.

Pattern 2: HITL approval (push notification + polling)

The user must explicitly approve each invocation. Used today for payments. Each call creates a server-side pending request, sends a push notification to the user’s phone, and returns immediately. The user approves (or rejects) in the Moneda app; your agent polls a status endpoint until it reaches a terminal state. Examples: initiate_payment, get_payment_status. Initiation response shape:
{
  "paymentRequestId": "...",
  "status": "PENDING_APPROVAL",
  "expiresAt": "2026-05-14T10:05:00.000Z",
  "amount": "50.00",
  "currency": "EUR"
}
Status polling response shape:
{
  "paymentRequestId": "...",
  "status": "COMPLETED",
  "transactionHash": "0x..."
}
Terminal states: COMPLETED, FAILED, EXPIRED, REJECTED. Agent behaviour:
  1. Call the initiation tool (e.g. initiate_payment).
  2. Tell the user a notification has been sent and what to do (e.g. “I’ve sent the payment request to your phone — approve it in the Moneda app”).
  3. Poll get_payment_status({ paymentRequestId }) periodically (every few seconds). Stop polling when the status is terminal or expiresAt passes.
  4. Tell the user the outcome.
Polling cadence. Moneda’s payment requests have a 5-minute TTL. Reasonable polling: every 3-5 seconds for the first minute, every 10-15 seconds after. Don’t poll faster than once per second; you’ll just hit rate limits. Why this pattern: value transfer is irreversible. The push-on-phone approval ensures the user is physically present, biometrically authenticated, and consciously authorising that specific payment.
For actions requiring a one-time device-bound ceremony — registering a new passkey, installing an on-chain Smart Session, accepting a recovery email — but where the user doesn’t need per-invocation approval afterwards. The tool creates a server-side pending claim and returns a short-lived signed URL. The user opens the URL in any browser; their synced passkey (iCloud Keychain, Google Password Manager, 1Password, etc.) signs the ceremony locally; the action completes atomically. Examples (designed): agent-mediated signup, scheduled-transaction activation, sub-account create. Status: signup is shipping; the others land alongside their respective backend features. Tool response shape:
{
  "claimId": "...",
  "activationUrl": "https://onboard.moneda.com/?token=eyJhbG...",
  "expiresAt": "2026-05-15T10:00:00.000Z"
}
Agent behaviour:
  1. Call the initiation tool.
  2. Render the activationUrl to the user. On a desktop, render as a clickable link. On a phone, the URL itself works in any browser. If the user’s passkey lives on a different device than the one they’re chatting from, the browser-side WebAuthn ceremony will use cross-device assertion (QR + Bluetooth proximity to the phone) automatically — no extra implementation needed.
  3. Tell the user what they’re signing for, briefly. (“This will set up email-based account recovery using ada@example.com — open the link and confirm with your passkey.”)
  4. If the action has follow-on state (e.g. “schedule activated” → continue scheduling), poll a corresponding status tool. For one-shot actions (passkey enrolled, recovery email accepted), no polling is needed; the user will tell you when they’re done.
Why this pattern: browser + synced passkey covers most device-bound ceremonies without requiring the Moneda mobile app, dramatically lowering friction for users who connect to Moneda via an AI assistant before installing the mobile app. The one-time nature makes it suitable for setup but not for recurring authorisation (use Pattern 2 for that). Claim link in chat history. Treat the activationUrl as a single-use token — which it is. The 24-hour expiresAt and one-shot consumption bound the blast radius if the URL leaks. Don’t echo it back later in conversation; refresh by calling the initiation tool again if the user needs a new one.

Pattern 4: Smart Sessions (delegated autonomous execution)

For repeating actions that should run without user interaction, bounded by a static on-chain policy: recipient pin, amount cap, time window. The user installs the session once via passkey (typically through a Pattern 3 claim-link); subsequent executions inside the policy run transparently. Status: rolling out alongside scheduled transactions. The first user is the recurring transfer engine; future users include auto-rebalance, threshold-triggered conversion, and recurring vault contributions. Setup response shape (one-time): see Pattern 3 — Smart Session installation is itself a claim-link. Execution response shape (subsequent):
{
  "scheduleId": "...",
  "status": "ACTIVE",
  "nextExecutionAt": "2026-06-01T08:00:00.000Z"
}
Agent behaviour:
  1. First time only: propose the standing instruction. Make the bounds explicit (“send €100 to your savings vault on the 1st of every month, capped at €1,200/year, expires 2027-05-14”). Initiate via the appropriate tool, render the resulting claim-link, wait for the user to install the session.
  2. From then on: query schedule status, propose adjustments, or initiate executions within the bounds without further per-invocation approval. The chain enforces the policy; the user’s passkey is the only thing that can revoke or amend.
Why this matters. Most fintechs cannot offer scoped agent delegation because they lack on-chain policy enforcement; the best they can do is server-side OAuth scopes with the custodian as trust root, which throws away self-custody. Moneda’s smart-account architecture means the bounds are enforced cryptographically: the worst a compromised agent can do is what the bounds allowed.

Detecting the pattern from a tool response

Your agent doesn’t need to know the pattern up-front for every tool — the response shape tells you what to do next.
Field presentPatternNext step
success: true (or terminal data)InstantShow result.
paymentRequestId + status: "PENDING_APPROVAL"HITLPoll get_payment_status.
claimId + activationUrlClaim-linkRender URL/QR.
scheduleId + status: "PENDING_INSTALL"Smart Session setup (claim-link sub-case)Render the included activationUrl.
scheduleId + status: "ACTIVE"Smart Session activeStanding instruction is live.
If a future tool response contains both paymentRequestId and activationUrl, treat it as claim-link first (the link is the user’s next action) and poll status afterwards. The patterns compose; they don’t conflict.

Forward-looking notes

The patterns above describe both what’s live today (Patterns 1 and 2) and what’s coming (Patterns 3 and 4 are designed and partially implemented; tools that use them will appear in Read Tools and Write Tools as they ship). Agents built today should be ready to handle all four — the response-shape detection above is forward-compatible. Internal documents that describe the implementation roadmap:
  • docs/agent-signup-spec.md — the canonical claim-link pattern, applied to signup.
  • docs/scheduled-transactions-spec.md — Smart Sessions architecture (PR #1818).
  • docs/agent-headless-parity.md — full pattern guide and parity gap inventory.
These live in the Moneda monorepo, not on this docs site.

Learn more

Working with your AI

The consumer-facing version of this page — what users will experience for each pattern.

Read tools

All Pattern 1 read operations available today.

Write tools

Pattern 1 instant writes plus Pattern 2 HITL payment initiation.

Scopes

OAuth permission scopes that gate access to tools.