Shareable links that grant AI agents bounded, revocable spending authority — enforced on-chain.
ETHGlobal Tokyo 2026A link
that carries a
permission.
The limits aren’t in our code. They’re Move asserts on Sui — nineteen of them, on every single spend.
Sui · ENS · World ID ↓
The problem
How do you give an AI agent access to your funds without handing over your master keys?
Today you can’t. You get a valet who can drive anywhere — and a note on the dashboard asking nicely.
Instructions
- “Only spend $50 a day” — in a prompt
- An API key that does everything
- You find out afterwards
- Stopping it means rotating keys
A key that only fits one lock
- $50/day is a number in a Move object
- One pool, one destination, one month
- The 51st dollar never leaves
- Revoke in one transaction
We’ve got you covered — it isn’t a promise, it’s the shape of the key.
The idea
You write what an agent may do in plain English. You send a link. Whoever opens it proves they’re a human and plugs in whatever agent they like.
Write
“Sell 0.02 SUI a day for 30 days, max 1% slippage, send the proceeds to Bob.”
Send
A link, and a QR beside it. No wallet, no seed phrase, no gas for anyone.
Enforce
The limits aren’t in our code. They’re Move asserts on Sui.
19 asserts. Every single spend.
The moment
Anyone can demo an agent that spends. Here is one being refused.
sell 0.01 SUI
settled to the recipient
sell 5 SUI
nothing moved
route through another pool
nothing moved
keep the proceeds
refused before any coin moved
ask to exceed the limit
the agent can ask, it cannot approve
That’s a general-purpose AI we didn’t write, on someone else’s laptop. It tried. Sui said no.
What the chain actually holds
Vault
Holds the money. The agent never owns it, and never owns the coins inside.
Capsule
The permission. No store ability, so it cannot be transferred, sold or wrapped. Access is by field, not by ownership.
Permit
One-shot authority to exceed a soft cap. No drop ability — execute_elevated takes it by value and destroys it. Replay is unrepresentable.
ExecTicket
A hot potato with no abilities at all. Cannot be stored, copied, or discarded. Only settle can destroy it.
begin_execute → the coin AND the ticket
swap at any venue — we import no DEX
settle(ticket, proceeds) → checks the destination
A transaction holding that ticket is structurally incapable of finishing unless the money lands on the right address. The agent isn’t trusted not to skim — a transaction where it skims cannot be built.
Nineteen asserts, every spend
Who is asking
vault matches · claimed · holder == ctx.sender()
Is it alive
not revoked · not surrendered · not paused by either party · within its dates
Recurrence
windows not exhausted
Soft caps
amount > 0 · per-action · per-window
Hard caps
hard cap · total cap
Scope
pool by object id · slippage · beneficiary fixed at mint
Plus one in settle — the fill must beat the floor the agent committed to — and three more on the permit path.
An approved escalation lifts the soft caps and only those. Nothing lifts the hard cap — not a permit, not the issuer at 3am, not a compromised backend. That ceiling was set once, at mint, by someone thinking clearly.
Who it’s for
Set it up for Mum
She gets a link, not a wallet. Signs in with Google, an agent handles her savings, and she can hand it back any time. You funded it and can revoke it — she never touches a seed phrase.
A strategy you don’t babysit
Give your own agent 30 days and a daily budget. It trades while you sleep, inside limits you set once, while awake.
Any agent platform
Bring the permission to the agent instead of the agent to the money. It plugs into what you already use.
Teams, allowances, payroll, subscriptions
Anywhere one party funds and another spends — with a ceiling, a clock, and a revoke button.
The primitive is delegated, bounded, revocable authority. Trading is just the demo.
Bring your own agent
Every permission is also an MCP server. Paste one line into Claude Desktop or Cursor, restart, and that assistant holds a spending authority it cannot exceed.
{
"mcpServers": {
"intentlink": { "type": "http", "url": "https://…/api/mcp/ilk_…" }
}
}Tools built from the capsule
get_permission · quote · execute · request_escalation · get_history
It cannot see an action outside its scope. That part is convenience.
The chain doesn’t care what it read
Ignore every description, ask for ten times the cap, and you get an abort code. That part is the guarantee.
Backed by a human
An agent can ask to exceed its limit. It can never approve.
approve_escalation asserts ctx.sender() == capsule.issuer
Plus a fresh World ID proof, signal-bound to hash(capsule, amount, nonce) — so a stored credential can’t be replayed, and a yes to 26 can’t be stretched into a yes to 260.
Every other approval mechanism is a bearer token. A bearer token can be handed to the agent you’re trying to constrain. A live human cannot.
Our own backend used to be able to mint that approval. We deleted the path.
Three chains, three jobs
Enforces it
19 asserts between any agent and the funds, on every spend. An ExecTicket hot potato with no abilities at all — the transaction is structurally incapable of finishing unless the proceeds land on the right address.
Not checked afterwards. Unrepresentable.
Publishes it
A subname per capability under intentlink.eth, issued through an ENSv2 PermissionedRegistry. Its records carry a hash of the terms — the same hash that sits inside the Sui object.
The agent halts if the two chains disagree.
Vouches for it
A live human redeems the link. And the agent cannot approve its own escalation, because it cannot be a person.
The one thing no credential can substitute for.
Ethereum names the permission. Sui refuses to break it. World proves a person is behind it.
Anyone can build
an agent that spends.
We built the part that says no.
intentlink.eth · Sui testnet · World ID v4