The job
You want to fund an agent. You do not want to discover, after the fact, that it bought the same thing eleven times, paid a vendor that never delivered, or drained the wallet because a prompt told it to.
Today the only real control is the balance in the wallet. That is a blast radius, not a control. A funded wallet answers exactly one question: can this transaction clear?
| Question | A balance’s answer |
|---|---|
| Is this vendor one we trust? | — |
| Have we already bought this? | — |
| Is this within the per-call cap the human set? | — |
| Is this the eleventh identical call in a minute? | — |
| Did the thing we paid for actually arrive? | — |
| Who authorised this, and can they prove it? | — |
The hatched column is chart vocabulary for a region that is not available. A balance does not answer these badly. It cannot answer them at all.
Why the obvious fixes fail
“Just give it a small wallet”
A cap on total loss is not a control on behaviour. A $50 wallet still buys the same domain eleven times, still pays a vendor that never delivers, and still produces no record of who authorised what. It bounds the damage and explains nothing.
“Let the model check its own limits”
The model is the thing being defended against. Prompt injection, hallucinated tool arguments and runaway loops all originate inside the model. A check the model performs is a check the attacker controls. The decision has to sit somewhere the model cannot reach.
The mechanism
Five lines. If the flow cannot be drawn in five lines, the mechanism is not sharp enough.
- 01ProposeThe model or agent proposes a bounded SpendIntent. It can propose anything.
- 02DecideA pure function evaluates the intent against the policy. No I/O, no LLM, no network. It returns a verdict, the rules evaluated, and a proposal of what committing would change. It writes nothing itself.
- 03Allow, escalate or blockALLOW mints an exact approval digest. ESCALATE sends that digest to a human. BLOCK returns a named reason code and moves nothing.
- 04SignOnly an allowed decision, bound to one exact digest, is signed through a Dynamic wallet the user still owns.
- 05ReceiptDecision, payment, delivery and anchor, recorded as four separate facts.
The model is outside the ambit. It reaches the API and nothing further. No LLM call appears anywhere on the money decision path.
Wallet ownership
The wallet is the user’s Dynamic embedded wallet. Ambit holds a delegated signing share the user granted and can take back at any moment.
- Pattern
- Delegated access
- Owner
- the end user — not Ambit, and not a developer account
- Agent auth
- user-approved delegated credentials (
walletId,walletApiKey,keyShare), delivered to Ambit’s webhook and re-encrypted at rest - Revocation
- the user, unilaterally. Dynamic fires
wallet.delegation.revoked, Ambit deletes the credentials, and every later request returns403 DELEGATION_REVOKED - Allowance
- none. EIP-3009 authorisations are exact-amount and single-use.
approveis never called on any ERC-20, so there is no allowance for anyone to drain
- Client
- getWalletAccounts()
hasDelegatedAccess()
delegateWaasKeyShares()
revokeWaasDelegation() - Server
- createDelegatedEvmWalletClient()
delegatedSignTypedData()
delegatedSignMessage() - Webhook
- wallet.delegation.created
wallet.delegation.revoked
Eight call sites across four files, each signature read from the published type declarations of the pinned package versions rather than from documentation.
Stated honestly: Ambit is a custodial decision layer over a delegated wallet. It cannot move funds outside policy and it cannot move funds after revocation, but during an active delegation it holds a signing share. It is not trustless.
The evidence
An agent request that violates policy produces a named refusal and no payment. Both outcomes are provable — from a transaction hash, or from the absence of one.
No payment has been executed in this build. No Dynamic environment and no x402 facilitator are configured, so there is no hash to show — and an example hash here would be indistinguishable from a real one.
- DUPLICATE_INTENTthe same task twice inside the window
- PER_CALL_CAP_EXCEEDEDover the human's per-call limit
- RECIPIENT_DENIEDpayee is on the deny list
- DIGEST_MISMATCHthe terms changed after approval
- DELEGATION_REVOKEDthe user took the authority back
Each refusal names the rule that produced it. The explorer carries every case with its real outcome.
What is not claimed
Stated plainly, because a reviewer will find them anyway. Ambit does not claim an agent is safe to fund. It makes the decision to fund impossible to fake, records exactly how far the proof reaches, and refuses to say a word past it.
This is the band where a landing page usually puts logos and testimonials. There are no users yet, and inventing them would break the one thing this product argues for.
Set the ambit
Fifteen rules, evaluated in fixed order, before any money moves.