npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

a2a-browser-sdk

v0.1.0

Published

TypeScript SDK for browser user interaction with AI Agents through the A2A protocol

Readme

A2A Browser SDK

TypeScript SDK for browser user interaction with AI Agents through the A2A protocol.

Features

  • 🚀 Full A2A Protocol Support - Implements the complete A2A specification
  • 🔍 Agent Discovery - Three methods: Well-known URI, Registry, Direct configuration
  • 🔐 Flexible Authentication - Bearer tokens, OAuth2, API keys, or custom auth
  • 📡 Real-time Streaming - Server-Sent Events support for live updates
  • 💾 Session Persistence - Browser storage integration with auto-save
  • 💬 Chat Interface - High-level API for conversational interactions
  • 🔌 Plugin System - Extensible architecture with hooks and lifecycle events
  • 📊 Built-in Plugins - Analytics and logging plugins included
  • 🎯 Type Safety - Full TypeScript support with Zod validation
  • 🌐 Framework Agnostic - Works with React, Vue, Angular, or vanilla JS
  • ⚛️ React Hook - Ready-to-use useA2A hook for React applications

Installation

npm install a2a-browser-sdk

Quick Start

import { A2AClient, AgentDiscovery } from 'a2a-browser-sdk';

// Discover an agent
const discovery = new AgentDiscovery();
const agentCard = await discovery.fromWellKnownUri('agent.example.com');

// Initialize client
const client = new A2AClient({
  agentCard,
  auth: {
    type: 'bearer',
    token: 'your-api-token'
  }
});

// Send a message
const task = await client.message.send({
  message: {
    role: 'user',
    content: [
      {
        type: 'text',
        content: 'Hello, agent!'
      }
    ]
  }
});

// Wait for response
const completed = await client.task.waitForCompletion(task.id);
console.log('Response:', completed.messages);

Agent Discovery

The SDK supports three methods for discovering agents:

1. Well-Known URI

const discovery = new AgentDiscovery();
const agentCard = await discovery.fromWellKnownUri('agent.example.com');

2. Registry Lookup

const agentCard = await discovery.fromRegistry(
  'https://registry.a2a.io',
  'agent-123'
);

3. Direct Configuration

// From URL
const agentCard = await discovery.fromDirect('https://example.com/agent-card.json');

// Or inline
const agentCard = await discovery.fromDirect({
  protocolVersion: '0.2.9',
  name: 'My Agent',
  description: 'Custom agent',
  version: '1.0.0',
  url: 'https://api.my-agent.com',
  capabilities: {
    streaming: true,
    pushNotifications: false,
    stateTransitionHistory: false
  },
  defaultInputModes: ['text/plain'],
  defaultOutputModes: ['text/plain'],
  skills: []
});

Authentication

The SDK supports multiple authentication methods:

// Bearer token
const client = new A2AClient({
  agentCard,
  auth: {
    type: 'bearer',
    token: 'your-token'
  }
});

// API Key
const client = new A2AClient({
  agentCard,
  auth: {
    type: 'api-key',
    key: 'your-api-key',
    header: 'X-API-Key'
  }
});

// OAuth2
const client = new A2AClient({
  agentCard,
  auth: {
    type: 'oauth2',
    accessToken: 'your-access-token'
  }
});

// Custom
const client = new A2AClient({
  agentCard,
  auth: {
    type: 'custom',
    handler: async (request) => {
      request.headers.set('X-Custom-Auth', await getAuthToken());
      return request;
    }
  }
});

Working with Messages

Sending Text Messages

const task = await client.message.send({
  message: {
    role: 'user',
    content: [
      {
        type: 'text',
        content: 'What is the weather today?'
      }
    ]
  }
});

Sending Files

const task = await client.message.send({
  message: {
    role: 'user',
    content: [
      {
        type: 'text',
        content: 'Please analyze this image:'
      },
      {
        type: 'file',
        mimeType: 'image/png',
        data: base64ImageData,
        filename: 'screenshot.png'
      }
    ]
  }
});

Structured Data

const task = await client.message.send({
  message: {
    role: 'user',
    content: [
      {
        type: 'structured',
        schema: {
          type: 'object',
          properties: {
            query: { type: 'string' },
            filters: { type: 'array' }
          }
        },
        data: {
          query: 'machine learning',
          filters: ['recent', 'peer-reviewed']
        }
      }
    ]
  }
});

Task Management

Polling for Completion

const task = await client.message.send({ /* ... */ });

const completed = await client.task.waitForCompletion(task.id, {
  pollingInterval: 1000, // Check every second
  timeout: 30000 // Timeout after 30 seconds
});

Manual Task Operations

// Get task status
const task = await client.task.get('task-123');

// Cancel a task
await client.task.cancel('task-123', 'User requested cancellation');

Real-time Streaming

Stream task updates in real-time using Server-Sent Events:

const stream = client.message.stream({
  message: {
    role: 'user',
    content: [
      {
        type: 'text',
        content: 'Write a story about a robot'
      }
    ]
  }
});

// Process streaming updates
for await (const task of stream) {
  console.log(`Task state: ${task.state}`);
  
  if (task.state === 'running' && task.messages.length > 1) {
    // Get the latest assistant message
    const assistantMessage = task.messages[task.messages.length - 1];
    console.log('Assistant:', assistantMessage.content);
  }
  
  if (task.state === 'completed') {
    console.log('Task completed!');
    break;
  }
}

Capability Checking

// List all capabilities
const capabilities = client.getCapabilities();

// Check specific capability
if (client.hasCapability('text-generation')) {
  // Agent supports text generation
}

// Get capability details
const capability = client.getCapability('image-analysis');
if (capability) {
  console.log('Input schema:', capability.inputSchema);
}

Advanced Usage

Custom HTTP Options

const client = new A2AClient({
  agentCard,
  httpOptions: {
    timeout: 60000, // 1 minute timeout
    retries: 5, // Retry failed requests 5 times
    retryDelay: 2000 // Wait 2 seconds between retries
  }
});

Request Interceptors

const httpClient = new HttpClient('https://api.example.com');

// Add request interceptor
httpClient.addRequestInterceptor((config) => {
  config.headers['X-Request-ID'] = generateRequestId();
  return config;
});

// Add response interceptor
httpClient.addResponseInterceptor((response) => {
  console.log('Response received:', response);
  return response;
});

Error Handling

try {
  const task = await client.message.send({ /* ... */ });
} catch (error) {
  if (error.message.includes('Invalid message')) {
    // Handle validation error
  } else if (error.message.includes('HTTP error')) {
    // Handle network error
  } else {
    // Handle other errors
  }
}

TypeScript Support

The SDK is written in TypeScript and provides full type definitions:

import type { 
  AgentCard, 
  Task, 
  Message, 
  Capability 
} from 'a2a-browser-sdk';

Browser Support

  • Chrome/Edge 88+
  • Firefox 78+
  • Safari 14+
  • Requires ES2020 support

Session Management

Persist user sessions across page reloads:

import { SessionManager } from 'a2a-browser-sdk';

// Create session manager
const session = new SessionManager({
  storage: 'local', // or 'session'
  storageKey: 'my-app-session',
  autoSave: true,
  ttl: 86400000 // 24 hours
});

// Store data
session.set('userId', 'user-123');
session.set('preferences', { theme: 'dark' });

// Retrieve data
const userId = session.get('userId');

// Listen for changes
session.on('change', ({ key, value }) => {
  console.log(`${key} changed to:`, value);
});

Chat Interface

High-level conversational API:

import { ChatInterface } from 'a2a-browser-sdk';

// Create chat interface
const chat = new ChatInterface({
  client,
  session,
  persistMessages: true
});

// Send messages
const response = await chat.send('Hello!');

// Stream responses
await chat.stream('Tell me a story', (update) => {
  console.log(update.content);
});

// Export conversation
const exported = chat.exportConversation();

Plugin System

Extend SDK functionality with plugins:

import { PluginManager, AnalyticsPlugin, LoggerPlugin } from 'a2a-browser-sdk';

// Create plugin manager
const plugins = new PluginManager({
  client,
  session,
  config: {}
});

// Register built-in plugins
plugins.register(new AnalyticsPlugin({
  trackingId: 'UA-123456',
  endpoint: 'https://analytics.example.com'
}));

plugins.register(new LoggerPlugin({
  level: 'info',
  timestamp: true
}));

Creating Custom Plugins

import type { Plugin } from 'a2a-browser-sdk';

class MyPlugin implements Plugin {
  name = 'my-plugin';
  version = '1.0.0';
  
  install(context) {
    console.log('Plugin installed');
  }
  
  hooks = {
    beforeMessageSend: async (message) => {
      // Modify message before sending
      return { ...message, customField: true };
    },
    
    onError: async (error) => {
      // Handle errors
      console.error('Plugin error:', error);
    }
  };
}

React Hook

For React applications, use the built-in useA2A hook for a simplified integration:

import { useA2A } from 'a2a-browser-sdk/react';

function ChatComponent() {
  const {
    isConnected,
    isLoading,
    messages,
    agentCard,
    connect,
    disconnect,
    sendMessage
  } = useA2A({
    persistSession: true,
    sessionKey: 'my-chat'
  });

  // Your chat UI
}

See the React Hook documentation for detailed usage.

Complete Example

See the examples directory for complete usage examples, including a React app using the useA2A hook.

Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

License

MIT