Take stock of what the first two layers bought. A session key has a cap (how much), an expiry (until when), a one-transaction kill switch, and — since part 2 — a durable identity behind it (who). And yet a compromised agent operating inside all of those bounds can still spend its entire budget on anything that answers a 402. The blast radius has a size. It has no shape.
Part 1 called this the field's hardest open problem: for agents, the useful domain isn't the merchant — merchant-scoping fights the whole point of an agent that shops across merchants. The useful domain is the intent. AP2 gestures at it with a mandate chain; Mastercard gestures with "Verifiable Intent" — an LLM-grade semantic judgment proposed inside a sub-second authorization, attackable at the language layer. Gestures, both. Nobody ships an enforceable primitive.
Shrink the problem until it runs
dfmi's move is deliberately modest: don't solve open-world semantics. Solve category-scoped intent, and enforce it where everything else in this series is enforced — the authorization path. Two small pieces. A ServiceRegistry maps every payout address to a category — market-data, ai-answers, api-tools — first-come, immutable, public. And IntentSessionWallet — v2 of part 1's wallet — gives every session an intentMask: a bitmask of the categories this key is allowed to want.
"Only market-data services, half a dollar, seven days" is now a single grant: grantSession(key, cap, expiry, mask). At payment time, pay() resolves the payee's category from the registry and checks membership — right beside the revocation gate, before any money moves. The agent's side changes not at all: same EIP-712 signature, same relayer path, same offline speed. Intent lives in the grant, not in the signature.
Same signature, two fates
The proof is the cleanest in the series. The agent signed two payments — same key, same format, same valid signature, budget comfortably unspent. The first went to a registered market-data payee: settled. The second went to an address outside the granted intent: reverted in the authorization path, before settlement, with the cap untouched. Nothing about the cryptography differed. What differed was what the owner had said this key was for.
| registry | 0xED134CC9c3D94908B20dd9DDBc2534C199394A81 | ||
| wallet | 0x8FDDE156116a4cBd0f9e185550f6476A56b550fB · grant: cap 0.50 · 7d · market-data only | ||
| pay | market-data payee · 0.02 · 0xa2272a9c…b8062b | ✓ | settled |
| pay | outside intent · same key · same valid signature | ✗ | reverted |
What this proves — and what it honestly doesn't
What it proves: intent enforcement needs no new cryptography and no synchronous issuer hop. Offline-signed, agent-speed, in the authorization path — the machinery is ~150 lines and it is running. The stateless-auth-versus-instant-control tension from part 1 does not get worse when the control is semantic; the gate is just one more storage read.
What it doesn't prove: the hard half is now clearly visible, and it isn't enforcement. Categories here are self-declared and first-come — a malicious seller can mis-file itself once. Categories are also coarse — "market-data" is not "a camping trip under $400". Rich, open-world intent needs a shared, attestable vocabulary of what services are: curator signatures, stake-and-challenge, cross-system category standards. That is an attestation problem and a semantics problem. It is not a payments problem anymore — which is exactly the finding.
Intent enforcement is solved machinery: a bitmask, a registry read, a require(). What the field is actually missing is the vocabulary — an attestable, portable answer to "what is this service?". Whoever builds that attestation layer completes the credential the whole industry is circling.
And with that, the control plane this series set out to build is standing, all three layers of it, on one public economy: the credential says how much and until when — revocable in one transaction. The identity says who — durable across every key rotation. The intent says what for — enforced before money moves. Each layer is about a hundred lines. Each is enforced in the authorization path, not an audit log. Each has a running agent, a public ledger, and an on-chain proof you can click. The rail was never the hard part.
All three layers are public — contracts, ledger, and a 24×7 agent living under them.
Everything here is drawn from public protocol documentation and standard payments practice. No proprietary anything — just twenty years of scar tissue, read from the outside, and a wallet dfmi taught to refuse a perfectly valid signature for a perfectly good reason.