A human signs what an agent may do: which contracts, which selectors, how much per transaction, where the output may land, and until when. In the demo, UNTOLL enforces that on chain, in the bytecode of the agent's own account, where a jailbroken model cannot reach it.
A rule held in the software that asks for the transaction is advisory the moment the key leaves that process. In the demo, UNTOLL's rule is bytecode on the path the funds take: which targets, which selectors, how much per transaction and per epoch, which argument the output may land in, and until when.
A stolen key reaches the same contract and meets the same rule.
Nothing. The scope installs as an EIP-7702 delegate on the EOA the agent already runs on. No Safe, no smart account to move to, no bundler, no EntryPoint, no paymaster, and the delegate itself is the policy container rather than a doorway into one.
The agent keeps its address, its history and its integrations.
Recipient policy is stored as a set, keyed by selector and by ABI argument index, so
one installed scope covers every destination you named rather than one grant per address. And a
refusal leaves a record: tryExecute emits a typed ScopeViolation carrying
the target, the selector and the reason, so what an agent tried and was refused reads back on chain
alongside what it did.
The containment run gives an agent a scoped key and a balance on a local chain, then has it try to escape five different ways. Every attempt is refused on chain, and the refusal is a decode anyone can reproduce.
RecipientNotAllowed before anything moves.Every figure on this page is reproducible from the repo with one command. The run starts a local chain, deploys the real delegate and checks the reverts on your own machine, with keys generated per run and never funded. The contracts it mirrors are deployed and source-verified on public testnet 46630.
There is no migration. Keep the wallet SDK, the agent framework and the signer you already chose. UNTOLL sits underneath them, at the point of settlement, and the adapter is the whole integration.
Scope-native accounts map one to one. The rule installs account-side, on the EOA the agent already has, under an EIP-7702 delegation.
One action provider, and an agent acquires a bounded key and operates under it without touching your prompt logic.
A signed permission or mandate says how much and to whom. This is the on-chain, revocable enforcement of exactly that shape.
Routing to a hook-enabled pool is permissionless, so nobody has to grant access for this to work.
Those are the hook contracts.
SessionKeyDelegate, the contract that carries the agent scope, runs on the local chain
the demo starts, with a real EIP-7702 delegation and real reverts, and has no address
on 46630.