Skip to main content

External Sources

Connect external data sources to your knowledge base for real-time information retrieval. External sources are queried at conversation time, ensuring your AI always has access to the latest data.

How External Sources Work

Unlike documents and URLs which are indexed ahead of time, external sources are queried in real-time during conversations.

Supported Source Types

TypeDescriptionUse Case
REST APIQuery any REST endpointInternal databases, CRM, custom APIs
GraphQLQuery GraphQL endpointsComplex data relationships
DatabaseDirect database queriesReal-time inventory, user data
WebhookYour server is calledCustom logic, authentication

Add a REST API Source

POST /personalities/:personality_id/knowledge/external
{
  "name": "Product Inventory",
  "type": "rest",
  "config": {
    "base_url": "https://api.example.com",
    "endpoints": [
      {
        "name": "get_product",
        "method": "GET",
        "path": "/products/{product_id}",
        "description": "Get product details by ID"
      },
      {
        "name": "search_products",
        "method": "GET",
        "path": "/products/search",
        "params": ["query", "category"],
        "description": "Search products by name or category"
      }
    ],
    "authentication": {
      "type": "header",
      "header": "X-API-Key",
      "value": "{{API_KEY}}"
    }
  },
  "secrets": {
    "API_KEY": "your-api-key-here"
  }
}
{
  "source_id": "src_abc123",
  "name": "Product Inventory",
  "type": "rest",
  "status": "active",
  "created_at": "2024-01-15T10:30:00Z"
}

Add a Database Source

Connect directly to a database:
POST /personalities/:personality_id/knowledge/external
{
  "name": "Customer Database",
  "type": "database",
  "config": {
    "driver": "postgresql",
    "host": "db.example.com",
    "port": 5432,
    "database": "customers",
    "queries": [
      {
        "name": "get_customer",
        "description": "Get customer by email",
        "sql": "SELECT name, plan, created_at FROM customers WHERE email = :email",
        "params": ["email"]
      },
      {
        "name": "get_recent_orders",
        "description": "Get customer's recent orders",
        "sql": "SELECT * FROM orders WHERE customer_id = :customer_id ORDER BY created_at DESC LIMIT 10",
        "params": ["customer_id"]
      }
    ]
  },
  "secrets": {
    "DB_USER": "readonly_user",
    "DB_PASSWORD": "your-password"
  }
}
Supported databases: postgresql, mysql, mongodb

Add a Webhook Source

Your server handles the query:
POST /personalities/:personality_id/knowledge/external
{
  "name": "Custom Search",
  "type": "webhook",
  "config": {
    "url": "https://your-server.com/ai-search",
    "method": "POST",
    "description": "Search internal knowledge and return relevant results",
    "authentication": {
      "type": "bearer",
      "token": "{{WEBHOOK_TOKEN}}"
    }
  },
  "secrets": {
    "WEBHOOK_TOKEN": "your-webhook-token"
  }
}
When triggered, Spike sends:
{
  "query": "What's the status of order #12345?",
  "context": {
    "conversation_id": "conv_xyz",
    "user_id": "user_abc",
    "personality_id": "personality_xyz"
  }
}
Your server responds:
{
  "results": [
    {
      "content": "Order #12345 was shipped on Jan 15 and is scheduled for delivery on Jan 18.",
      "metadata": {
        "source": "order_system",
        "order_id": "12345"
      }
    }
  ]
}

Query Routing

Configure when to query each source:
PATCH /personalities/:personality_id/knowledge/external/:source_id
{
  "routing": {
    "keywords": ["order", "shipping", "delivery", "tracking"],
    "intent_patterns": ["check order status", "track package"],
    "always_query": false
  }
}
SettingDescription
keywordsQuery when these words appear
intent_patternsQuery when user intent matches
always_queryQuery on every message

List External Sources

GET /personalities/:personality_id/knowledge/external
{
  "sources": [
    {
      "source_id": "src_abc123",
      "name": "Product Inventory",
      "type": "rest",
      "status": "active",
      "stats": {
        "queries_today": 145,
        "avg_latency_ms": 89,
        "error_rate": 0.01
      }
    }
  ]
}

Test a Source

Test your source configuration:
POST /personalities/:personality_id/knowledge/external/:source_id/test
{
  "query": "What products do you have in the electronics category?"
}
{
  "success": true,
  "latency_ms": 127,
  "results": [
    {
      "content": "Found 15 products in electronics...",
      "metadata": {}
    }
  ]
}

Update Source Configuration

PATCH /personalities/:personality_id/knowledge/external/:source_id
{
  "config": {
    "endpoints": [
      {
        "name": "get_product",
        "method": "GET",
        "path": "/v2/products/{product_id}"
      }
    ]
  }
}

Rotate Secrets

Update API keys or passwords:
POST /personalities/:personality_id/knowledge/external/:source_id/secrets
{
  "secrets": {
    "API_KEY": "new-api-key"
  }
}

Disable/Enable a Source

POST /personalities/:personality_id/knowledge/external/:source_id/disable
POST /personalities/:personality_id/knowledge/external/:source_id/enable

Delete a Source

DELETE /personalities/:personality_id/knowledge/external/:source_id

Error Handling

Configure behavior when external sources fail:
{
  "error_handling": {
    "timeout_ms": 5000,
    "retry_count": 2,
    "fallback": "continue",
    "notify_on_failure": true
  }
}
SettingDescription
timeout_msMaximum wait time
retry_countNumber of retries on failure
fallback"continue" (skip source) or "error" (fail conversation)
notify_on_failureSend webhook on repeated failures

Security Best Practices

  1. Use read-only credentials - External sources should never modify data
  2. Limit query scope - Only expose necessary data
  3. Rotate secrets regularly - Update API keys periodically
  4. Monitor usage - Watch for unusual query patterns
  5. Use IP allowlisting - Restrict access to Spike’s IP ranges