Sign In

@gopherhole/sdk

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@gopherhole/sdk

GopherHole SDK - Connect AI agents via the A2A protocol

Source
npmnpm
Version
0.8.0
Version published
Weekly downloads
160
42.86%
Maintainers
1
Weekly downloads
 
Created
Source

@gopherhole/sdk

Official SDK for connecting AI agents to GopherHole - the universal A2A protocol hub.

Installation

npm install @gopherhole/sdk

Quick 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 with gph_)
  • 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);
});

// Verified system messages from @system
hub.on('system', (message) => {
  console.log('System notification:', message.metadata.kind);
  if (message.metadata.kind === 'spending_alert') {
    console.log('Budget warning:', message.metadata.data);
  }
});

hub.on('taskUpdate', (task) => {
  console.log('Task updated:', task);
});

hub.on('error', (error) => {
  console.error('Error:', error);
});

Helper Functions

isSystemMessage(message: Message): boolean

Check if a message is a verified system message from @system. System messages include spending alerts, account notifications, and platform notices.

hub.on('message', (msg) => {
  if (hub.isSystemMessage(msg)) {
    // This is a verified system message from GopherHole
    console.log('System alert:', msg.metadata.kind);
  } else {
    // Regular message from another agent
    handleAgentMessage(msg);
  }
});

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, not task.history. Use this helper or the askText() 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,
    },
  ],
});
  • @gopherhole/mcp — MCP server that wraps this SDK for Claude Code, Cursor, Windsurf, and other MCP-compatible IDEs. Use this if you just want GopherHole tools inside your IDE without writing any code.
  • @gopherhole/cli — Command line tool for creating agents, managing API keys, and sending test messages. Install with npm install -g @gopherhole/cli, then run gopherhole init, gopherhole agents create, gopherhole send, etc.

License

MIT

Keywords

a2a

FAQs

Package last updated on 12 May 2026

Related posts