# agents.u.cash — Architecture

How a single HTTP-402 challenge carries every payment rail — crypto and fiat/card — and how each rail is verified and settled **peer-to-peer, non-custodially**. The platform is a **verifier and detector**. It never holds user funds and never holds user private keys.

## Non-custodial by design (the rule everything follows)

The platform never accepts, holds, pools, controls, or re-transmits user funds, and never holds user private keys. Under the FinCEN "control" test it is therefore **not a money transmitter / money-service business** — no licenses, no KYC. Funds always move **directly from buyer to seller** on-chain (crypto) or to the seller's own processor (fiat); the platform's only role is to detect the payment, confirm it, index the result, and notify. See [RISKS.md](RISKS.md) for the per-flow legal argument.

**The critical invariant:** at no instant does the platform control a coin owed to a user. Concretely — no internal balance representing user funds; no withdrawal/payout-from-balance function (ever); no sweep from held keys; no platform address in the principal's value path.

## The unified 402 protocol

The 402 Online Protocol is **stateless and HTTP-native**:

1. A client requests a paid resource.
2. The server responds **HTTP 402** with an `accepts` **array** of payment details, each describing one way to pay (a `scheme`, an asset, an amount, a payee).
3. The client picks one entry and fulfills it per that scheme.
4. The platform **verifies** the payment (per scheme) and **settles** if needed.
5. The platform returns **HTTP 200** + the resource, or 402 again on failure.

The `accepts`/`scheme` mechanism is **extensible** (the registry defines `detect`, `redirect`, and `exact`). That extensibility lets one challenge serve every rail.

## One challenge, many rails

A resource's 402 challenge builds an `accepts` array with entries from every registered scheme. Two ship today:

**`detect` — the universal crypto rail.** The `payTo` is the **seller agent's own wallet**; the `amount` is EXACT when the seller saved 3+ receive addresses for the asset (each buyer gets a unique address), or carries a tiny dust variation in the last decimals only when the address is reused — so payments stay attributable with no visible overcharge:
```json
{ "scheme": "detect", "asset": "btc", "payTo": "<seller's own wallet>", "amount": "16230", "challengeId": "chal_…", "expiresAt": 1730000000 }
```
The buyer broadcasts a real on-chain transfer of `amount` to `payTo`. The platform **detects** that transaction (via its detection engine + cron; optionally a buyer/seller push-verify carrying the tx hash for instant settlement), confirms it on-chain, and settles. No client-supplied cryptographic proof is needed — the chain itself is the proof.

**`redirect` — the fiat/card rail.** The buyer follows a hosted-checkout URL to the **agent's own** Stripe account:
```json
{ "scheme": "redirect", "url": "https://…/checkout", "challengeId": "chal_…", "expiresAt": 1730000000 }
```
The challenge pre-creates a pending transaction whose reference is the resource; the buyer pays at Stripe (funds settle buyer→agent's Stripe directly); Stripe's webhook completes the transaction. The `redirect` 402 does **not** block — the seller learns of payment through its webhook.

**One resource, every audience** — a crypto buyer pays a `detect` entry to the seller's wallet; a human buyer follows a `redirect` entry to the seller's card processor.

## The platform verifies and settles — never custodies

- **`detect`:** the platform confirms a real on-chain transaction to the seller's own address for the exact amount (with the required confirmations) via the same detection engine merchants already use, then marks the resource settled. It touches no funds.
- **`redirect`:** the platform verifies the processor's signed webhook (Stripe signature), completes the pending transaction, and notifies the seller. The card payment lands in the seller's own processor account.
- **Fee:** the platform fee is debited from the **seller's prepaid, non-withdrawable service credit** at the platform's UCASH fee rate — the same schedule merchants pay. The buyer's payment is always the full gross amount, direct to the seller; there is no held balance and no on-chain fee split.

## UCP checkout sessions (the commerce layer on top of 402)

The 402 engine handles per-resource payments (detect + redirect). On top of it, the UCP (Universal Commerce Protocol, ucp.dev) checkout layer lets a buyer create a **checkout session** that wraps one or more resources, mint their challenges in one call, and track per-item settlement:

- **Session lifecycle:** `incomplete` -> `ready_for_complete` (after `complete` mints the challenges) -> `completed` (after the settlement hook fires when every item's challenge settles). `GET /orders/{id}` shows per-item fulfillment.
- **Multi-item carts:** a session wraps N resources (`line_items[]`), each with its own quantity. The buyer pays each item's challenge independently (each to the seller's wallet, non-custodial). The session completes only when ALL items settle.
- **Mixed-currency:** items may be priced in different fiat currencies; the displayed cart total converts to a single cart currency via cached OpenExchangeRates (`uxc_usd_rates`, 1h cache). The on-chain payment per item uses the item's original fiat price.
- **AP2 mandates (dev.ucp.shopping.ap2_mandate):** the merchant signs every checkout response with a detached JWS (`ap2.merchant_authorization`, RFC 9421 ES256 over the JCS-canonicalized checkout). On `complete`, a buyer's `checkout_mandate` (SD-JWT-VC) is verified: issuer signature, checkout-hash binding, key-binding JWT holder proof (RFC 9901), and open-mandate constraints (max_amount / nbf / allowed_merchant). Rejected with 401 `mandate_invalid_signature` / `mandate_scope_mismatch`.
- **RFC 9421 response signing:** every merchant-origin UCP response is signed (ES256, Content-Digest + Signature-Input + Signature headers) with the merchant key published in `/.well-known/ucp`. Signed inbound requests are passively verified (`UCP-Request-Signature` header).
- **Rate limiting:** the public UCP REST surface is per-IP throttled (checkout 60/min, catalog 120/min, orders 60/min, discovery 300/min; CF-Connecting-IP; 429 `uxc_rate_limited`).
- **Settlement monitoring:** `uxc_settlement_health()` (cloud cron) records cron liveness + scans for stuck pending transactions (>6h, before the 48h reap) + alerts the super-admin.

## Agent balances — indexer-only, plus an optional email-verify credit

- Agent **earnings** are a **read-only on-chain indexer record** (tx hash, from/to, amount, resource) for display, reputation, and discovery — like a block explorer showing your balance. It is **not** a claim against the platform and has **no withdrawal function** (and never will). This is the unhosted-wallet/indexer category FinCEN excludes.
- Agents **start at $0** (no signup credit). The only internal agent credit is the **optional email-verification reward** — non-withdrawable, fee-only (the same non-custodial mechanism merchants use), granted when an agent verifies an email. It is a service prepayment, never redeemable for cash.

## Multi-chain

`detect` works for any address-based coin — ~40 native coins: Bitcoin (+ Lightning), Ethereum + 15 EVM L2s (Base, Arbitrum, Optimism, Linea, Mantle, Berachain, Sonic, Unichain, World, Monad, Plasma, Abstract, Scroll, Ink, Hyperliquid), Solana, Tron, XRP, Dogecoin, Litecoin, Bitcoin Cash, Algorand, Monero, Polkadot, Stellar, Tezos, Polygon, Avalanche, BNB Chain; plus USDT (ETH/BSC/Tron), USDC, UCASH; and **custom tokens on 20 chains** (ERC-20 / BEP-20 / Base-20 / Polygon-20 / Arb-20 / Op-20 / Avax-20 / ... / TRC-20 / SPL). The `exact` rail additionally enables gasless **USDC-on-Base** (EIP-3009). It only needs an address and the existing detection engine; the canonical live list is at [agents.u.cash](https://agents.u.cash/). One challenge can offer several via per-asset `detect` entries. Cross-chain, if ever needed, uses **CCTP burn-and-mint direct buyer→seller** (Circle's regulated, non-custodial rail) — **never** a platform-operated bridge that takes custody.

## `exact`: signed-payload push (EIP-3009 / x402)

Implemented (v1: USDC on Base). `exact` is an EVM rail where the buyer signs an off-chain EIP-3009 `transferWithAuthorization` and the platform verifies it; funds move direct buyer→seller (the seller's own Base address). The platform recovers the signer and checks the authorization binds to the challenge (payee, amount, expiry, unused nonce). It holds no funds and signs no value move.

**Two settlement postures:**
- **Gasless / facilitator-relayed (DEFAULT).** A stock x402 client signs the authorization and expects the facilitator to relay it on-chain. The platform relayer does so: it submits the buyer-signed `transferWithAuthorization`, signing only a gas-paying wrapper around a message it cannot alter (meta-tx relaying — it cannot redirect the buyer→seller value move). This is **on by default** so off-the-shelf x402 clients pay without adaptation. The seller is billed the relayer gas + 21% per settle from its prepaid, non-withdrawable credit. A seller who prefers the buyer to pay gas opts out (`POST /v1/exact-relay {enabled:0}` or `DELETE`).
- **Verify-only / buyer-pays-gas (fallback).** With the relayer off or unavailable, the platform verifies the signature, records it, and settles confirm-then-settle once the buyer (or seller) submits the authorization on-chain and posts the resulting tx hash (`POST /v1/exact-settle` or `/v1/verify`). This is the fallback for opted-out sellers and sophisticated clients/SDKs; a stock x402 client that never submits on-chain needs the relayer.

Even with the relayer on, the platform never holds funds and never signs a value move, so the FinCEN control-test argument holds. There is **no on-chain atomic fee split** in v1: the on-chain tx is buyer→seller full gross; the fee (plus relayer gas, when relayed) is debited from the seller's prepaid non-withdrawable credit, exactly as `detect` and `redirect`.

The door also speaks the x402 wire format: `WWW-Authenticate: x402`, the `X-PAYMENT` / `X-PAYMENT-RESPONSE` headers, and facilitator `/verify` + `/settle` endpoints, so an off-the-shelf x402 client pays without adaptation. Permit2 (any ERC-20), more chains, and signed-intent batching remain future generalizations.

## Agent personas (honest asymmetry)

- **Agent-as-seller (full, v1):** emits multi-rail 402 challenges to its own wallets; is paid direct on-chain (`detect`) or via its own Stripe (`redirect`). Pure reuse of the merchant model.
- **Agent-as-buyer, crypto (v1):** the agent holds its own key and pays a `detect` entry's `payTo` on-chain from its own wallet — fully autonomous.
- **Agent-as-buyer, fiat (not built):** autonomous card payment requires stored funding (custody) and 3DS/SCA anyway needs a human. Fiat buying by an agent stays human-in-the-loop via the `redirect` scheme.

## Security essentials

- **Replay/idempotency:** a wallet-submitted tx hash has a uniqueness guard (receive addresses are reused → a replayed hash must not re-credit); HMAC-signed webhooks with event ids.
- **Double-settle:** completion is idempotent on status and unique on hash; a settlement cache rejects duplicate submissions.
- **Challenge freshness:** each challenge carries an expiry and an exact amount and is single-use.
- **Agent receive addresses are the agent's own** self-custody wallets. Node-generated addresses + auto-sweep are **never** used on the agent surface (and are disabled + warned platform-wide — see [RISKS.md](RISKS.md)).
- **No withdrawal function exists or will be added.** No sweep from held keys. These are architectural guarantees, not just policy.

## Read next

- [USE-CASES.md](USE-CASES.md) — what gets sold over this protocol.
- [ROADMAP.md](ROADMAP.md) — when each piece ships (non-custodial from day one).
- [RISKS.md](RISKS.md) — the per-flow "not a money transmitter" argument, and the residual state-level exposure.
