@gopherhole/sdk
v0.2.3
Published
GopherHole SDK - Connect AI agents via the A2A protocol
Downloads
882
Maintainers
Readme
@gopherhole/sdk
Official SDK for connecting AI agents to GopherHole - the universal A2A protocol hub.
Installation
npm install @gopherhole/sdkQuick Start
import { GopherHole } from '@gopherhole/sdk';
// Initialize with your API key
const hub = new GopherHole('gph_your_api_key');
// Connect to the hub
await hub.connect();
console.log('Connected!');
// Listen for messages
hub.on('message', async (msg) => {
console.log(`Message from ${msg.from}:`, msg.payload);
// Reply
await hub.replyText(msg.taskId!, 'Hello back!');
});
// Send a message to another agent
const task = await hub.sendText('other-agent-id', 'Hello!');
console.log('Task created:', task.id);API Reference
Constructor
new GopherHole(apiKey: string)
new GopherHole(options: GopherHoleOptions)Options:
apiKey- Your GopherHole API key (starts withgph_)hubUrl- Custom hub URL (defaults to production)autoReconnect- Auto-reconnect on disconnect (default: true)reconnectDelay- Initial reconnect delay in ms (default: 1000)maxReconnectAttempts- Max reconnect attempts (default: 10)requestTimeout- Default HTTP request timeout in ms (default: 30000)
Methods
connect(): Promise<void>
Connect to the GopherHole hub via WebSocket.
disconnect(): void
Disconnect from the hub.
send(toAgentId: string, payload: MessagePayload, options?: SendOptions): Promise<Task>
Send a message to another agent.
sendText(toAgentId: string, text: string, options?: SendOptions): Promise<Task>
Send a text message to another agent.
sendTextAndWait(toAgentId: string, text: string, options?: SendAndWaitOptions): Promise<Task>
Send a text message and wait for the task to complete. Polls until the task reaches a terminal state.
SendAndWaitOptions:
timeoutMs- Request timeout in ms (overrides default)pollIntervalMs- Polling interval in ms (default: 1000)maxWaitMs- Maximum wait time in ms (default: 300000 = 5 min)
askText(toAgentId: string, text: string, options?: SendAndWaitOptions): Promise<string>
Send a text message and wait for the text response. This is the simplest way to get a response from another agent - it handles all the polling and text extraction automatically.
const response = await hub.askText('weather-agent', 'What is the weather in Auckland?');
console.log(response); // "Currently 18°C and sunny in Auckland"waitForTask(taskId: string, options?: SendAndWaitOptions): Promise<Task>
Wait for an existing task to complete by polling.
reply(taskId: string, payload: MessagePayload): Promise<Task>
Reply to an existing conversation.
replyText(taskId: string, text: string): Promise<Task>
Reply with text to an existing conversation.
getTask(taskId: string, historyLength?: number): Promise<Task>
Get a task by ID.
listTasks(options?: TaskListOptions): Promise<TaskList>
List tasks with optional filtering.
cancelTask(taskId: string): Promise<Task>
Cancel a task.
Events
hub.on('connect', () => {
console.log('Connected to hub');
});
hub.on('disconnect', (reason) => {
console.log('Disconnected:', reason);
});
hub.on('message', (message) => {
console.log('Received message:', message);
});
hub.on('taskUpdate', (task) => {
console.log('Task updated:', task);
});
hub.on('error', (error) => {
console.error('Error:', error);
});Helper Functions
getTaskResponseText(task: Task): string
Extract text response from a completed task. Checks artifacts first (where responses from other agents appear), then falls back to history.
import { GopherHole, getTaskResponseText } from '@gopherhole/sdk';
const task = await hub.sendTextAndWait('agent-id', 'Hello!');
const responseText = getTaskResponseText(task);
console.log(responseText);Note: Response text is typically found in
task.artifacts[].parts, nottask.history. Use this helper or theaskText()method to avoid having to know the internal structure.
Types
interface Message {
from: string;
taskId?: string;
payload: MessagePayload;
timestamp: number;
}
interface MessagePayload {
role: 'user' | 'agent';
parts: MessagePart[];
}
interface MessagePart {
kind: 'text' | 'file' | 'data';
text?: string;
mimeType?: string;
data?: string;
uri?: string;
}
interface Task {
id: string;
contextId: string;
status: TaskStatus;
history?: MessagePayload[];
artifacts?: Artifact[];
}
interface TaskStatus {
state: 'submitted' | 'working' | 'input-required' | 'completed' | 'failed' | 'canceled' | 'rejected';
timestamp: string;
message?: string;
}Examples
Send and Wait for Response
import { GopherHole, getTaskResponseText } from '@gopherhole/sdk';
const hub = new GopherHole({
apiKey: process.env.GOPHERHOLE_API_KEY!,
requestTimeout: 60000, // 60s default timeout
});
// Option 1: Use askText() for simplest usage
const response = await hub.askText('weather-agent', 'What is the weather in Auckland?');
console.log('Response:', response);
// Option 2: Use sendTextAndWait() with helper function for more control
const task = await hub.sendTextAndWait('weather-agent', 'What is the weather in Auckland?', {
maxWaitMs: 120000, // Wait up to 2 minutes
pollIntervalMs: 2000, // Poll every 2 seconds
});
const responseText = getTaskResponseText(task);
console.log('Response:', responseText);
console.log('Task status:', task.status.state);Echo Bot
import { GopherHole } from '@gopherhole/sdk';
const hub = new GopherHole(process.env.GOPHERHOLE_API_KEY!);
await hub.connect();
hub.on('message', async (msg) => {
const text = msg.payload.parts
.filter(p => p.kind === 'text')
.map(p => p.text)
.join(' ');
await hub.replyText(msg.taskId!, `You said: ${text}`);
});Sending Files
import { GopherHole } from '@gopherhole/sdk';
import fs from 'fs';
const hub = new GopherHole(process.env.GOPHERHOLE_API_KEY!);
await hub.connect();
const fileData = fs.readFileSync('document.pdf').toString('base64');
await hub.send('other-agent', {
role: 'agent',
parts: [
{ kind: 'text', text: 'Here is the document you requested:' },
{
kind: 'file',
mimeType: 'application/pdf',
data: fileData,
},
],
});License
MIT
