When is approval required?
The Mandate policy engine can require human approval before a transaction proceeds. Seven conditions trigger an approval request. If any one matches, the intent entersapproval_pending state and waits for the owner’s decision.
| # | Trigger | Policy field / source |
|---|---|---|
| 1 | Amount above threshold | require_approval_above_usd |
| 2 | Action requires approval | require_approval_actions (e.g. ["swap", "bridge"]) |
| 3 | Selector requires approval | require_approval_selectors (function selectors like 0xa9059cbb) |
| 4 | High risk flag from Aegis scanner | Risk score exceeds threshold |
| 5 | Unknown agent (not registered on-chain, EIP-8004) | On-chain identity check |
| 6 | Low reputation score | Reputation below minimum threshold |
| 7 | Reason flagged by scanner | Prompt injection or suspicious intent detected in reason field |
How does the SDK signal an approval requirement?
When a transaction passes policy checks but requires human sign-off, the SDK throws anApprovalRequiredError. This is not a rejection. The intent is created and waiting for a decision. Your code catches the error, extracts the intentId, and polls until the owner approves or rejects.
Handling approval workflows
When a transaction requires human approval, the SDK throws anApprovalRequiredError. Catch it and poll for the decision:
Catching ApprovalRequiredError
Here is the full pattern usingMandateClient directly. This gives you maximum control over the wait behavior.
waitForApproval() method polls GET /api/intents/{intentId}/status at the specified interval. It resolves when the status becomes approved or confirmed. It throws a MandateError if the approval is rejected (failed) or times out (expired).
waitForApproval options
| Option | Type | Default | Description |
|---|---|---|---|
timeoutMs | number | 3600000 (1 hour) | Maximum time to wait before throwing a timeout error |
intervalMs | number | 5000 (5 seconds) | Polling interval between status checks |
onPoll | (status) => void | undefined | Callback fired after each poll. Use for logging or progress updates. |
MandateWallet shortcut
MandateWallet provides transferWithApproval() and sendTransactionWithApproval() that handle the entire flow: validate, wait for approval if needed, sign, broadcast, and confirm. No manual try/catch required.
How owners approve
When a transaction entersapproval_pending, the owner receives a notification through their configured channels:
- Dashboard: The Approvals page shows pending requests with agent name, amount, action, reason, and risk level. One-click approve or reject with an optional note.
- Telegram bot: Sends a formatted message with transaction details. The owner replies with approve or reject.
- Slack webhook: Posts to the configured channel with action buttons.
Configure notification channels in Dashboard > Notifications. You can enable multiple channels simultaneously. The first decision from any channel takes effect.
Approval TTLs
Pending approvals expire after 1 hour by default. This matches thewaitForApproval() default timeout of 3600000ms. After expiry, the intent transitions to expired state. The agent must call validate() again to create a new approval request.
You cannot extend the TTL programmatically. If your workflow requires longer decision windows, contact support to adjust the server-side configuration.
Next Steps
Approvals Dashboard
Review and manage pending approval requests from your agents.
Notifications
Configure Telegram, Slack, and dashboard notification channels.
Approval Triggers Reference
Full reference for all 7 approval trigger conditions and their policy fields.
MandateWallet
High-level SDK with built-in approval handling via transferWithApproval().