The agent should not own the keys
The pitch is seductive: an AI agent that watches the mempool, spots a favorable swap, and executes before you finish reading the headline. Speed, leverage, autonomy. Every crypto-AI demo ends the same way — the agent clicks “Confirm” and the room applauds.
Nobody shows the next five minutes. The drained wallet. The contract interaction the agent wasn’t supposed to see. The signing key that said yes to everything.
The problem isn’t autonomy. It’s autonomy with no boundaries.
Permission scoping: the agent should not own the keys
A human wallet holder can reason about a weird contract call. An agent cannot. It sees a prompt, matches it to a tool, and signs. That is the entire reasoning loop. OWASP’s LLM06 on excessive agency flags this exact pattern: when an agent’s permissions are broader than its ability to evaluate consequences, the system is brittle by design.
The fix is boring but necessary. The agent does not hold the private key. It holds a scoped signing session — a pre-authorized set of actions, contract addresses, and value ranges. The wallet layer enforces the scope, not the agent. If the agent hallucinates a call to a contract not on the allowlist, the signing layer simply refuses. No exceptions, no override from the LLM.
This is not a technical debate. It is an architectural decision. Either the signing boundary lives in the agent’s memory, where it can be rewritten, or it lives in the wallet layer, where it cannot.
Spending limits: a hard ceiling is not a suggestion
The first thing a production agent should do is hit a cap. Not a soft warning. A hard stop.
A per-transaction limit is table stakes. 0.1 ETH, 500 USDC, whatever the use case justifies. The harder problem is cumulative limits — what happens when the agent executes fifty small transactions that each look harmless but sum to a drain. The agent’s session should carry a total spend ceiling that decrements with every signed transaction and does not reset until a human reauthorizes the session.
A transaction boundary looks like this: a cap per transaction, a ceiling for the whole session, and an allowlist of contracts the agent may touch at all. Anything outside those bounds requires a human countersign. The agent does not negotiate. It waits.
Simulation layers: dry-run before broadcast
A transaction boundary is only useful if the system knows what the transaction does before it signs. That means a simulation step — a dry-run against a forked chain state — that evaluates the outcome before the agent commits.
The simulation checks: does this contract call transfer value to an unapproved address? Does it approve an infinite allowance? Does it interact with a contract that was deployed three hours ago? If any check fails, the transaction is dropped and the failure is logged. The agent never sees the signing prompt.
This is not a performance hit. It is a safety gate. The simulation runs in milliseconds. The cost of skipping it is the entire wallet.
Audit logs: immutable trails for post-hoc review
Every signed transaction, every failed simulation, every permission denial — written to an immutable log that the agent cannot modify. This is not for the agent. It is for the human who wakes up to a drained wallet and needs to know exactly where the boundary failed.
The log records: the prompt that triggered the action, the tool call, the simulation result, the signing decision, and the on-chain hash. If the agent was compromised, the log shows the moment of compromise. If the boundary held, the log shows what stopped it.
The boundary framework
A production-ready crypto-AI agent needs four layers, in order:
- Permission scope — a signing session that the wallet enforces, not the agent
- Spending limits — hard per-transaction and cumulative ceilings that require human reauthorization
- Simulation — a dry-run against forked state before any signing prompt
- Audit log — an immutable record of every action and decision
Any agent that ships without these four layers is not autonomous. It is a loaded weapon with a prompt interface.
The market will figure this out eventually. The question is whether the first production failure teaches the lesson or the first production design does.