a2a-browser-sdk
v0.1.0
Published
TypeScript SDK for browser user interaction with AI Agents through the A2A protocol
Maintainers
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
useA2Ahook for React applications
Installation
npm install a2a-browser-sdkQuick 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
