A gate between your AI agent and your money.
A NEAR smart contract holds the money you set aside for your agent. It pays only for jobs you signed. Any other request is refused: nothing is paid, and the reason is recorded on-chain.
Watch the 96-second demoIllustration. The top lane shows the general risk of giving an agent a wallet key.
How the gate decides
An AI agent wants to spend your money. Nothing is stamped yet, so the gate refuses.
You stamp (sign) each job it may pay for: recipient, maximum amount, exact instruction.
The agent asks for exactly that job, within your limit: paid.
A different instruction, a fake owner, or a higher amount: refused, and recorded.
Above the review amount you set, a payment waits for your approval.
Not signed with the stamp key
No jobs stamped yet
-
To translator.testnetUp to 0.01 NEAR
"Pay for chapter 3 translation"
Signed with the stamp key
OWNER Used -
To designer.testnetUp to 0.1 NEAR
"Pay for the cover design"
Signed with the stamp key
OWNER Used
Nothing waiting for approval
Approve this payment?
0.08 NEAR → designer.testnet
59:12 left
No records yet
- Refused0 NEARunknown_mandate
- Paid0.01 NEARallowed
- Refused0 NEARunsigned_instruction
- Refused0 NEARowner_impersonation
- Refused0 NEARentry_limit_exceeded
-
Held0.08 NEARtier2_escalateApproved0.08 NEARpayout_settled
-
1
An AI agent wants to spend your money. Nothing is stamped yet, so the gate refuses.
- Refused0 NEARunknown_mandate
-
2
You stamp (sign) each job it may pay for: recipient, maximum amount, exact instruction.
-
3
The agent asks for exactly that job, within your limit: paid.
- Paid0.01 NEARallowed
-
4
A different instruction, a fake owner, or a higher amount: refused, and recorded.
- Refused0 NEARunsigned_instruction
- Refused0 NEARowner_impersonation
- Refused0 NEARentry_limit_exceeded
-
5
Above the review amount you set, a payment waits for your approval.
- Held0.08 NEARtier2_escalate
- Approved0.08 NEARpayout_settled
Illustration. Accounts and amounts are examples.
Where to start
It sends four preset requests to one test gate from your testnet wallet. Each attaches 0 NEAR and costs a little testnet gas.
Every payment request ends in one of three ways
-
Paid
Testnet NEAR leaves the gate only for a stamped job.
-
Held
Above your review amount, the payment waits for your approval. After the deadline (one hour at most) it can no longer be approved, and nothing is paid.
-
Refused
Nothing is paid. The transaction itself goes through and stores a reason code on-chain, so anyone can check what the agent tried.
Up to three checks, in order
-
1
Contract rules
Stamped jobs, limits and budgets are checked on-chain.
-
2
Judge model (optional)
An optional second check: a judge model reviews the request before payment. Used live in testnet Run B (see Proof).
-
3
Your approval
Payments above your review amount wait for you.
On testnet now
- 10scene transactions on the proof page. Anyone can re-read them from a public archival NEAR RPC node.
- 0 NEARpaid on the refused requests among them
- 4attack requests you can send yourself from a testnet wallet
Limits
- Testnet prototype. Not audited.
- Not deployed on mainnet. No real funds.
- The stamp key (the key you sign jobs with) cannot be changed later. Back it up before you deposit.
- Anyone who knows a mandate serial can freeze it with the same refused request from the same account twice in a row (with no passing request in between), or three mandate-check refusals in a row. Nothing is paid, a new mandate recovers use, and that mandate can be frozen again. The refusal count goes back to 0 only when a request passes the mandate checks with an amount above 0 and the transaction does not fail, whatever follows: a payment, a new hold, a spend-rule refusal (tier2_deny), or an allowed request that pays nothing (an authorize call or an action other than a transfer). A zero-amount request leaves the count unchanged. Approving or rejecting a hold later does not change it.
- Anyone can grow the gate's storage with refused requests that carry long strings: in the sandbox, 3 requests grew storage by 63,758 bytes, and a full escrow withdrawal then failed with LackBalanceForState, about 0.028 NEAR short. A plain NEAR transfer (not Deposit) of the shortfall fixes it. There is no per-mandate storage cap in the contract (a 4th call on an already frozen mandate added 0 bytes in that run), and the fix is designed, not deployed.
If you lose the stamp key you cannot take the escrow out. It is stored in this browser without encryption.