Arete documentation
Consent and spending limits
For the complete documentation index optimized for AI agents, see llms.txt or llms-full.txt. A markdown version of this page is available by appending.mdto the URL or sendingAccept: text/markdown.
For AI agents: the documentation index is at llms.txt (full corpus: llms-full.txt). A markdown source for this page is /automations/consent.md.
Nothing runs for a wallet until its owner has signed a consent: a short, readable message that says which steps you may run, how much may leave their wallet, with which settings, and until when. This page covers what that message contains, how its limits are enforced, and how to present it.
What the user signs
Section titled “What the user signs”Build the message from the fields you want the user to agree to:
import { SOL } from "@usearete/automations";
const fields = { wallet, deploymentId: client.deploymentId, steps: ["buy"], limits: { perExecution: { [SOL]: "10000", [USDC_MINT]: "50000000" }, perWindow: { [USDC_MINT]: { amount: "200000000", window: "30d" } }, }, params: { amount: "50000000", weekday: "fri" }, expiresAt: new Date("2027-01-01"),};
const proof = await automations.consent.proofMessage(fields);The user’s wallet signs proof.bytes with signMessage. The message reads
like this:
app.example asks to run protocol steps for your wallet without asking each time:7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU
Deployment: dep_7d1e0b2aInstance: anySteps: buyPer run: 50000000 base units of EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1vPer run: 10000 lamports of SOLPer 30d: 200000000 base units of EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1vSetting "amount": "50000000"Setting "weekday": "fri"Expires At: 2027-01-01T00:00:00.000Z
These limits count the SOL and SPL tokens that leave your wallet, network fees included. You can revoke this at any time without signing.
Version: arete.automation-consent/v2Nonce: 3yZe7d7bqA1kxH3cMSGvJvIssued At: 2026-10-22T12:00:00.000ZSend the signature back with the same fields:
const { grant, warnings } = await automations.consent.grant({ ...fields, nonce: proof.nonce, issuedAt: proof.issuedAt, signature, // the wallet's 64-byte signature, or its base58 text});grant rebuilds the message from the fields it is given and checks the
wallet’s signature over it, so any changed field, raised limit or different
setting fails. The nonce works once and expires after ten minutes. Raising a
limit or changing a setting later needs a new signature.
warnings lists what your signer reports missing, such as no delegated
access to the wallet or no provider-side policy bounding it. Treat a warning
as a setup step the user still has to finish.
Limits
Section titled “Limits”Limits are per asset: SOL in lamports, or a token mint in its base units.
- Per run (
perExecution): the most one step may move out of the wallet. An asset with no per-run limit may not leave at all, so includeSOLfor network fees. - Per window (
perWindow): the most all steps together may move within a rolling window, such as30d.
What a step moves is measured by simulating its exact transactions before
signing. A step over a limit ends refused, with a reason naming the limit.
Spending is recorded the moment a step is signed, and only one step per wallet runs at a time, so even many workers cannot overspend a window. If a transaction never lands, its spending is released. If it fails on chain, only the fee it was charged still counts when the RPC can return that fee; when it cannot, the transaction’s full estimated SOL outflow stays counted.
Revoking
Section titled “Revoking”await automations.consent.revoke({ wallet }); // everythingawait automations.consent.revoke({ wallet, steps: ["buy"] }); // some stepsRevoking needs no wallet signature and takes effect before the next step signs, including steps already queued. Expose it only to the signed-in user (through your app’s own authentication), or anyone could stop someone else’s automations. A consent scoped to one instance also ends when that instance finishes.
Design the opt-in
Section titled “Design the opt-in”- Say what will happen in your product’s words. “We’ll refund you
automatically if this raise fails”, not “authorize step
refund”. - Show limits in units people read, such as “Up to 50 USDC per buy, at most 200 USDC in 30 days”. The message states base units; show the human amount next to it.
- Give automation its own screen and signature. Never pre-tick it or bundle it with sign-in or a first deposit.
- Ask for what the feature needs, and no more. Set an end date that fits it, such as the end of a raise.
- Make stopping easy. Put the off switch where users found the feature.
- Tell users what ran. Send a notification from your
onOutcomehook for every completed, refused and failed step, with the amount and a link to the transaction.refused(over a limit) andrejected(the protocol said no) are normal outcomes; say why. - Be honest about delegation. The consent bounds what your backend does. If your backend were compromised, the wallet provider’s policy is what still holds; see signers and safety.