Custody and the agent key
What a stolen agent key reaches, what stops it, and why key compromise is not a slashable auditor fault.
This is what is deployed
The v2 contracts are live on testnet and are what every address on this site now points at. Where a page outside this section still describes v1 behaviour, the two differ and this section is the current one.
Before the router, an agent key is an ordinary Stellar account key: steal it and you drain that account. With the router, the agent transacts in routed USDC held in the router's custody and metered per certificate — so stealing the key also reaches the operating float. That is a real increase in what a single compromised key is worth, and it is why the threat model was made a precondition of shipping custody rather than a follow-up to it.
The mitigation is not that theft becomes impossible. It is that the reachable amount is bounded, visible and stoppable.
What a stolen key reaches, and what it does not
A thief holding the agent key can move the agent's routed balance to any destination, and every transfer they make meters against the certificate like any other — so they can push the spend counter past the bound.
They cannot reach the reserve: depositing and withdrawing it authenticate the certificate's operator, read from the registry, and the agent key is not the operator key. They cannot reach the auditor's stake, which only a settled challenge moves. They cannot reach another certificate's float, because balances, caps and halts are keyed by certificate. They cannot invalidate or re-point the certificate. And they cannot clear the kill switch.
There is no payee allowlist, on purpose. It is the obvious mitigation and it is rejected: an agent that can only pay a fixed set of addresses is not an autonomous agent, and the operator maintaining that list becomes a trusted party in every transaction — which is what the protocol exists to remove. The float cap bounds the same loss without constraining who the agent may deal with.
The float cap
Each certificate has a maximum float the router will hold for it, named when the first agent enrols and adjustable afterwards by the operator. A deposit that would push the certificate's float above the cap is refused, so an operator cannot raise the ceiling by topping up, and lowering the cap does not claw back float already held — it only refuses further deposits.
Two limits worth stating plainly.
Inbound payments are not cap-checked. The cap is enforced on deposits only. A tracked agent that is paid can end up holding more than the cap, because refusing an inbound payment would make an honest agent unable to be paid, and inbound value is not something a stolen key can conjure. The cap therefore bounds what the operator commits, not the maximum the agent can ever hold.
The cap is not on the certificate. The design calls for it to be set at publish and visible in the certificate and in the SDK's view of it, which was half the point of having one: a counterparty should be able to see the maximum exposure before trusting the agent. As built it lives on the router only, because putting it on the certificate is a storage change to the certificate itself. Until it moves, a counterparty must read the router.
The kill switch, and clawback
Halting is the first step in a compromise response, and deliberately so. It requires no challenge, no proof, no counterparty and no auditor. Any response that depended on the challenge system would be too slow to matter and would put a compromise on the same clock as a dispute. Halt and resume both authenticate the operator, so a thief holding the agent key cannot re-enable routing after the operator halts it.
The halt gates payments, burns and withdrawals. Withdrawal has to be gated, or a thief simply withdraws the float and the kill switch is decorative. But that gate is symmetric: it also stops the honest operator recovering their own money, and the only way out was to resume — which re-arms the thief. The operator was made to choose between losing the money and handing it back to the attacker.
Clawback is the third door. It is operator-only, works only while the certificate is halted, and sweeps one named enrolled agent's whole router balance to the certificate's registered operator. The destination is not a parameter. It performs no resume, so recovering the money and re-opening the certificate stay two separate acts. It is a purely internal balance move — no USDC leaves custody, the meter is deliberately not advanced — and sweeping an empty balance returns zero rather than panicking, so an incident-response retry does not fail loudly.
It is not timelocked, deliberately. A timelock would be a delay handed to the attacker: the halt-and-claw pair only works if response is faster than the thief, and a day's delay gives an attacker who already holds the key a day to find any exit the halt did not close. The usual reason to timelock a privileged sweep — giving depositors time to exit ahead of an abusive admin — does not apply here, because there are no third-party depositors on that balance.
The residue of that, stated rather than hidden: an operator can sweep their own agent's float at will. Nothing stops an operator halting their own certificate and clawing the float back the same second. It is acceptable for one reason only — it grants no authority over anyone else's money. The agent's routed balance is capital the operator deposited under a cap the operator set, and the operator could already reach all of it by halting and then withdrawing after a resume. Clawback removes the requirement to re-arm the thief on the way out; it does not widen who can be reached. An agent is not a custodian and must never be treated as one. Anyone extending the router so a third party can hold a balance under an enrolled agent's certificate has to revisit clawback first, because that person's money would be inside the sweep.
One more sharp edge: clawback sweeps one named agent per call, and the router keeps no index from a certificate to its agents. A compromise of two keys is two calls, and an operator who has lost track of which addresses they enrolled will not be rescued by this function.
Who bears the loss
This is the part that must not be got wrong.
A compromised agent key is not a slashable auditor fault.
The auditor attests that capital is committed and that the operator's process is sound. They do not attest to the operator's key hygiene, they cannot observe it, and they cannot price it. An auditor who can be slashed for an operator losing a key is underwriting a risk they have no instrument to measure — and the rational response is to not audit at all, or to demand a premium that makes the product pointless. Getting this boundary wrong makes auditing uninsurable.
So the line runs like this. The operator bears float loss from their own compromised key; the float cap is the operator's own risk limit, chosen by them. The bond covers harm to counterparties, whoever caused it — if a thief uses the stolen key to take payment and not deliver, the counterparty was harmed by the agent, and that is exactly the case the bond exists for. Being compensated for it means going through the arbiter, who is the only party that can name and size a victim; a predicate-computed proof pays nobody. The counterparty does not have to care whose fault the key loss was, and must not be asked to. The auditor is slashed only on a proven claim, on the same terms as any other; key compromise is not itself a proof type.
The distinction carrying all of it: an operator's own loss and a counterparty's loss are different things, and only the second is covered. A thief draining the float harms the operator, and the protocol pays nothing. A thief harming a counterparty triggers the ordinary settlement waterfall.
And the counter, again
A thief can push the spend counter past the bound, making BoundExceeded true without
anyone having been harmed. That is the same result the spend probe
proves for a self-dealing operator, reached by a different route, and it has the same
answer: the counter is evidence, not a payout trigger.
If BoundExceeded ever paid out on the counter alone, stealing an agent key would become a
way to force a payout from an honest operator's collateral. It does not, and this is one of
the reasons why. A thief who pushes spend past the bound can kill the certificate, which is
the correct outcome and the same one a compromised agent's own overspending should have.
They cannot reach the auditor's allocation, and neither can the operator.
A compromise does not invalidate the certificate. Invalidating on compromise would give an attacker a way to destroy a certificate by stealing a key. Counterparties harmed during the window challenge normally, and are not asked to prove anything about the key.
The largest gap here is the plainest one: detection is out of scope. Nothing in the protocol notices a compromise; it only bounds and stops one. The operator must be watching, and halting is only as fast as they are.