An agent that rebalances a treasury, buys a token for a game or moves USDC to the chain where a vendor gets paid needs to trade. The usual way to give it that power is a private key in an environment variable. A key has no notion of "trade": whatever can sign a swap can sign a transfer of the whole balance to an attacker. Once the key sits in an agent's context, one prompt injection is enough to lose it.
The fix is the same one that works for payments: keep the key out of the agent and give it a narrow, capped permission that the broker enforces.
The agent gets a permission, not a key
In Notlogin the human grants each agent a permission from the Swap page. It has five limits, and raising any of them needs a fresh sign-in:
- Budget: total USD volume of swaps and bridges in a rolling 24 hours.
- Per-trade cap: the largest single swap or bridge.
- Networks: for example Base and Solana only.
- Max slippage: up to 5%.
- Trades per 24 hours, plus whether the agent may bridge and the highest bridge fee it may pay.
The agent trades from its own Notlogin wallet. Its backend calls /api/x402/agent-swap or /api/x402/agent-bridge with a quote or execute action, and the broker signs. A refusal comes back as a code the agent can act on, such as budget_exceeded, slippage_too_high or network_not_allowed, instead of an on-chain surprise.
Output can only land in the same wallet
A cap on volume is not enough on its own. A hostile route can respect the amount and still send the proceeds somewhere else, take a hidden fee, or approve a spender for the whole balance. So every route is checked before it is signed:
- EVM (KyberSwap): the router must be on an allowlist, the calldata is decoded, and the receiver must be the wallet itself. There must be no fee receiver, the minimum return must honour the slippage limit, and the approval covers exactly the input amount. The transaction is simulated with
eth_callbefore it is sent. - Solana (Jupiter): the quote must match the mints, amount and slippage. The transaction must have a single signer. A simulation diffs the wallet and all its token accounts: only the input account may go down, the output must reach the quoted minimum, and no owner, delegate or close authority may change.
- Bridges (Across, Relay): the contract or program must be allowlisted, the recipient on the destination chain must be the same user's wallet, refunds may only go to the user's own wallets, and destination calls are refused. Any mismatch fails as
unsafe_bridgeand nothing is signed.
The worst a compromised agent can do is make bad trades inside its cap. It cannot withdraw: moving funds to an outside address needs the owner's own session, not the agent's token.
Retries never trade twice
Agents retry. Networks time out, processes crash, and a tool loop may send the same call twice. Every swap and bridge carries a clientRef chosen by the agent. A retry with the same one returns the stored result and never signs again. Bridges go further. The signed deposit is saved before it is broadcast, so a broker that dies mid-flight resumes from the chain instead of paying twice. A background reconciler follows each bridge until it is filled or refunded.
Bridging only when a buy needs it
Funds are rarely on the right chain. With auto-bridge on, a buy that is short on one network first bridges USDC, or a native coin if no network has enough USDC, from the user's best-funded chain into the same wallet. The fee is capped in basis points and by a monthly ceiling per user, and the provider's gas estimate counts toward it. The dashboard shows one balance across all chains, so the human sees what the agent can actually reach.
Vendors get mandates, humans get a swap page
The same engine serves three callers. Humans swap and bridge from their own wallet at /dashboard/swap, with a quote that shows expected and minimum output, price impact and network fee. Agents use permissions. A trading app that signs users in with Notlogin can request a trade mandate: a capped open exposure, a per-trade limit and an expiry the user approves once. All three use the same allowlists, decoding and simulation. Notlogin adds no fee; you pay only network and route fees.
Try it
Fund a wallet, open the Agents tab on the Swap page and grant a budget you would not mind losing. Point your agent at auth.md, which lists the calls and error codes. Create an account to start, or read the full API reference.