Lanes
Agent lane
The Agent lane protects x402 and nanopayment calls with capped sessions and seller-signed receipts. A missing receipt means an automatic refund.
What the Agent lane covers
AI agents pay for API calls, data and compute in very small amounts, many times in a row. A dispute process built for people does not fit. An agent cannot write a complaint, and nobody will arbitrate a 0.02 USDC call.
The Agent lane replaces judgement with a rule that code can check:
- The agent opens a protected session with a spending cap.
- Each paid API response must carry a receipt signed by the seller.
- A call that was paid but has a missing or late signed receipt is refunded automatically. There is no arbitration.
The seller side is the same as in the Commerce lane: one bond, one capacity, one fee.
x402 in brief
x402 is a payment flow built on the HTTP status code 402 Payment Required.
- The agent requests a resource.
- The server answers 402 and states the price, the asset and where to pay.
- The agent repeats the request with a payment attached.
- The server checks the payment and returns the response.
The agent pays per request. There are no accounts and no API keys. With UNDO, step 4 has one more requirement: the response carries the signed receipt, for example in a response header.
GET /v1/check?target=api.example.com HTTP/1.1
Host: monitor.example.com
HTTP/1.1 402 Payment Required
Content-Type: application/json
{ "accepts": [{ "scheme": "exact", "network": "arc", "asset": "USDC", "maxAmountRequired": "20000" }] }
GET /v1/check?target=api.example.com HTTP/1.1
Host: monitor.example.com
X-PAYMENT: <payment payload bound to the UNDO session>
HTTP/1.1 200 OK
Content-Type: application/json
X-UNDO-RECEIPT: <base64 of the Receipt fields and the seller signature>
{ "status": "up", "latencyMs": 41 }
The header name X-UNDO-RECEIPT is a draft. A receipt middleware for x402 servers is planned for phase 2 of the roadmap, so that sellers do not have to write the signing code themselves.
Protected sessions
A session is the unit of protection in this lane.
| Session parameter | Planned value |
|---|---|
| Spending cap | Set by the agent when it opens the session |
| Window | From 10 minutes to 24 hours |
| Price per call | Set by the seller |
| Proof of delivery | One signed receipt per paid call |
| Assets | USDC and EURC |
The lifecycle has four steps.
- Open session. The agent opens a session against a seller with a spending cap, for example 5 USDC. The cap is the most the agent can spend in that session.
- Paid call. The agent pays per request through x402 or a nanopayment. Each call has an index inside the session.
- Signed receipt. The seller returns the response with a receipt that binds the session, the call index, the request hash and the response hash.
- Claim. Before the window ends, the agent can claim a refund for every paid call that has no valid receipt.
Before opening a session, an agent can read the seller's public profile: protected volume, dispute rate, lost-dispute rate, bond and free capacity.
Signed receipts
A receipt is an EIP-712 typed message signed by the seller. It states that a specific response was served for a specific paid call.
Receipt struct
struct Receipt {
bytes32 sessionId; // protected session opened by the payer
uint64 callIndex; // position of the call inside the session
bytes32 requestHash; // keccak256 of the request the agent sent
bytes32 responseHash; // keccak256 of the response body the seller returned
uint256 amount; // price of this call, in USDC base units
uint64 servedAt; // seller timestamp, must fall within the receipt deadline
}
EIP-712 domain
{
"name": "UNDO Receipts",
"version": "1",
"chainId": 5042,
"verifyingContract": "0x0000000000000000000000000000000000000000"
}
verifyingContract will be the Receipts contract. Its address is not published yet. The zero address above is a placeholder.
Verifying a receipt
The agent should verify each receipt as soon as the response arrives. This draft example uses viem.
import { createPublicClient, http, keccak256, toHex } from "viem";
const client = createPublicClient({ transport: http(ARC_RPC_URL) });
const domain = {
name: "UNDO Receipts",
version: "1",
chainId: 5042,
verifyingContract: RECEIPTS_ADDRESS, // not published yet
} as const;
const types = {
Receipt: [
{ name: "sessionId", type: "bytes32" },
{ name: "callIndex", type: "uint64" },
{ name: "requestHash", type: "bytes32" },
{ name: "responseHash", type: "bytes32" },
{ name: "amount", type: "uint256" },
{ name: "servedAt", type: "uint64" },
],
} as const;
async function isReceiptValid(receipt, signature, responseBody, sellerAddress) {
// 1. The receipt must describe the response that was actually received.
const hashMatches = receipt.responseHash === keccak256(toHex(responseBody));
if (hashMatches === false) return false;
// 2. The signature must come from the seller of the session.
return client.verifyTypedData({
address: sellerAddress,
domain,
types,
primaryType: "Receipt",
message: receipt,
signature,
});
}
If isReceiptValid returns false, the agent keeps the call in its list of claimable calls.
Smart-contract wallets
Sellers and agents can use smart-contract wallets. The Receipts contract is designed to accept EIP-1271 signatures, so a seller contract can approve a receipt through its isValidSignature function. In the example above, the public client's verifyTypedData action also checks contract signatures, so the same code covers both wallet types.
Automatic claims
A claim is a list of call indexes that were paid without a valid receipt. The Receipts contract checks each call against the session record.
| Case | Outcome |
|---|---|
| Paid call, valid receipt on time | No refund through this path |
| Paid call, no receipt | Automatic refund |
| Paid call, receipt after the receipt deadline | Automatic refund |
| Valid receipt, but the agent's owner contests the content | Standard dispute: deposit, 48h seller response, arbitration |
Automatic refunds follow the same refund waterfall as any other refund.
Worked example
A monitoring agent opens a 5 USDC session at 0.02 USDC per call. The cap covers up to 250 calls.
During the session the API goes down. The payments still settle, but 212 calls are paid without a signed receipt.
unreceipted calls 212
price per call 0.02 USDC
refund 212 x 0.02 = 4.24 USDC
The agent submits the claim. 4.24 USDC is refunded automatically, with no arbitration.
Keys and operations
The seller's receipt signing key is sensitive. Anyone who holds it can sign receipts for responses that were never served. Sellers should keep it separate from the key that controls the bond, and store it the way they would store any production secret. See Risks.