HIVE

Integrations

Custom Tools

Custom Tools

Custom tools extend your agents' capabilities by allowing them to interact with external APIs, databases, and services. This guide covers creating, testing, and deploying custom tools in HIVE Protocol.

Overview

┌─────────────────────────────────────────────────────────────────┐
│                    Custom Tools Architecture                     │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│    Agent                    Custom Tool                          │
│   ┌──────────┐             ┌─────────────────┐                  │
│   │          │  "I need    │                 │                  │
│   │  Decides │  weather    │  Weather Tool   │                  │
│   │  to use  │ ─────────▶  │  - Validate     │                  │
│   │  tool    │             │  - Call API     │                  │
│   │          │             │  - Format       │                  │
│   └──────────┘             └────────┬────────┘                  │
│        ▲                            │                            │
│        │                            ▼                            │
│        │                   ┌─────────────────┐                  │
│        │  Result           │  External API   │                  │
│        └───────────────────│  (weather.com)  │                  │
│                            └─────────────────┘                  │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Tool Types

Built-in Tools

HIVE includes several built-in tools:

ToolDescriptionUse Case
Web SearchSearch the internetResearch, fact-checking
Code ExecutorRun code snippetsData analysis, calculations
File ReaderRead uploaded filesDocument analysis
CalculatorMathematical operationsNumerical tasks

Custom Tools

Create your own tools for:

  • External API integrations
  • Database queries
  • Internal service calls
  • Specialized computations
  • Third-party service access

Creating Custom Tools

Tool Definition Structure

Every tool requires:

interface ToolDefinition {
  name: string;           // Unique identifier
  description: string;    // What the tool does (shown to AI)
  parameters: {           // JSON Schema for inputs
    type: 'object';
    properties: Record<string, ParameterSchema>;
    required: string[];
  };
  execute: (params: any) => Promise<any>;  // Implementation
}

Example: Weather API Tool

const weatherTool = {
  name: 'get_current_weather',
  description: 'Get the current weather conditions for a specific location. Returns temperature, conditions, humidity, and wind speed.',
  parameters: {
    type: 'object',
    properties: {
      location: {
        type: 'string',
        description: 'City name or address (e.g., "San Francisco, CA")'
      },
      units: {
        type: 'string',
        enum: ['celsius', 'fahrenheit'],
        description: 'Temperature units',
        default: 'fahrenheit'
      }
    },
    required: ['location']
  },
  execute: async ({ location, units = 'fahrenheit' }) => {
    const response = await fetch(
      `https://api.weatherapi.com/v1/current.json?key=${API_KEY}&q=${encodeURIComponent(location)}`
    );

    if (!response.ok) {
      throw new Error(`Weather API error: ${response.statusText}`);
    }

    const data = await response.json();

    return {
      location: data.location.name,
      country: data.location.country,
      temperature: units === 'celsius'
        ? data.current.temp_c
        : data.current.temp_f,
      units: units,
      conditions: data.current.condition.text,
      humidity: data.current.humidity,
      wind_mph: data.current.wind_mph
    };
  }
};

Example: Database Query Tool

const databaseQueryTool = {
  name: 'query_database',
  description: 'Execute a read-only SQL query against the analytics database. Only SELECT queries are allowed.',
  parameters: {
    type: 'object',
    properties: {
      query: {
        type: 'string',
        description: 'SQL SELECT query to execute'
      },
      limit: {
        type: 'number',
        description: 'Maximum rows to return',
        default: 100
      }
    },
    required: ['query']
  },
  execute: async ({ query, limit = 100 }) => {
    // Security: Only allow SELECT queries
    const normalizedQuery = query.trim().toLowerCase();
    if (!normalizedQuery.startsWith('select')) {
      throw new Error('Only SELECT queries are allowed');
    }

    // Add limit if not present
    const limitedQuery = query.includes('LIMIT')
      ? query
      : `${query} LIMIT ${limit}`;

    const { data, error } = await supabase
      .rpc('execute_readonly_query', { sql: limitedQuery });

    if (error) throw new Error(`Database error: ${error.message}`);

    return {
      rows: data,
      count: data.length,
      query: limitedQuery
    };
  }
};

Example: Slack Notification Tool

const slackNotifyTool = {
  name: 'send_slack_message',
  description: 'Send a message to a Slack channel. Use for notifications and alerts.',
  parameters: {
    type: 'object',
    properties: {
      channel: {
        type: 'string',
        description: 'Slack channel name (without #)',
        enum: ['general', 'alerts', 'team-updates']
      },
      message: {
        type: 'string',
        description: 'Message content to send'
      },
      priority: {
        type: 'string',
        enum: ['low', 'normal', 'high'],
        description: 'Message priority level',
        default: 'normal'
      }
    },
    required: ['channel', 'message']
  },
  execute: async ({ channel, message, priority = 'normal' }) => {
    const emoji = {
      low: ':information_source:',
      normal: ':speech_balloon:',
      high: ':rotating_light:'
    };

    const response = await fetch(SLACK_WEBHOOK_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        channel: `#${channel}`,
        text: `${emoji[priority]} ${message}`,
        unfurl_links: false
      })
    });

    if (!response.ok) {
      throw new Error('Failed to send Slack message');
    }

    return {
      success: true,
      channel,
      timestamp: new Date().toISOString()
    };
  }
};

Adding Tools via Dashboard

Step-by-Step Creation

  1. Navigate to Tools in the sidebar
  2. Click Create Tool
  3. Fill in the tool details:
┌─────────────────────────────────────────────────────────────────┐
│  Create Custom Tool                                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Basic Information                                               │
│  ────────────────────────────────────────────────────────────── │
│                                                                  │
│  Name (unique identifier)                                        │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ get_stock_price                                          │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│  Display Name                                                    │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ Stock Price Lookup                                       │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│  Description (for AI)                                            │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ Get real-time stock price and basic info for a ticker   │    │
│  │ symbol. Returns current price, change, and volume.      │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│  Parameters                                                      │
│  ────────────────────────────────────────────────────────────── │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ Name: symbol                                             │    │
│  │ Type: string                                             │    │
│  │ Required: Yes                                            │    │
│  │ Description: Stock ticker symbol (e.g., AAPL, GOOGL)    │    │
│  └─────────────────────────────────────────────────────────┘    │
│  [+ Add Parameter]                                               │
│                                                                  │
│  Endpoint Configuration                                          │
│  ────────────────────────────────────────────────────────────── │
│                                                                  │
│  Type: [HTTP Request v]                                          │
│                                                                  │
│  URL Template                                                    │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ https://api.stocks.com/v1/quote/{{symbol}}              │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│  Method: [GET v]                                                 │
│                                                                  │
│  Headers                                                         │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ Authorization: Bearer {{STOCK_API_KEY}}                  │    │
│  │ Content-Type: application/json                           │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│                                    [Cancel]  [Create Tool]       │
└─────────────────────────────────────────────────────────────────┘

Tool Configuration Options

OptionDescriptionExample
HTTP RequestCall external REST APIWeather API, stock prices
JavaScriptCustom code executionData transformation
DatabaseQuery internal databaseAnalytics queries
WebhookCall your own endpointCustom business logic

Testing Tools

Built-in Test Interface

Test your tools before deploying:

┌─────────────────────────────────────────────────────────────────┐
│  Test Tool: get_stock_price                                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Input Parameters                                                │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ {                                                        │    │
│  │   "symbol": "AAPL"                                      │    │
│  │ }                                                        │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│                                              [Run Test]          │
│                                                                  │
│  ─────────────────────────────────────────────────────────────  │
│                                                                  │
│  Result (234ms)                                                  │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ {                                                        │    │
│  │   "symbol": "AAPL",                                     │    │
│  │   "price": 178.42,                                      │    │
│  │   "change": +2.35,                                      │    │
│  │   "change_percent": +1.34,                              │    │
│  │   "volume": 45234567,                                   │    │
│  │   "last_updated": "2024-01-15T14:30:00Z"               │    │
│  │ }                                                        │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                  │
│  Status: SUCCESS                                                 │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Test with Different Inputs

// Test cases for your tool
const testCases = [
  { input: { symbol: 'AAPL' }, expectSuccess: true },
  { input: { symbol: 'INVALID' }, expectSuccess: false },
  { input: { symbol: '' }, expectSuccess: false },
  { input: {}, expectSuccess: false }
];

for (const testCase of testCases) {
  try {
    const result = await tool.execute(testCase.input);
    console.log(`Test passed: ${JSON.stringify(testCase.input)}`);
  } catch (error) {
    if (!testCase.expectSuccess) {
      console.log(`Test passed (expected error): ${error.message}`);
    } else {
      console.error(`Test failed: ${error.message}`);
    }
  }
}

Assigning Tools to Agents

Per-Agent Tool Assignment

┌─────────────────────────────────────────────────────────────────┐
│  Agent: Data Analyst                                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Available Tools                                                 │
│                                                                  │
│  Built-in Tools                                                  │
│  [x] Web Search                                                  │
│  [x] Calculator                                                  │
│  [ ] Code Executor                                               │
│  [x] File Reader                                                 │
│                                                                  │
│  Custom Tools                                                    │
│  [x] get_stock_price                                            │
│  [x] query_database                                             │
│  [ ] send_slack_message                                         │
│  [x] get_weather                                                │
│                                                                  │
│  Tool Permissions                                                │
│  ────────────────────────────────────────────────────────────── │
│  [ ] Require approval before tool execution                     │
│  [x] Log all tool executions                                    │
│  [ ] Limit tool calls per message (Max: ___)                    │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Tool Access in System Prompt

Agent: Data Analyst
Model: gpt-4o
System Prompt: |
  You are a data analyst with access to the following tools:
  - get_stock_price: Look up real-time stock prices
  - query_database: Query the analytics database
  - get_weather: Get current weather conditions

  Use these tools when needed to answer questions accurately.
  Always verify data before making conclusions.

Tools:
  - get_stock_price
  - query_database
  - get_weather

Security Best Practices

Input Validation

Always validate and sanitize inputs:

execute: async ({ query }) => {
  // Validate input type
  if (typeof query !== 'string') {
    throw new Error('Query must be a string');
  }

  // Sanitize input
  const sanitized = query.replace(/[;'"\\]/g, '');

  // Validate against allowed patterns
  if (!sanitized.match(/^SELECT/i)) {
    throw new Error('Only SELECT queries allowed');
  }

  // Length limits
  if (sanitized.length > 1000) {
    throw new Error('Query too long');
  }

  // Execute safely
  return executeQuery(sanitized);
}

Secret Management

Never hardcode secrets:

// BAD - Don't do this
const API_KEY = 'sk-1234567890';

// GOOD - Use environment variables
const API_KEY = process.env.EXTERNAL_API_KEY;

// BETTER - Use HIVE's secret storage
const API_KEY = await getSecret('external_api_key');

Rate Limiting

Implement rate limits on tools:

const rateLimiter = new Map();

execute: async (params) => {
  const key = `tool_${userId}`;
  const now = Date.now();
  const windowMs = 60000; // 1 minute
  const maxCalls = 10;

  const calls = rateLimiter.get(key) || [];
  const recentCalls = calls.filter(t => now - t < windowMs);

  if (recentCalls.length >= maxCalls) {
    throw new Error('Rate limit exceeded. Try again later.');
  }

  recentCalls.push(now);
  rateLimiter.set(key, recentCalls);

  // Execute tool
  return performAction(params);
}

Error Handling

Return safe error messages:

execute: async (params) => {
  try {
    return await callExternalApi(params);
  } catch (error) {
    // Log detailed error internally
    console.error('Tool error:', error);

    // Return safe message to agent
    throw new Error('Unable to complete request. Please try again.');
  }
}

Advanced Patterns

Chained Tool Calls

Tools that call other tools:

const analyzeCompanyTool = {
  name: 'analyze_company',
  description: 'Get comprehensive company analysis',
  parameters: {
    type: 'object',
    properties: {
      symbol: { type: 'string' }
    },
    required: ['symbol']
  },
  execute: async ({ symbol }, { callTool }) => {
    // Call multiple tools and combine results
    const [stock, news, financials] = await Promise.all([
      callTool('get_stock_price', { symbol }),
      callTool('get_company_news', { symbol }),
      callTool('get_financials', { symbol })
    ]);

    return {
      symbol,
      stock,
      news: news.slice(0, 5),
      financials: {
        revenue: financials.revenue,
        profit: financials.profit
      }
    };
  }
};

Streaming Results

For long-running tools:

const longRunningTool = {
  name: 'process_large_dataset',
  streaming: true,
  execute: async function* ({ dataset_id }) {
    const chunks = await getDatasetChunks(dataset_id);

    for (let i = 0; i < chunks.length; i++) {
      yield {
        progress: (i + 1) / chunks.length,
        status: `Processing chunk ${i + 1} of ${chunks.length}`
      };

      await processChunk(chunks[i]);
    }

    yield {
      progress: 1,
      status: 'Complete',
      result: await getFinalResult()
    };
  }
};

Conditional Tool Access

const restrictedTool = {
  name: 'admin_action',
  access: {
    roles: ['admin'],
    conditions: async (user, context) => {
      // Check additional conditions
      return user.verified && context.swarm.is_internal;
    }
  },
  execute: async (params) => {
    // Admin-only functionality
  }
};

Tool Monitoring

Execution Logs

View tool execution history:

┌─────────────────────────────────────────────────────────────────┐
│  Tool Executions - Last 24 Hours                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  get_stock_price                                                │
│  ├─ Executions: 156                                             │
│  ├─ Success Rate: 98.7%                                         │
│  ├─ Avg Latency: 234ms                                          │
│  └─ Errors: 2 (rate limit)                                      │
│                                                                  │
│  query_database                                                  │
│  ├─ Executions: 89                                              │
│  ├─ Success Rate: 100%                                          │
│  ├─ Avg Latency: 45ms                                           │
│  └─ Errors: 0                                                   │
│                                                                  │
│  send_slack_message                                              │
│  ├─ Executions: 34                                              │
│  ├─ Success Rate: 97.1%                                         │
│  ├─ Avg Latency: 189ms                                          │
│  └─ Errors: 1 (channel not found)                               │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Setting Up Alerts

// Configure tool monitoring alerts
const toolAlerts = {
  'get_stock_price': {
    errorThreshold: 5, // Alert after 5 errors
    latencyThreshold: 1000, // Alert if > 1 second
    notifyChannel: 'alerts'
  }
};
  • [Available Integrations](/docs/integrations/available-integrations): Integration overview
  • [Webhooks](/docs/integrations/webhooks): Event notifications
  • [Agents](/docs/agents/creating-agents): Agent configuration
  • [Tools API](/docs/api/tools-api): Tools API reference

Cookie Preferences

We use cookies to enhance your experience, analyze site traffic, and for marketing purposes. By clicking "Accept All", you consent to our use of cookies. Read our Privacy Policy for more information.