AdvancedA2A Transport

A2A Transport (Agent-to-Agent)

T402 payment flows over the Agent-to-Agent (A2A) protocol, enabling AI agents to pay each other for services.

Overview

The A2A transport adapts the T402 payment protocol for Google’s Agent-to-Agent protocol, enabling autonomous AI agents to monetize their services through on-chain payments.

Instead of HTTP status codes and headers, A2A uses task state and message metadata to signal payment requirements and submit payments.

Key Differences from HTTP

AspectHTTP TransportA2A Transport
Payment signal402 status codeTask state input-required
Requirements locationResponse bodyTask metadata
Payment submissionPayment-Signature headerMessage metadata
Settlement receiptPayment-Response headerTask metadata
State managementStatelessTask lifecycle
Error signalingHTTP status codesTask state failed

Payment Flow

Client sends task

The client agent sends a message/send request to the server agent.

Server signals payment required

Instead of HTTP 402, the server returns a task with state: "input-required" and payment requirements in metadata.

Client submits payment

The client signs the payment authorization and sends it back as a message with t402.payment.payload metadata.

Server verifies and settles

The server verifies the payment, settles on-chain, and completes the task with the response and settlement receipt.

Payment Required Signal

When a server agent requires payment, it returns a task in input-required state:

{
  "jsonrpc": "2.0",
  "id": "req-001",
  "result": {
    "kind": "task",
    "id": "task-123",
    "status": {
      "state": "input-required",
      "message": {
        "role": "agent",
        "parts": [{ "text": "Payment required to access this service." }],
        "metadata": {
          "t402.payment.status": "payment-required",
          "t402.payment.required": {
            "t402Version": 2,
            "error": "Payment required",
            "resource": {
              "url": "a2a://agent/weather-tool",
              "description": "Weather data lookup",
              "mimeType": "application/json"
            },
            "accepts": [{
              "scheme": "exact",
              "network": "eip155:8453",
              "amount": "1000",
              "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
              "payTo": "0xAgentAddress...",
              "maxTimeoutSeconds": 300
            }]
          }
        }
      }
    }
  }
}

Payment Submission

The client signs the payment and sends it back with the task ID for correlation:

{
  "jsonrpc": "2.0",
  "method": "message/send",
  "id": "req-002",
  "params": {
    "message": {
      "taskId": "task-123",
      "role": "user",
      "parts": [],
      "metadata": {
        "t402.payment.status": "payment-submitted",
        "t402.payment.payload": {
          "t402Version": 2,
          "scheme": "exact",
          "network": "eip155:8453",
          "payload": {
            "authorization": {
              "from": "0xClientAddress...",
              "to": "0xAgentAddress...",
              "value": "1000",
              "validAfter": 1700000000,
              "validBefore": 1700000300,
              "nonce": "0xabc..."
            },
            "signature": "0xdef..."
          }
        }
      }
    }
  }
}

Settlement Response

After successful verification and settlement, the task completes with the receipt:

{
  "kind": "task",
  "id": "task-123",
  "status": {
    "state": "completed",
    "message": {
      "role": "agent",
      "parts": [{ "text": "Weather in Tokyo: 22°C, sunny." }],
      "metadata": {
        "t402.payment.status": "payment-completed",
        "t402.payment.receipts": [{
          "success": true,
          "transaction": "0x1234abcd...",
          "network": "eip155:8453",
          "payer": "0xClientAddress..."
        }]
      }
    }
  }
}

AP2 Embedded Flow

The Agent Payments Protocol (AP2) extends A2A with a structured, mandate-based payment flow. Instead of carrying x402 requirements in message metadata, AP2 wraps them inside CartMandate artifacts using the W3C Payment Request format.

Embedded vs Standalone

AspectStandalone (A2A)Embedded (AP2)
Requirements locationt402.payment.required metadataCartMandate artifact DataPart
Payment submissiont402.payment.payload metadataPaymentMandate message DataPart
Payment method formatt402 PaymentRequirementsW3C PaymentMethodData wrapping t402
Cart supportNoYes (PaymentDetailsInit)
Mandate trackingNoYes (mandate IDs, receipts)
DetectionisStandaloneFlow(task)isEmbeddedFlow(task)

How It Works

In the embedded flow, the server creates a CartMandate with x402 requirements embedded in the PaymentMethodData:

{
  "artifacts": [{
    "kind": "ap2.cart",
    "name": "Cart Mandate",
    "parts": [{
      "kind": "data",
      "data": {
        "ap2.mandates.CartMandate": {
          "contents": {
            "payment_request": {
              "method_data": [{
                "supported_methods": "https://www.x402.org/",
                "data": { "requirements": [{ "scheme": "exact", "network": "eip155:8453", "..." }] }
              }]
            }
          }
        }
      }
    }]
  }]
}

The client extracts the requirements, signs the payment, and wraps it in a PaymentMandate DataPart in a message.

See the AP2 Integration guide for the full embedded flow with code examples.

Payment Status Lifecycle

StatusTask StateDescription
payment-requiredinput-requiredServer needs payment
payment-submittedworkingClient sent payment payload
payment-verifiedworkingPayload verified
payment-completedcompletedSettled on-chain
payment-rejectedfailedClient declined to pay
payment-failedfailedVerification or settlement failed

Extension Declaration

Agent Card

Server agents advertise T402 support in their Agent Card:

{
  "name": "Weather Agent",
  "capabilities": {
    "extensions": [
      {
        "uri": "https://github.com/google-a2a/a2a-t402/v0.1",
        "description": "Accepts T402 USDT payments",
        "required": true
      },
      {
        "uri": "https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2",
        "description": "x402 v0.2 compatibility",
        "required": false
      }
    ]
  }
}

Client Activation

Clients signal T402 support via an HTTP header on the A2A connection:

X-A2A-Extensions: https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2

Error Handling

When payment fails, the task transitions to failed state with error details:

{
  "kind": "task",
  "id": "task-123",
  "status": {
    "state": "failed",
    "message": {
      "role": "agent",
      "parts": [{ "text": "Payment verification failed." }],
      "metadata": {
        "t402.payment.status": "payment-failed",
        "t402.payment.error": "EXPIRED_PAYMENT",
        "t402.payment.receipts": [{
          "success": false,
          "errorReason": "Payment authorization has expired",
          "network": "eip155:8453"
        }]
      }
    }
  }
}

Error Codes

Error CodeDescriptionRecovery
EXPIRED_PAYMENTAuthorization deadline passedRetry with new signature
INSUFFICIENT_AMOUNTAmount less than requiredRetry with correct amount
INVALID_SIGNATURESignature verification failedCheck signer address
NETWORK_MISMATCHWrong networkUse correct network from accepts
SETTLEMENT_FAILEDOn-chain settlement failedRetry or try different network

Metadata Fields Reference

FieldLocationDescription
t402.payment.statusMessage metadataCurrent payment lifecycle state
t402.payment.requiredMessage metadataPaymentRequired object (same as HTTP 402 body)
t402.payment.payloadMessage metadataSigned PaymentPayload
t402.payment.receiptsMessage metadataArray of settlement receipts
t402.payment.errorMessage metadataError code string
x402.payment.statusMessage metadatax402 compat alias for t402.payment.status
x402.payment.requiredMessage metadatax402 compat alias for t402.payment.required
x402.payment.payloadMessage metadatax402 compat alias for t402.payment.payload
x402.payment.receiptsMessage metadatax402 compat alias for t402.payment.receipts
x402.payment.errorMessage metadatax402 compat alias for t402.payment.error

Implementation Example

import { A2AServer } from '@google/a2a'
 
const server = new A2AServer({
  agentCard: {
    name: 'Premium Data Agent',
    capabilities: {
      extensions: [{
        uri: 'https://github.com/google-a2a/a2a-t402/v0.1',
        required: true
      }]
    }
  }
})
 
server.onMessage(async (message, task) => {
  // Check for payment
  const paymentPayload = message.metadata?.['t402.payment.payload']
 
  if (!paymentPayload) {
    // Return payment required
    return task.requireInput({
      metadata: {
        't402.payment.status': 'payment-required',
        't402.payment.required': {
          t402Version: 2,
          accepts: [{
            scheme: 'exact',
            network: 'eip155:8453',
            amount: '1000',
            asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
            payTo: agentAddress,
            maxTimeoutSeconds: 300
          }]
        }
      }
    })
  }
 
  // Verify and settle payment
  const receipt = await facilitator.settle(paymentPayload)
 
  // Return result with receipt
  return task.complete({
    parts: [{ text: 'Here is your data...' }],
    metadata: {
      't402.payment.status': 'payment-completed',
      't402.payment.receipts': [receipt]
    }
  })
})

Comparison with MCP Transport

FeatureA2A TransportMCP Transport
Use caseAgent-to-agent servicesTool access for AI models
ProtocolJSON-RPC + tasksJSON-RPC + tool calls
Payment signalTask input-requiredTool result with 402
StateTask lifecycleStateless per call
DiscoveryAgent CardMCP server manifest

For AI agents accessing tools (like weather APIs), use the MCP transport. For agents providing services to other agents, use A2A.

Negotiation Protocol

Coming Soon: @t402/a2a-negotiation is not yet released. This page describes planned functionality and APIs are subject to change. Follow the GitHub repository for release announcements.

The A2A Negotiation Protocol enables AI agents to negotiate payment terms, discover services, and settle payments atomically. It implements the Agent-to-Agent (A2A) protocol with T402 payment extensions.

Features

  • Negotiation Protocol - State machine for multi-round price negotiations
  • Pricing Strategies - Pluggable strategies for automated negotiation
  • Agent Discovery - Service registry with capability and pricing discovery
  • Escrow System - Conditional payments with multi-sig and time-lock support
  • Atomic Settlement - All-or-nothing payment settlement
  • Dispute Resolution - Evidence-based dispute handling

Installation

npm install @t402/a2a-negotiation

Quick Start

Basic Negotiation

import {
  NegotiationProtocol,
  StrategyFactory,
} from '@t402/a2a-negotiation';
 
// Create a negotiation session
const negotiation = NegotiationProtocol.create({
  initiator: 'client-agent',
  counterparty: 'service-agent',
  resource: {
    url: 'https://api.example.com/generate-image',
    description: 'AI Image Generation Service',
  },
  maxRounds: 5,
  timeoutMs: 300000, // 5 minutes
});
 
// Submit a proposal
const proposal = negotiation.propose({
  terms: {
    scheme: 'exact',
    network: 'eip155:8453', // Base
    asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bda02913', // USDC
    amount: '1000000', // 1 USDC (6 decimals)
    payTo: '0xServiceWallet',
  },
  slaTerms: {
    maxResponseTimeMs: 5000,
  },
});
 
// Use a pricing strategy to evaluate
const strategy = StrategyFactory.priceRange(
  '500000',  // min: 0.5 USDC
  '2000000', // max: 2 USDC
  ['eip155:8453'],
  ['0x833589fCD6eDb6E08f4c7C32D4f71b54bda02913'],
);
 
const evaluation = strategy.evaluate({
  proposal,
  currentRound: negotiation.getSession().currentRound,
  maxRounds: 5,
  previousOffers: [],
});
 
if (evaluation.accept) {
  negotiation.accept(proposal.proposedTerms);
} else if (evaluation.counterTerms) {
  negotiation.counter({
    proposalId: proposal.id,
    counterTerms: evaluation.counterTerms,
    reason: evaluation.reason,
  });
}

Negotiation Flow

Initiate Negotiation

Client agent creates a negotiation session with the service agent.

Submit Proposal

Client proposes payment terms (amount, network, asset, SLA requirements).

Evaluate with Strategy

Service agent uses a pricing strategy to evaluate the proposal.

Counter or Accept

If terms are acceptable, accept. Otherwise, send a counter-offer.

Multiple Rounds

Negotiation continues until agreement or max rounds reached.

Settlement

Once accepted, proceed to atomic payment settlement.

Agent Discovery

Register an Agent

import {
  AgentRegistry,
  PriceDiscovery,
  CommonCapabilities,
} from '@t402/a2a-negotiation';
 
const registry = new AgentRegistry();
 
// Register an agent with capabilities
registry.register({
  id: 'image-gen-agent',
  name: 'AI Image Generator',
  version: '1.0.0',
  endpoints: [{
    url: 'https://api.imagegen.ai',
    protocol: 'https',
    transport: 'a2a',
  }],
  capabilities: [
    CommonCapabilities.imageGeneration('Generate images from text prompts'),
  ],
  pricing: [{
    capabilityType: 'image-generation',
    config: {
      model: 'per-request',
      basePrice: '1000000', // 1 USDC
      currency: {
        network: 'eip155:8453',
        asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bda02913',
        decimals: 6,
      },
      negotiable: true,
    },
  }],
  paymentAddress: '0xAgentWallet',
  supportedNetworks: ['eip155:8453'],
  supportedAssets: ['0x833589fCD6eDb6E08f4c7C32D4f71b54bda02913'],
});

Discover Agents

// Find agents by capability
const result = registry.discover({
  capabilityType: 'image-generation',
  networks: ['eip155:8453'],
  maxPrice: '2000000',
});
 
// Get price quotes from discovered agents
const quotes = result.agents.map(agent =>
  PriceDiscovery.getQuote(agent, {
    agentId: agent.id,
    capabilityType: 'image-generation',
    network: 'eip155:8453',
    asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bda02913',
  }),
);
 
// Find the cheapest option
const cheapest = PriceDiscovery.findCheapest(quotes);

Pricing Strategies

Built-in Strategies

StrategyDescription
AcceptAllStrategyAccepts any proposal (for testing)
FixedPriceStrategyOnly accepts at fixed price
RangePricingStrategyAccepts within price range
DynamicPricingStrategyAdjusts based on demand
GraduatedDiscountStrategyOffers discounts per round
SLAAwareStrategyPrices based on SLA requirements
CompositeStrategyCombines multiple strategies

Using Strategy Factory

import { StrategyFactory } from '@t402/a2a-negotiation';
 
// Fixed price strategy
const fixed = StrategyFactory.fixedPrice('1000000');
 
// Price range strategy
const range = StrategyFactory.priceRange(
  '500000',   // min
  '2000000',  // max
  ['eip155:8453'],
  ['0xUSDC'],
);
 
// Graduated discount (10% per round, max 30%)
const discount = StrategyFactory.graduatedDiscount(
  '1000000',  // base price
  0.1,        // discount per round
  0.3,        // max discount
);
 
// SLA-aware pricing
const sla = StrategyFactory.slaAware('1000000', {
  priorityMultiplier: 1.5,
  urgencyMultiplier: 2.0,
});

Custom Strategy

import { NegotiationStrategy, StrategyContext, StrategyEvaluation } from '@t402/a2a-negotiation';
 
class MyStrategy implements NegotiationStrategy {
  name = 'my-strategy';
 
  evaluate(context: StrategyContext): StrategyEvaluation {
    const { proposal, currentRound, maxRounds } = context;
 
    // Accept if price >= 1 USDC
    if (BigInt(proposal.proposedTerms.amount) >= BigInt('1000000')) {
      return { accept: true };
    }
 
    // Counter with minimum price
    return {
      accept: false,
      counterTerms: {
        ...proposal.proposedTerms,
        amount: '1000000',
      },
      reason: 'Price below minimum',
    };
  }
}

Escrow System

Create Escrow with Confirmation Release

import {
  EscrowManager,
  createConfirmationConditions,
} from '@t402/a2a-negotiation';
 
const escrow = new EscrowManager();
 
// Create escrow
const record = escrow.createEscrow({
  negotiationId: 'neg-123',
  payer: '0xClientWallet',
  payee: '0xServiceWallet',
  paymentTerms: {
    scheme: 'exact',
    network: 'eip155:8453',
    asset: '0xUSDC',
    amount: '1000000',
    payTo: '0xServiceWallet',
    maxTimeoutSeconds: 600,
  },
  releaseConditions: createConfirmationConditions('0xServiceWallet'),
  expirationMs: 7 * 24 * 60 * 60 * 1000, // 7 days
});
 
// Fund the escrow
escrow.fund(record.id, '0xFundingTxHash');
 
// Service confirms delivery
escrow.confirm(record.id, '0xServiceWallet', '0xSignature');
 
// Release funds
if (escrow.checkReleaseConditions(record.id)) {
  escrow.release(record.id, '0xReleaseTxHash');
}

Multi-Sig Escrow

import { createMultiSigConditions } from '@t402/a2a-negotiation';
 
const record = escrow.createEscrow({
  // ... other config
  releaseConditions: createMultiSigConditions(
    ['0xSigner1', '0xSigner2', '0xSigner3'],
    2, // Required signatures
  ),
});

Time-Locked Escrow

import { createTimeLockConditions } from '@t402/a2a-negotiation';
 
const record = escrow.createEscrow({
  // ... other config
  releaseConditions: createTimeLockConditions(
    new Date('2026-02-01T00:00:00Z'),
  ),
});

Atomic Settlement

import { AtomicSettlement } from '@t402/a2a-negotiation';
 
const settlement = new AtomicSettlement();
 
// Register a settlement handler
settlement.registerHandler({
  network: 'eip155:8453',
  async submit(request) {
    // Submit transaction to blockchain
    return { txHash: '0x...' };
  },
  async verify(txHash) {
    // Check transaction confirmation
    return { confirmed: true, confirmations: 3 };
  },
  async refund(request) {
    // Process refund
    return { txHash: '0x...' };
  },
});
 
// Create settlement from negotiation
const request = settlement.createFromNegotiation(
  negotiation.getSession(),
  paymentPayload,
);
 
// Execute settlement
const result = await settlement.execute(request.id);
 
if (result.state === 'completed') {
  console.log('Payment settled:', result.transactionHash);
}

A2A Integration

Building AgentCard with T402 Extension

import {
  AgentCardBuilder,
  CommonCapabilities,
} from '@t402/a2a-negotiation';
 
const agentCard = new AgentCardBuilder()
  .setInfo(
    'My AI Agent',
    'https://api.myagent.ai',
    'AI-powered service agent',
    '1.0.0',
  )
  .setA2ACapabilities(true, true) // streaming, pushNotifications
  .addT402Extension()
  .withT402Capabilities()
    .addCapability(
      CommonCapabilities.textGeneration(),
      {
        model: 'per-token',
        pricePerUnit: '10', // 0.00001 USDC per token
        currency: {
          network: 'eip155:8453',
          asset: '0xUSDC',
          decimals: 6,
        },
        negotiable: true,
      },
      { maxResponseTimeMs: 5000 },
    )
    .setPaymentAddress('0xMyWallet')
    .addNetwork('eip155:8453')
    .addAsset('0xUSDC')
    .build();

Processing A2A Messages

import {
  isNegotiationMessage,
  extractNegotiationMetadata,
} from '@t402/a2a-negotiation';
 
function handleA2AMessage(message: any) {
  const metadata = message.metadata ?? {};
 
  if (isNegotiationMessage(metadata)) {
    const negotiationMeta = extractNegotiationMetadata(metadata);
 
    switch (negotiationMeta?.['t402.negotiation.status']) {
      case 'negotiate-request':
        // Handle negotiation request
        break;
      case 'negotiate-counter':
        // Handle counter-offer
        break;
      case 'negotiate-accept':
        // Handle acceptance
        break;
    }
  }
}

Common Capabilities

The package provides pre-defined capability types:

import { CommonCapabilities } from '@t402/a2a-negotiation';
 
// AI/ML Capabilities
CommonCapabilities.textGeneration()
CommonCapabilities.imageGeneration(description)
CommonCapabilities.audioTranscription(description)
CommonCapabilities.codeGeneration(description)
 
// Data Capabilities
CommonCapabilities.dataQuery(description)
CommonCapabilities.dataStorage(description)
 
// API Capabilities
CommonCapabilities.apiAccess(description)
CommonCapabilities.webhookDelivery(description)

Negotiation API Reference

Negotiation Module

ExportDescription
NegotiationProtocolState machine for negotiations
NegotiationSessionSession state type
NegotiationProposalProposal schema
CounterOfferCounter-offer schema
PaymentTermsPayment terms schema
SLATermsSLA terms schema

Discovery Module

ExportDescription
AgentRegistryAgent service registry
PriceDiscoveryPrice quote and comparison
DynamicPricingManagerMarket-based pricing
AgentCardBuilderBuild T402-enabled AgentCards

Settlement Module

ExportDescription
AtomicSettlementAtomic payment settlement
ConditionalPaymentManagerConditional payments
EscrowManagerEscrow management
DisputeResolverDispute resolution