0xShikhar
Writing

Why AI Agents Need a Payment Layer, Not Just an API Key

· 12 min read· AI InfrastructureShare on X ↗

A few months into building UACP, someone asked me what it actually did. I said: it lets AI agents pay each other without a human in the loop.

They looked at me like it was obvious. Of course agents can pay each other. Just give them a wallet and some ETH.

That right there is the misconception. Handing an agent a private key and some ETH is like handing a new hire your corporate card with no spending policy, no approval flow, and no audit trail. It works fine. Until it really doesn't.

The actual problem isn't the wallet#

The payment problem showed up for me while building the multi-agent orchestration layer for DeFi strategies, which is what eventually became UACP.

We had a coordinator agent that broke down a DeFi strategy (a leveraged yield position across a few protocols) into subtasks and delegated them: one agent for swaps, one for liquidity, one for monitoring. Standard stuff.

Here's where it broke. The swap agent needed to pay a quote service agent for fresh pricing before executing. That quote service was an autonomous service that charged per call to cover its own gas. Reasonable design.

But making that payment meant one of two things:

  1. The swap agent held its own ETH and could sign arbitrary transactions, meaning it could drain its whole balance on a bad day
  2. A human had to approve it, which kills the whole "autonomous" part

Every framework I checked (LangChain, AutoGPT, CrewAI) punted on this. They either gave the agent a wallet with no constraints or required human approval. Neither works for anything running at machine speed.

The real problem isn't that agents lack wallets. It's that there's no protocol for one agent to request a service from another agent with machine-readable payment terms, automatic authorization against pre-declared spending policies, and verifiable settlement.

That's the thing I ended up building.

HTTP 402, the status code that never shipped#

Before the architecture, a quick aside because it's too good not to mention.

HTTP 402 is "Payment Required". The RFC reserves it "for future use". That was 1996. For almost thirty years it sat there unused, a footnote in the spec.

Then autonomous agents started making HTTP calls to each other and suddenly 402 was the most relevant status code nobody had ever implemented.

The idea: when an agent calls a service endpoint that needs payment, the service responds 402 and puts a machine-readable payment spec in the response headers. The calling agent reads it, checks it against its own spending policy, and either pays or escalates.

Coinbase formalized this as the X402 standard in 2024: the amount, the accepted token, the chain, the settlement address, an expiry. Everything a programmatic payer needs to decide without a human reading anything.

So that's piece one of UACP. Not my invention, I'm standing on Coinbase's work here. The observation is just that 402 + X402 is the right primitive for agent payment negotiation.

The identity problem you hit five minutes later#

Agents can negotiate payment via 402. Solved? Not quite, because the next question is: who is this agent and why should I trust its payment?

It sounds paranoid but it's a real attack surface. If service agent B accepts payments from anything claiming to be coordinator agent A, any malicious agent can impersonate A, drain B's credits, poison its data. You need agent identity.

The existing options are all bad:

  • API keys: shared secrets, stealable, can't be revoked granularly, carry no capability info
  • OAuth tokens: built for human-to-service auth, not machine-to-machine with dynamic capability negotiation
  • JWT: closer, but the trust root is still a centralized issuer

The right answer is DID-based identity. Each agent gets a DID anchored on-chain, and its capabilities (what it can request, its spending limits) live in a DID Document that any agent can resolve and verify without a central authority.

This is basically Google's A2A (Agent-to-Agent) contribution: a machine-readable format for capability declaration. What the agent does, what it costs, what auth it accepts.

So: X402 for payment semantics, A2A for identity and capability. UACP combines them on EVM.

How a UACP interaction actually works#

Setup#

Every agent publishes an Agent Card, a JSON doc following the A2A schema:

{
  "agentId": "did:ethr:0x1234...abcd",
  "name": "PricingOracle-v2",
  "capabilities": ["quote.spot", "quote.twap", "quote.historical"],
  "pricing": {
    "quote.spot": { "amount": "0.001", "token": "USDC", "chain": "somnia" },
    "quote.twap": { "amount": "0.005", "token": "USDC", "chain": "somnia" }
  },
  "endpoint": "https://oracle.agentnet/v1",
  "authentication": { "type": "did-auth", "challenge": true }
}

Any agent can resolve this from the on-chain DID registry. No manual config, no shared secrets floating around.

The request flow#

1. SwapAgent resolves PricingOracle's DID → gets Agent Card
2. SwapAgent checks its own SpendingPolicy:
   - Is quote.spot in my authorized capabilities? ✓
   - Is 0.001 USDC under my per-call limit? ✓
   - Is my daily spend budget not exhausted? ✓
3. SwapAgent calls the oracle endpoint
4. Oracle verifies SwapAgent's DID signature (challenge-response)
5. Oracle responds 200 + price data
6. Settlement happens async via on-chain payment channel

If the oracle returns a 402 mid-session (prepaid credits ran low), the SwapAgent reads the X402 headers and tops up from its allocated budget on its own. No human involved.

The spending policy#

This is the piece I spent the most time on and probably the most underrated part of the design. It's a declarative JSON object in the coordinator's config:

const spendingPolicy: SpendingPolicy = {
  daily_limit_usd: 50,
  per_call_limit_usd: 0.10,
  authorized_services: [
    { capability: 'quote.spot', max_per_hour: 1000 },
    { capability: 'swap.execute', max_per_hour: 100 },
  ],
  require_approval_above_usd: 5.00,
  circuit_breaker: {
    pause_on_consecutive_failures: 5,
    reset_after_minutes: 30
  }
}

This isn't smart contract logic. It's the agent's own governance layer, enforced before anything goes on-chain. The check runs in microseconds, before any signature, before any gas. It's the seat belt that makes giving agents real spending power survivable.

The circuit breaker#

Worth dwelling on, because this is where agent systems die in practice.

During development I watched a pricing agent bug return null instead of a price on a specific token pair. The swap agent got null, retried, got null, retried again. Dozens of retries in a couple of seconds, each one costing gas. A real version of that failure is how you end up with a three-figure gas bill because of a null pointer.

The UACP circuit breaker catches it: five consecutive failures and the agent pauses, logs, escalates to the coordinator. Human gets pinged. System stops.

Where v1 got it wrong#

First version of UACP had no SDK. The spec existed, the contracts were deployed, and I expected developers to implement the message schema themselves.

Naive, looking back.

The A2A message format has enough edge cases (capability negotiation, partial responses) that two independent implementations drift in ways that don't show up until production. You get agents that technically speak the same protocol but can't interoperate because developer A read the spec differently from developer B.

So v2 ships a TypeScript SDK with Zod validation on every message boundary. Malformed capability request? You find out at compile time instead of staring at a failed tx at 2am. The Zod schemas are the spec made executable.

What's still unsolved#

I don't want to oversell where UACP is. Real open problems:

Disputes. Agent pays for a service, gets corrupt data. There's no on-chain dispute mechanism in the base protocol. You can build one on top (escrow + quality oracle) but every app has to decide it themselves. Intentional, dispute logic is app-layer, but it's still a gap.

Gas abstraction. Each agent needs ETH for gas, USDC for payments, and some coordination around gas estimation. ERC-4337 helps toward agents running on pure token budgets, but the tooling isn't quite there for production multi-agent systems.

Bootstrapping. How does an agent get its first DID? Who issues initial credentials? Until there's a critical mass of agents with DIDs, discovery is underused. Right now the deploying developer registers agent DIDs during deployment, which works but isn't elegant.

Revocation latency. Revoking a compromised agent takes 12-15 seconds to propagate on most EVM chains, and a bad actor can keep making signed requests in that window. Short-lived capability tokens (60s expiry) mitigate it, at the cost of complexity.

Beyond DeFi#

I built UACP for DeFi because that's where the problem bites hardest. Real money, high-frequency decisions, no room for human approval latency.

But the pattern generalizes. Any mesh of specialized agents exchanging services (research agents, codegen agents, data agents) hits the same thing. A needs something from B. How do they negotiate? How does A pay? How does B know A is A?

402 + A2A + DID is one answer. Not the only possible one, but it's built on standards that already exist and it doesn't require anyone to adopt a new consensus mechanism.

The agentic web is coming whether the payment rails exist or not. I'd rather they do.


UACP is open source. The SDK and protocol spec are at github.com/0xshikhar/UACP. The live demo runs on Somnia testnet at uacp.shikhar.xyz.

↑ back to top
Why AI Agents Need a Payment Layer, Not Just an API Key — Shikhar Singh — Shikhar Singh (@0xshikhar)