intent.standard. This page explains each standard and what the owner agrees to. You only need it to debug a wallet integration or explain a prompt to owners: Owner Signing has the frontend code.
At a glance
- NEAR owners:
nep366(a delegate action the API relays on-chain) ornep413(a signed message). - EVM owners:
eip712typed data, shown field by field in the wallet. - Passkey owners:
webauthn, a Face ID, fingerprint or PIN prompt. - One rule: the wallet signs
intent.payloadexactly as returned. You never build these messages yourself.
Two kinds of owner requests
Every owner intent is one of two kinds. The kind decides the standard.Wallet requests (on-chain)
agent_create, agent_freeze, agent_unfreeze, agent_delete, and a policy_update that changes the wallet’s rules (actions, assets, limits, approval, max_actions_per_hour).The owner signs a NEAR call that the API sends to the chain and pays gas for. It installs, changes or deletes the policy the agent’s wallet enforces. Window: 600 s.Consent messages (off-chain)
Every other intent:
grant_issue, grant_revoke, execution_cancel, agent_archive, agent_restore, approval_vote, and a policy_update that changes only destinations, budget, timelock_ms or schedule.The owner signs a message that the Agent API checks. Nothing is sent to the chain, so there’s no gas. Window: about 290 s (passkey about 270 s).
For a
policy_update, the API decides which kind it is from what changed. A NEAR owner can get either nep366 or nep413, so choose the wallet call from intent.standard.
Rules for every standard
- Sign the payload as it is. Don’t rebuild, hash, reorder or re-encode it. The API compares what comes back with what it sent, and refuses any difference with
intent_payload_mismatch. - Sign with the owner’s key. A NEAR owner’s key must be a full-access key. A signature from any other key fails with
signer_mismatch(signed messages and passkeys),policy_delegate_owner_mismatch(NEAR delegate actions),owner_key_not_full_access(the key isn’t full access), or a signature error such asowner_proof_invalid. Owner Signing shows which flow gives which. - Use the standard you were given. Signing with another one fails with
intent_standard_mismatch. - Sign before
expires_at. Every intent fromgenerate-intenthas a deadline: about 290 s for consent messages (about 270 s for passkeys), 600 s for wallet requests. After it, you getintent_expired: generate a new one. Timestamps the API stamps into EVM and passkey messages are set 30 s in the past, to absorb clock skew between servers and devices. - Each intent works once. A nonce can’t be reused. Submitting the same signature again is safe and returns the same result.
- Encodings. The API accepts NEAR signatures as base58, base64 or hex, and normalizes EVM recovery IDs and WebAuthn DER signatures.
NEAR owners
NEP-366: delegate action (wallet requests)
NEP-366: delegate action (wallet requests)
The owner signs a NEAR transaction without sending it. The API, as the relayer, sends it and pays the gas (NEP-366). Window: 600 s. The owner’s key must still be able to execute the delegate when it is relayed, or you get
policy_delegate_expired.intent.payload has receiverId and a list of one or two actions. Each action is a FunctionCall with params: methodName, args, gas and deposit. The wallet signs it with signDelegateActions, and you return the result as signed_delegate.The delegate is signed by the owner’s account and key from agent_create, so the policy change is made by the owner’s own account. Another account or key is refused with policy_delegate_owner_mismatch. For agent_delete, the single action is the wallet’s delete_wallet_policy call. For a policy update, the arguments include a hash of the complete policy, so the signature covers every rule, including the ones the API enforces itself (destinations, budget, timelock_ms, schedule).NEP-413: signed message (consent messages)
NEP-413: signed message (consent messages)
The owner signs a text message that can’t be used as a transaction (NEP-413).
intent.payload has:message: a JSON object as text, with the agent, the action and its detailsrecipient: who the message is for (the API’s hostname)nonce: 32 random bytes, base64-encoded. Decode it to bytes before you pass it to the wallet.
signMessage, and you return public_key and signature. The key must be the owner’s full-access key from agent_create, or you get signer_mismatch or owner_key_not_full_access.Window: about 290 s. For an approval_vote, message is the short vote string described below and recipient is the wallet provider’s contract instead of the API’s hostname.EVM owners
EVM owners sign EIP-712 typed data, so the wallet shows the owner every field before they sign. Both message types use the same domain:chainId, so the owner can sign on any EVM network their wallet is connected to.
WalletMessage (wallet requests)
WalletMessage (wallet requests)
A request for the owner’s
0s account on NEAR. The account checks the owner’s signature and runs the request. See Owner Accounts.eth_signTypedData_v4, for example walletClient.signTypedData in viem. Return the 65-byte signature, 0x-prefixed, as signature. The API checks that it comes from the owner’s public_key.
Passkey owners
Passkey owners sign with WebAuthn, the standard behind Face ID, Touch ID and security keys.intent.payload is a ready-to-use request for the browser:
Pass it to
navigator.credentials.get, or to startAuthentication in @simplewebauthn/browser, and return the result as credential.
What the challenge is a hash of depends on the kind of request:
Wallet requests: NEP-616 wallet request
Wallet requests: NEP-616 wallet request
The challenge is the SHA3-256 hash of a wallet request for the owner’s
0s account: the NEAR network, the account, a one-time nonce, a validity window and the NEAR calls to make. The account checks the passkey signature and runs the request.The window is 600 s from a creation time set 30 s in the past, so about 570 s remain.Consent messages: NEP-641 off-chain message
Consent messages: NEP-641 off-chain message
The challenge is the SHA3-256 hash of an off-chain message (NEP-641) signed for the owner’s
0s account. It contains the same JSON as the NEAR and EVM consent messages, plus a timestamp.The message is stamped 30 s in the past and valid for 300 s, so the owner has about 270 s. Ask the owner to sign right away. If the window passes, generate a new intent.What a consent message says
Consent messages are canonical JSON, the same for every owner type, exceptapproval_vote (below). They name the owner, the tenant and the agent, and carry a single-use nonce and a deadline. The rest depends on the intent:
agent_delete is not a consent message. It is a wallet request: the owner signs the agent wallet’s delete_wallet_policy call as a nep366 delegate action, an EIP-712 WalletMessage or a WebAuthn assertion over the wallet request hash. preview.deletion shows what would be lost. See Deleting an agent.
Show preview next to the wallet prompt so the owner sees this in plain language.