Skip to main content
In short: you can let an AI agent or a bot trade for you without handing it your private key or seed phrase. Your money sits in an account that only your own wallet controls. The agent gets a narrow permission: it can run operations from an approved list, it cannot send money to an address of its own, and it cannot make itself the owner. If it is tricked, or the agent’s signing key is stolen, taking money out is still something only your wallet can do. It can still make a bad trade inside those limits, and nothing caps how much it moves unless you set a daily limit. This page says exactly where the limits are. You can switch the agent off from your own wallet at any time. We never hold your money, and you can take it out without us. This page works both of those out in detail, including the parts that are not finished.
You, your account, and our side: your wallet can do anything and take everything out; our side is an agent key in a hardware enclave, an agent contract and a fee payer, none of which can hold a token, and reaches the account through one approved call.

Two keys and one contract reach your account. Only your own key is an authority over it.

We never hold your money

Your account belongs to you outright. The address you are given is your deposit address, so money landing there is under your control before we do anything with it.

You can leave without us

You can take everything out with your own wallet, without our help, without our servers running, and without our permission. There is no contract above you and no override for us to use.
Two other keys touch your account, and neither can hold a token. One is the agent, which approves what your strategy does and can do nothing else. Its signing key lives inside a hardware enclave, described on the enclave page. The other pays network fees and has authority over nothing. Neither was ever given your key.

The standards underneath, named

The mechanism this page describes has a name. It is what makes an agent possible without giving anyone your key. Your operating address is an ERC-4337 smart account (account abstraction). An ordinary wallet is an address controlled by one private key, and every transaction has to be signed by that key. A smart account is a contract, so its code sets the rules about who may do what. Three properties follow from that, and all of them appear later on this page:
You do not need to understand any of this to use it, and nothing on this page depends on you knowing the numbers. They are here because “the agent cannot hold your money” is a claim, and the standard is where the claim is enforced.
Someone paying gas on your behalf is also part of the same standard. A transaction is submitted as a user operation and a separate party can pay for it. That is why you never hold the native coin of a network you have not used.

Where your money actually sits

“We never hold your money” means we hold no key to the address it sits at. It does not mean the money stays in the wallet you already use. For a workflow to spend anything, the money has to be reachable by your operating address, the account this page is about. There are two ways to arrange that, and you choose: Approving moves no money. The tokens stay where they are and the account gains permission to draw them, which you can revoke in your own wallet like any other allowance.

What you are actually trusting

The operating address is not the wallet you already use. It is a smart account whose address is derived from your own, and moving funds into it is a real step. Here is what changes and what does not:
  • Ownership does not change. You are the root owner. You can empty it at any time with your own wallet, without our help and without our servers running. We cannot move anything out of it, and we cannot stop you moving it.
  • The address changes. Your money is no longer in the wallet you watch every day. It is one address further along, and that address is a contract.
  • So the code matters. A smart account is code, and code can be wrong. The agent has no raw call at all, so the code that matters most is the fixed set of operations it can reach. The rest of this page sets out exactly where that leaves you.
If you would rather not move funds at all until a run needs them, use the approve route. The money stays in your wallet, and the account draws it one step at a time.

If our side is compromised

Three things on our side can be attacked: our servers, the agent’s signing key, and the fee payer’s key. Each is bounded differently.

If our servers are taken over

Someone who controls our servers can ask the enclave for signatures. The enclave judges every request against a policy fixed inside its measured code. It signs only a step that:
  • targets an approved operation, at one of that operation’s entry points;
  • pays your account or your own wallet and nobody else;
  • belongs to one owner per batch, with a valid receipt for each step;
  • expires within one hour;
  • passes a price check against the market, for swaps and liquidity steps.
So an attacker cannot make it sign a payment to an address of their own. The full list is on the enclave page, including what it does not check.
What the enclave does not stop. It does not cap how much one step moves, and it does not yet require proof that you asked for a run. Your approvals are recorded and checked, but a run without one still gets signed. An attacker could move your money between positions, or trade it at up to 3% off the market price per step. Only the daily limit below bounds the total.

If the agent’s signing key leaks

The key is created inside the enclave and never leaves it, so a leak is not an expected failure. If it happened anyway, the key alone reaches your account through the agent contract, and the agent contract refuses anything but an approved operation. It will not target your account directly, will not run the instructions that install permissions or change your account’s owner, and will not touch an operation the guardian never approved or that you never switched on. Whoever holds it also cannot choose where money goes. Destinations point to your own account or your own wallet, looked up when the step runs, so there is no field to put an attacker’s address in. Three limits bound it on the network itself:
  • A daily limit per token, which you set. It is off until you set it. See Your daily limit below.
  • A loan ceiling. No loan may end above 80% of its collateral’s value. You can tighten that for your account and never loosen it.
  • A kill switch. The agent can be revoked on a whole network in one transaction, and you can stand it down for your own account from your own wallet. See Emergency stops.

If the fee-payer key is stolen

It can waste fees, refuse to send transactions, and send transactions of its own. It cannot touch your assets, because it was never an authority over them.

The worst case

Your account stays yours. The agent can never become the owner or hand the account away, and it has no field to name a destination in, so nothing on our side can send what your account holds to an address of its own. Taking value out is something only your own key can do, and that does not change in the worst case. What can go wrong is where the value sits and at what price. A step could leave it in the wrong position or the wrong asset, or sell it at a poor price. The enclave allows up to 3% below its price source. A token it cannot price, or a leaked key used outside it, gets no price check at all. Unwinding that is your work, and we cannot do it for you. It is a mess to sort out, but you still own the account and the value can still be moved.

Your daily limit

You can cap how much of each token the agent moves per day. The limit is checked on the network, per token, over a fixed 24-hour window. Only your wallet can set it, and the agent cannot raise it.
The limit is off by default. A token with no limit is uncapped. A limit on USDC does not cap WETH, so set one for every token you hold. The app has no screen for it yet. Today you set it with a transaction that your wallet sends through your account. Raising a limit mid-day does not refund what was already spent that day.
Pulling money from your own wallet has a separate daily limit. It controls how fast the agent can draw on an allowance you granted.

Leaving without us

There is a tool that reads who is allowed to drive your account and what it holds, then builds the transactions that empty it to an address you name. It shows them to you before it sends anything, and only sends them if you ask. It uses no fee payer, no agent and none of the approved operations. Every one of those is something that could be broken on the day you need to leave.
Proven on a frozen copy of a real network: an account holding ether and WETH was emptied to a fresh address in a single transaction from the owner. The same worked on an account whose agent had no permissions installed at all.
Two things a sweep does not do.
  • It moves balances. It does not unwind a loan, does not move a liquidity position, and cannot move what has not arrived yet. Unwind first, or the debt outlives the exit. The tool says all of this in its own output. The risk is an owner who believes they have left while a leveraged position is still running behind them.
  • If you asked the console to create an address for you, nobody holds its key, including us. The key was generated, the address kept, and the key itself discarded. The agent can still work through the address, and nothing else can. Connect a wallet you control and prove it on the Accounts page. Until you do, the contract has a way out, but you cannot use it.
We hold no override. The same property that lets you leave without us means we cannot stop you, or anyone holding your key. If your key is stolen, the account is gone and we cannot recover it.

Who holds what

Two keys and one contract touch the account. Only one of them is an authority over your money.
The agent is a contract, not a key: the registry refuses to let an account make a plain key its agent.

You, the owner

You may do everything. One direct transaction is enough, with nothing else involved. You may call any contract, replace your account’s code, add or remove permissions, hand the account to somebody else, or cancel every permission. Nothing may overrule you. There is no control above you and there is not meant to be. That is what “you can leave without our cooperation” means, and the contract enforces it.

The agent is a contract, and the key only drives it

The agent is a contract, and your account gives it permission. A plain key cannot get that permission: the registry refuses one. Your account also installs no validator for it, so the agent has no way to run a raw instruction on your account or to sign for it. Behind it sits an agent signing key, which is ours. Only that key may drive the agent contract, and driving it is all the key can do. Whoever holds the key cannot reach your account except through the agent, and the agent has one function: call an approved operation. The agent may not own your account, add or remove permissions, hand the account away, replace its code, or call your account directly. It rejects all of that itself, on the network, before anything else happens. These checks run on every call, in the agent contract: Then the operation itself re-derives who owns the account, refuses a step you switched off, and checks its daily limit and loan ceiling, rather than believing what it was told.
Your account can never be re-pointed at a different agent. The first agent you approve is fixed. After that the only permitted changes are standing it down to nothing and coming back to that same agent. An attacker who could make your account approve an agent cannot swap ours for theirs. Standing down is one transaction from your own wallet and takes effect on the next call.
Revoking an agent for everyone is permanent for those accounts. If we revoke the agent contract on a network, every account that approved it can never automate again at that address. Nothing is stuck: you can still spend, withdraw and uninstall with your own key. We keep revocation for an agent that must never run again, and fix bugs by upgrading the contract instead.

The fee payer: pays, and authorises nothing

It builds the transaction from labelled fields and is never handed a ready-made instruction. The agent says “send 100 USDC on Base”. The build step looks up the contract address from trusted configuration and encodes the transfer. There is no input to that function capable of expressing an arbitrary call, and there must never be one. It holds nothing but fees. Everything that moves value moves it through your account, so the fee payer is the sender of the outer envelope only. Measured against a long-running frozen copy after many runs: none of the assets this system deals in, no standing permission at any venue, and enough of the network’s own currency to pay fees. Its key is held in a cloud key service that signs only from our production servers’ address and never releases the key.
The remaining risk with the fee payer is its key. A stolen fee-payer key can burn fees, refuse to send, and sign transactions of its own. It cannot spend your assets.

How your account is owned

The kind of wallet you connect decides how your account is owned, and the kind is part of the address. The console reads the wallet and picks the matching setup. You do not choose it from a menu.
The kind cannot change afterwards. It is baked into your account’s address, so it is fixed the moment the address is worked out. There is no migration: a different kind of wallet is a different account at a different address.
A separate passkey approves runs when you press Start. It does not sign you in, and it is not an owner of the account. See Approving with a passkey.

Proved accounts

New accounts are proved accounts. They fix a list of what the agent may ever do, and the network checks a proof of every plan against that list. Older accounts keep the older kind, and Ethereum runs both kinds the older way. Read Proved accounts for what that changes and what it does not.

What bounds the agent today

An earlier design put a guard in front of the agent that banned a list of actions. Four attacks got past it on a copy of the real network, because a ban list is always incomplete. All four used a raw call on your account. The agent no longer has any raw call, so the guard had nothing left to filter, and it was removed. Those four attacks no longer apply, because the path they used is gone. What replaced it is a smaller door. The agent has no way to run a raw call on your account. It reaches your account only through a fixed set of operations, and each one takes labelled fields, never a target and never an instruction. That closes the takeover and the arbitrary call. It does not close everything:
What protects you today. The destination is always your account or your own wallet. The set of operations is approved by a guardian and waits three days before a new one works. A daily limit and a loan ceiling are yours to set. The enclave checks every request before it signs, and you can revoke the agent from your own wallet.

Under the hood

For integrators. Not needed to use the product.

”Root” does not mean what it sounds like

The rest of the model follows from this finding. The account’s own execute function is guarded by a modifier that admits the industry-standard entry point, the account itself, or “root”. The account performs no ownership check of its own. For any other caller it asks the root module “are you also a guard?” and, if so, hands the entire decision to that module. So “root” means whoever the root module admits. With the standard validator as root, that check is one line: the sender must equal the stored owner. It checks nothing about the target, the action, or the value. Two things follow, and the second is the dangerous one.
  1. The owner can call execute directly, with no helper service, and reach any contract.
  2. Swapping the root module silently changes who may call execute, replace the code, and add permissions directly. A module that is not also a guard returns false. The third-party branch then fails, and nobody can call execute directly.
New accounts use a root validator that refuses to install a second validator, so the owner cannot add one by accident. A root also cannot be de-registered while it is the account’s root.

Why the agent is never a validator

A validator for the agent’s key would let a token contract ask the account to vouch for a signature, and the account would route that to the agent’s key. That is a known drain: it moves tokens with no execute hook ever firing. So the agent has no validator, and no setting can give it one. The agent contract also refuses to be an ERC-7579 validator or hook, and answers every signature check as invalid.

What every operation must force, by construction

The security claim is that the network itself constrains the agent. Our signer authorising only a fixed set of actions is not enough on its own. That claim holds only if each operation independently forces the owner binding and the destination. One operation with a settable recipient lets funds be drained again, and the failure shows up late, as a valid signature and a misdirected transfer.
  1. Every state-changing entry point goes through the one path that binds the owner and blocks replay and expiry.
  2. The owner is read from the account, never taken from the request. A valid agent authorisation is not proof the right account was meant.
  3. The recipient is forced to the account. Never taken from the request. Where a venue hides the recipient inside an opaque hash, the operation rebuilds the hash forcing the receiver, and never accepts a pre-built one.
  4. No destination or raw instruction from the request, anywhere.
  5. Venue by name from the approved list, the daily limit if you set one, and the operation on the allow-list. A request naming a venue address would be an arbitrary call.
  6. Permissions cleared inside the transaction, or a bounded standing permission justified in the file header.
  7. Output measured by the change in balance, never taken from what the venue claims, wherever a venue could lie.
Prove the recipient is forced with a mutation test: point it at an attacker and watch the security assertion fail. Without that test, nothing shows the control works.

Designed versus built