ChallengeEngine and state machine as the x402 HTTP flow. The difference is the wire format: A2A task lifecycle with x402 metadata keys instead of HTTP headers. A2A-native clients reach the Key0Executor via POST /x402/access with the X-A2A-Extensions header (Express only).
Flow Overview
1
Discovery
The client fetches
/.well-known/agent.json to learn about available skills, pricing plans, and the seller’s wallet address.2
Access Request
The client sends an
AccessRequest with a resourceId and planId via A2A message/send.3
Challenge
The server creates a PENDING record in the challenge store and returns an
X402Challenge with the payment amount, destination wallet, chain ID, and expiration.4
Payment
The client pays on-chain USDC on Base — a standard ERC-20 transfer. No custom contracts or off-chain signatures required.
5
Proof
The client submits a
PaymentProof containing the transaction hash via a second message/send with x402 payment metadata.6
Verification
The server verifies the payment on-chain: correct recipient, correct amount, not expired, not double-spent. On success, the challenge transitions from PENDING to PAID.
7
Grant
The server calls
fetchResourceCredentials to issue a credential (JWT, API key, etc.), transitions PAID to DELIVERED, and returns an AccessGrant with the token and resource endpoint URL.8
Access
The client uses the token as a
Bearer header to call the protected resource directly.Sequence Diagram
A2A Protocol Details
The A2A flow usesKey0Executor, which implements the AgentExecutor interface from @a2a-js/sdk. The payment negotiation happens across two message/send round-trips, using task metadata to carry x402 payment state.
Phase 1 — AccessRequest to Challenge
The client sends amessage/send JSON-RPC request with an AccessRequest in the message parts:
engine.requestAccess() and publishes a Task with:
- State:
input-required— indicating the client needs to take action (pay) - Metadata:
x402.payment.statusset to"payment-required"andx402.payment.requiredcontaining the fullPaymentRequirementsobject - Parts: a text description of the challenge plus the
X402Challengeas a data part
Phase 2 — Payment to Grant
After paying on-chain, the client sends a secondmessage/send with the payment payload in task metadata:
- Extracts
challengeIdfrompayload.accepted.extra.challengeId - Publishes working Task with
x402.payment.status: "payment-submitted" - Calls
settlePayment()to verify and settle on-chain - Publishes working Task with
x402.payment.status: "payment-verified" - Calls
engine.processHttpPayment()to transition PENDING to PAID to DELIVERED - Publishes final Task:
- State:
completed - Metadata:
x402.payment.status: "payment-completed"andx402.payment.receiptswith the settlement receipt - Parts: confirmation text and the
AccessGrantdata part - Artifacts: the
AccessGrantas a data artifact
- State:
x402 Metadata Keys
All payment state is communicated through task metadata using these keys:A2A Headers
Native A2A clients send theX-A2A-Extensions header on POST /x402/access. This tells the Express integration to bypass the standard x402 HTTP flow and route the request to the A2A JSON-RPC handler and Key0Executor.
Next Steps
Express Integration
A2A is only available on Express — see setup details and the
X-A2A-Extensions header.x402 HTTP Flow
The simpler REST-based payment flow using HTTP 402 status codes.
State Machine
Full state diagram covering PENDING, PAID, DELIVERED, EXPIRED, and REFUNDED states.
Settlement Strategies
Gas wallet vs. facilitator settlement and EIP-3009 authorization.

