Skip to content

nevermined-io/a2a-agent-client-sample

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A2A Payments Agent Example

This example demonstrates how to use the Nevermined payments library with the Agent2Agent (A2A) protocol, including bearer token authentication, asynchronous task management, and push notification support.

Features

  • Bearer Token Authentication: The server extracts bearer tokens from the Authorization header and injects them into the task context.
  • Credit Validation: Validates that the user has sufficient credits before executing a task.
  • Credit Burning: Burns the credits specified in the result after successful execution.
  • 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 Agent/Client: There is a single agent and client implementation.

Project Structure

src/
├── agent.ts      # A2A agent with payments, async, and push notification support
├── client.ts     # Client for interacting with the agent

Quick Start

1. Environment Setup

Create a .env file with the following variables:

PUBLISHER_API_KEY=your_publisher_api_key_here
SUBSCRIBER_API_KEY=your_subscriber_api_key_here
AGENT_ID=your_agent_id_here
PLAN_ID=your_plan_id_here
ASYNC_EXECUTION=true if the agent supports async

2. Build and Run the Agent

npm run build
node dist/agent.js

The agent will start on port 41243 by default.

3. Run the Client

node dist/client.js

The client will test various flows, including bearer token, push notification, streaming, and error handling.


Agent Initialization and Executor Definition

The agent is initialized using the Nevermined payments library and the A2A protocol. The executor defines the business logic for each type of request.

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

const paymentsService = Payments.getInstance({
  environment: "local",
  nvmApiKey: process.env.PUBLISHER_API_KEY,
});

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

class Executor implements AgentExecutor {
  async handleTask(context, eventBus) {
    // ... see agent.ts for full logic ...
    // Returns { result: TaskHandlerResult, expectsMoreUpdates: boolean }
  }
  async cancelTask(taskId) { /* ... */ }

  /**
   * Required by the A2A SDK. Publishes the result of handleTask as a final status-update event.
   * Handles asynchronous flows and ensures the correct event lifecycle.
   * @param requestContext - The task context.
   * @param eventBus - The event bus to publish events.
   */
  async execute(requestContext, eventBus) {
    // Example: see agent.ts for full implementation
    const { result, expectsMoreUpdates } = await this.handleTask(requestContext, eventBus);
    if (expectsMoreUpdates) return;
    // Publish final status-update event
    // ...
  }
}

paymentsService.a2a.start({
  agentCard,
  executor: new Executor(),
  port: 41243,
  basePath: "/a2a/",
});
  • The Executor class routes and handles all supported operations (greeting, calculation, weather, translation, streaming, push notification).
  • The handleTask method returns both the result and a boolean indicating if more updates are expected (for async flows).
  • The agent publishes the initial task, intermediate status updates, and the final event as per the A2A standard.

Client Usage: Sending Tasks and Push Notification Config

The client interacts with the agent using JSON-RPC requests. It can send messages, poll for task status, and associate push notification configs.

Sending a Task

const response = await client.sendMessage(
  "Testing push notification!",
  accessToken
);
const taskId = response?.result?.id;

Associating Push Notification Config

This functionality will work only if process.env.ASYNC_EXECUTION is set to true

const pushNotification = {
  url: "http://localhost:4000/webhook",
  token: "test-token-abc",
  authentication: {
    credentials: "test-token-abc",
    schemes: ["bearer"],
  },
};
const setResult = await client.setPushNotificationConfig(
  taskId,
  pushNotification,
  accessToken
);

Polling for Task Status

const task = await client.getTask(taskId);
console.log("Task status:", task.status.state);

Webhook Receiver Example

app.post("/webhook", async (req, res) => {
  console.log("[Webhook] Notification received:", req.body);
  const task = await client.getTask(req.body.taskId);
  console.log("[Webhook] Task:", JSON.stringify(task, null, 2));
  res.status(200).send("OK");
});

Complete Flow

  1. Client gets access token: Uses API key to call getAgentAccessToken.
  2. Client sends request: Includes access token in Authorization header using sendMessage.
  3. Agent receives and creates the task: Publishes the initial task event.
  4. Agent publishes intermediate status-update events: For long-running or async tasks, publishes status-update events with final: false.
  5. Client can poll or stream events: Using getTask or streaming endpoints.
  6. Client associates push notification config: Calls setPushNotificationConfig with the taskId.
  7. Agent publishes final status-update event: With final: true and triggers push notification if configured.
  8. Webhook receiver gets notified: When the task is completed.

CLI Instructions

Build

npm run build

Run the Agent

node dist/agent.js

Run the Client

node dist/client.js
  • The client will run all test flows: bearer token, invalid tokens, mixed scenarios, streaming, push notification, and error handling.
  • You can comment/uncomment specific tests in client.ts as needed.

Troubleshooting

  • Port conflicts: Ensure port 41243 is available.
  • Environment variables: Check that all required env vars are set.
  • API key permissions: Verify your API key has the necessary permissions.
  • Webhook not received: Ensure the push notification config is set before the task completes.
  • Streaming not working: Check that both agent and client support SSE and that events are published.

Further Reading

About

No description, website, or topics provided.

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published