Skip to main content
Nevermined Payments integrates with Google A2A to enable heterogeneous multi-agent systems to authorize and charge per request between agents:
  • Discovery: publish your AI Agent Card at /.well-known/agent.json.
  • Streaming and re-subscribe: set capabilities.streaming: true for message/stream and tasks/resubscribe.
  • Authentication: credentials are sent in HTTP headers (e.g., payment-signature: <token>), not in the JSON‑RPC payload.
  • Authorization/charging: the agent emits a final event with metadata.creditsUsed; Nevermined validates and burns credits accordingly.

Architecture

Features

The libraries provide an a2a module that enables seamless integration into new or existing A2A agents, including payment-signature authentication, asynchronous task management, and push notification support. Main features:
  • Payment Signature Authentication: The server extracts access tokens from the payment-signature header and injects them into the task context.
  • Credits Validation: Validates that the user has sufficient credits before executing a task.
  • Credits Burning/Redemption: Redeem the credits specified in the result after successful execution.
  • Multi-Plan Support: Agent cards can advertise multiple plans via planIds, allowing consumers to choose which plan to subscribe to.
  • Push Notifications: Supports the A2A standard flow for push notification configuration and delivery.
  • Asynchronous Task Handling: Supports intermediate and final state events, compatible with polling and streaming.
  • Unified SDK: Provides both agent and client integration.

Quickstart

If you already have a Google A2A agent, or you are building a new one, add the Payments Library to your agent and obtain an API key:
1

1. Get Your API Key

To interact with the Nevermined API, you need an API key.
  1. Go to the Nevermined App.
  2. Log in via Web3Auth.
  3. Navigate to the Settings section in the user menu.
  4. Click on the API Keys tab.
  5. Generate a new key, give it a descriptive name, and copy it.
  6. Store this key securely as an environment variable (e.g., NVM_API_KEY).
2

2. Install and Initialize the Payments Library

Install the Payments Library and initialize the Payments client with your API key.
npm install @nevermined-io/payments

Initialize the Payments Library

import { Payments } from "@nevermined-io/payments"

const payments = Payments.getInstance({
  nvmApiKey,
  environment: 'sandbox',
})

A2A Server

Add the Payment Extension to the Agent Card

Because your AI agent charges for requests, add a payment extension to your agent card. Add a payment extension under capabilities.extensions carrying Nevermined metadata:

Single Plan

{
  "capabilities": {
    "streaming": true,
    "pushNotifications": true,
    "extensions": [
      {
        "uri": "urn:nevermined:payment",
        "description": "Dynamic cost per request",
        "required": false,
        "params": {
          "paymentType": "dynamic",
          "credits": 1,
          "planId": "<planId>",
          "agentId": "<agentId>"
        }
      }
    ]
  },
  "url": "https://your-agent.example.com/a2a/"
}

Multiple Plans

When your agent supports multiple plans, use planIds (array) instead of planId (string):
{
  "capabilities": {
    "extensions": [
      {
        "uri": "urn:nevermined:payment",
        "params": {
          "paymentType": "dynamic",
          "credits": 5,
          "planIds": ["<planId-basic>", "<planId-premium>"],
          "agentId": "<agentId>",
          "costDescription": "1-5 credits depending on request complexity"
        }
      }
    ]
  }
}
Provide either planId or planIds, not both. When multiple plans are configured, the 402 Payment Required response includes all plans in accepts[], allowing consumers to choose.
Important notes:
  • The url must match exactly the URL registered in Nevermined for the agent/plan.
  • The final streaming event must include metadata.creditsUsed with the consumed cost.

Define the Payment Agent Card in Your A2A Agent

const baseAgentCard = {
  name: 'My A2A Server',
  description: 'A2A test server that requires payment',
  capabilities: {
    streaming: true,
    pushNotifications: true,
    stateTransitionHistory: true,
  },
  defaultInputModes: ['text'],
  defaultOutputModes: ['text'],
  skills: [],
  url: 'http://localhost:3005/a2a/',
  version: '1.0.0',
}

const agentCard = payments.a2a.buildPaymentAgentCard(baseAgentCard, {
  paymentType: "dynamic",
  credits: 1,
  planId: process.env.PLAN_ID,
  agentId: process.env.AGENT_ID,
})

Start the A2A Server

The agent is initialized using the Nevermined Payments Library and the A2A protocol.

Using the Decorator (Simple)

The @a2a_requires_payment decorator is the quickest way to create a payment-protected A2A agent in Python:
// Start server on port 3005 for A2A
class Executor implements AgentExecutor {
  async handleTask(context, eventBus) {
    // Returns { result: TaskHandlerResult, expectsMoreUpdates: boolean }
  }
  async cancelTask(taskId) { /* ... */ }

  // Publishes the final status-update event when no more updates are expected
  async execute(requestContext, eventBus) {
    const { result, expectsMoreUpdates } = await this.handleTask(requestContext, eventBus)
    if (expectsMoreUpdates) return
    // Publish final status-update event...
  }
}

serverResult = await paymentsBuilder.a2a.start({
  port: 3005,
  basePath: '/a2a/',
  agentCard: agentCard,
  executor: A2AE2EFactory.createResubscribeStreamingExecutor(),
})

serverManager.addServer(serverResult)

Using PaymentsA2AServer (Advanced)

For more control over the executor and event lifecycle:
from payments_py.a2a.server import PaymentsA2AServer
from a2a.server.agent_execution import AgentExecutor
from a2a.server.events.event_queue import EventQueue

class MyExecutor(AgentExecutor):
    async def execute(self, ctx, event_queue: EventQueue):
        # Your agent logic — publish events to event_queue
        ...

    async def cancel(self, ctx, event_queue: EventQueue):
        ...

result = PaymentsA2AServer.start(
    agent_card=agent_card,
    executor=MyExecutor(),
    payments_service=payments,
    port=8080,
    base_path="/",
)

import asyncio
asyncio.run(result.server.serve())

A2A Client

The client interacts with the agent using JSON-RPC requests. It discovers available plans from the agent card, purchases a plan, obtains an access token, and sends messages.

Discovering Plans from the Agent Card


const paymentsSubscriber = Payments.getInstance({
  nvmApiKey,
  environment: 'sandbox',
})

const client = paymentsSubscriber.a2a.getClient({
  agentBaseUrl: 'http://localhost:3005/a2a/',
  agentId: process.env.AGENT_ID,
  planId: process.env.PLAN_ID
})

Sending a Task

After purchasing access to the payment plan associated with the AI agent, a client can generate an access token and start sending tasks:
// Purchase the Plan
const orderResult = await paymentsSubscriber.plans.orderPlan(planId)
// Get the X402 access token associated to the agent and plan
const { accessToken } = await paymentsSubscriber.x402.getX402AccessToken(planId, agentId)


// Test sending an A2A message with correct format
const response = await client.sendMessage(
  "Testing push notification!",
  accessToken
);
const taskId = response?.result?.id

Full example code

Find a complete working example in the repository: nevermined-io/a2a-agent-client-sample.