npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ai-spine-sdk

v2.5.4

Published

Official JavaScript SDK for AI Spine - The Stripe for AI Agent Orchestration

Downloads

112

Readme

AI Spine JavaScript SDK

The official JavaScript SDK for AI Spine - The Stripe for AI Agent Orchestration.

AI Spine makes it incredibly easy to orchestrate AI agents and build sophisticated AI workflows. Just like Stripe simplified payments, AI Spine simplifies AI agent coordination.

🚀 Quick Start

Installation

npm install ai-spine-sdk
# or
yarn add ai-spine-sdk
# or
pnpm add ai-spine-sdk

Basic usage

import { AISpine } from 'ai-spine-sdk';

// Initialize SDK (API key is optional - backend currently has API_KEY_REQUIRED=false)
const spine = new AISpine();  // Will use production API by default

// Check API health
const health = await spine.healthCheck();
console.log('API Status:', health.status);

// Execute a flow (example: credit analysis)
const result = await spine.executeFlow('credit_analysis', {
  user_query: 'Necesito un préstamo de 50000',
  amount: 50000
});

console.log('Execution started:', result.execution_id);

// Wait for completion and get results
const execution = await spine.waitForExecution(result.execution_id);
console.log('Final result:', execution.output_data);

📚 Documentation

⚠️ Important notes

  • API Status: The API is currently running at https://ai-spine-api.up.railway.app
  • Authentication: API keys are currently optional (API_KEY_REQUIRED=false)
  • Agents: No real agents are connected yet - flows will fail until agents are registered
  • Webhooks: Not implemented - use polling with waitForExecution() instead

Configuration

You can configure the SDK during initialization:

import { AISpine } from 'ai-spine-sdk';

const spine = new AISpine({
  apiKey: 'sk_test_your_api_key_here', // Optional - currently API_KEY_REQUIRED=false
  // baseURL defaults to: https://ai-spine-api.up.railway.app
  // baseURL: 'https://your-custom-api.com', // Optional: Custom API URL
  timeout: 30000, // 30 second timeout
  retries: 3, // Retry failed requests 3 times
  debug: true // Enable debug logging
});

Flow execution

Execute a flow

// Simple execution
const result = await spine.executeFlow('text-analysis', {
  text: 'Analyze this text for sentiment and topics'
});

// With custom timeout
const result = await spine.executeFlow('long-running-task', 
  { data: complexData },
  { timeout: 120000 } // 2 minute timeout
);

Wait for completion

// Wait with progress updates
const execution = await spine.waitForExecution(result.execution_id, {
  timeout: 300000, // 5 minutes
  interval: 2000,  // Check every 2 seconds
  onProgress: (execution) => {
    console.log(`Status: ${execution.status}`);
    if (execution.status === 'running') {
      console.log('Still processing...');
    }
  }
});

console.log('Final result:', execution.output_data);

Get execution status

// Get current status
const execution = await spine.getExecution('exec-123');

console.log(`Status: ${execution.status}`);
console.log(`Started: ${execution.started_at}`);

if (execution.status === 'completed') {
  console.log('Result:', execution.output_data);
} else if (execution.status === 'failed') {
  console.log('Error:', execution.error_message);
}

Flow management

List available flows

const flows = await spine.listFlows();

flows.forEach(flow => {
  console.log(`${flow.name}: ${flow.description}`);
  console.log(`Nodes: ${flow.nodes.length}`);
});

Get flow details

const flow = await spine.getFlow('customer-support');

console.log(`Flow: ${flow.name}`);
console.log(`Description: ${flow.description}`);
console.log('Nodes:');
flow.nodes.forEach(node => {
  console.log(`  - ${node.id} (${node.type}): ${node.agent_id}`);
});

Agent management

List registered agents

const agents = await spine.listAgents();

agents.forEach(agent => {
  console.log(`${agent.name} (${agent.status})`);
  console.log(`  Capabilities: ${agent.capabilities.join(', ')}`);
  console.log(`  Endpoint: ${agent.endpoint}`);
});

Register a new agent

const agent = await spine.registerAgent({
  agent_id: 'my-custom-agent',
  name: 'My Custom Agent',
  description: 'A specialized agent for custom tasks',
  endpoint: 'https://my-agent.example.com/api',
  capabilities: ['text-processing', 'data-analysis', 'custom-logic'],
  type: 'custom'
});

console.log(`Agent registered: ${agent.agent_id}`);

Test agent connection

const testResult = await spine.testAgent('https://my-agent.example.com/api');

if (testResult.connected) {
  console.log('Agent is reachable and responding');
} else {
  console.log('Agent connection failed:', testResult.message);
}

Batch processing

Execute multiple flows in parallel with automatic concurrency control:

const requests = [
  { id: '1', flowId: 'sentiment-analysis', input: { text: 'I love this product!' } },
  { id: '2', flowId: 'sentiment-analysis', input: { text: 'This is terrible.' } },
  { id: '3', flowId: 'sentiment-analysis', input: { text: 'It\'s okay, I guess.' } }
];

const results = await spine.executeBatch(requests, {
  concurrency: 2, // Process 2 at a time
  onProgress: (completed, total) => {
    console.log(`Progress: ${completed}/${total} completed`);
  },
  onItemComplete: (result) => {
    console.log(`Item ${result.id} completed:`, result.status);
  }
});

// Process results
results.forEach(result => {
  if (result.status === 'completed') {
    console.log(`${result.id}: ${JSON.stringify(result.result)}`);
  } else {
    console.log(`${result.id} failed: ${result.error}`);
  }
});

System monitoring

Health check

const health = await spine.healthCheck();

console.log(`System status: ${health.status}`);
console.log(`Version: ${health.version}`);
console.log(`Database: ${health.database}`);
console.log(`Uptime: ${health.uptime}s`);

Get metrics

const metrics = await spine.getMetrics();

console.log(`Total executions: ${metrics.total_executions}`);
console.log(`Success rate: ${(metrics.successful_executions / metrics.total_executions * 100).toFixed(1)}%`);
console.log(`Average execution time: ${metrics.average_execution_time}ms`);

Environment variables (NEW in v2.1.0)

The SDK now supports environment variable management for agents, making it easy to handle API keys, credentials, and configuration.

Register agent with environment schema

const agent = await spine.registerAgent({
  agent_id: 'restaurant_agent',
  name: 'Restaurant Reservation Agent',
  description: 'Books restaurant reservations through OpenTable',
  endpoint: 'http://localhost:8001/restaurant',
  capabilities: ['restaurant_booking', 'opentable_api'],
  environment_schema: {
    'opentable_api_key': {
      type: 'password',
      description: 'Your OpenTable API key for authentication',
      required: true,
      sensitive: true
    },
    'opentable_partner_id': {
      type: 'string',
      description: 'Your OpenTable partner ID',
      required: true,
      sensitive: false
    },
    'default_cuisine': {
      type: 'string',
      description: 'Default cuisine when none specified',
      required: false,
      default_value: 'any'
    }
  }
});

Validate environment variables

// Get environment schema for an agent
const schema = await spine.getAgentEnvironmentSchema('restaurant_agent');

// Validate environment variables
const result = await spine.validateAgentEnvironment('restaurant_agent', {
  'opentable_api_key': 'ot_live_abcd1234567890',
  'opentable_partner_id': 'partner_12345',
  'default_cuisine': 'italian'
});

if (!result.valid) {
  console.error('Validation errors:');
  result.errors.forEach(error => {
    console.error(`- ${error.field}: ${error.message}`);
  });
}

Use environment variables in flows

const flow = await spine.createFlow({
  flow_id: 'restaurant_booking',
  name: 'Restaurant Booking Flow',
  description: 'Books restaurant reservations with environment variables',
  nodes: [
    {
      id: 'book_restaurant',
      type: 'processor',
      agent_id: 'restaurant_agent',
      config: {
        system_prompt: 'Book a restaurant reservation using OpenTable API',
        environment: {
          'opentable_api_key': process.env.OPENTABLE_API_KEY,
          'opentable_partner_id': process.env.OPENTABLE_PARTNER_ID,
          'default_cuisine': 'italian'
        }
      }
    }
  ]
});

Environment field types

  • string: Regular text fields
  • number: Numeric values
  • boolean: True/false values
  • password: Sensitive fields (API keys, secrets) - handled as strings but marked as sensitive for UI

🔑 API Key Management (v2.4.0+)

The SDK now supports dual authentication for enhanced security:

  • Supabase Token: For user account management (profile, API keys)
  • API Key: For API operations (flows, agents, executions)

Secure User Account Methods (NEW - Recommended)

These methods use Supabase authentication for enhanced security:

import { AISpine } from 'ai-spine-sdk';
import { createClient } from '@supabase/supabase-js';

// Get Supabase session
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
const { data: { session } } = await supabase.auth.getSession();

// Initialize SDK with Supabase token
const spine = new AISpine({
  supabaseToken: session.access_token,  // For user account methods
  apiKey: savedApiKey,  // For API operations (when available)
  baseURL: 'https://ai-spine-api.up.railway.app'
});

// Get user profile
const profile = await spine.getUserProfile();
console.log('User:', profile.email);

// Check API key status (returns masked key)
const status = await spine.getUserApiKeyStatus();
if (!status.has_api_key) {
  console.log('No API key exists');
} else {
  console.log('Masked key:', status.api_key_masked); // sk_...abc
  console.log('Credits:', status.credits);
  console.log('Rate limit:', status.rate_limit);
}

// Generate or regenerate API key
const result = await spine.generateApiKey();
console.log('New API key:', result.api_key); // Full key - save securely!
console.log('Action:', result.action); // 'created' or 'regenerated'

// Revoke API key
const revokeResult = await spine.revokeApiKey();
console.log('Revoked:', revokeResult.message);

Complete Settings Page Implementation

import { AISpine } from 'ai-spine-sdk';
import { useAuth } from '@/hooks/useAuth'; // Your Supabase auth hook

function SettingsPage() {
  const { session } = useAuth();
  const [apiKeyStatus, setApiKeyStatus] = useState(null);
  const [newApiKey, setNewApiKey] = useState(null);
  
  // Initialize with dual authentication
  const spine = useMemo(() => new AISpine({
    supabaseToken: session?.access_token,  // For user account
    apiKey: localStorage.getItem('apiKey'),  // For API operations
    baseURL: 'https://ai-spine-api.up.railway.app'
  }), [session]);
  
  useEffect(() => {
    checkApiKeyStatus();
  }, []);
  
  const checkApiKeyStatus = async () => {
    try {
      const status = await spine.getUserApiKeyStatus();
      setApiKeyStatus(status);
    } catch (error) {
      console.error('Failed to check API key status:', error);
    }
  };
  
  const generateNewKey = async () => {
    try {
      const result = await spine.generateApiKey();
      setNewApiKey(result.api_key);
      
      // Save to secure storage
      localStorage.setItem('apiKey', result.api_key);
      
      // Update status
      await checkApiKeyStatus();
      
      toast.success(`API Key ${result.action}! Copy it now.`);
    } catch (error) {
      toast.error('Failed to generate API key');
    }
  };
  
  const revokeKey = async () => {
    if (!confirm('This will permanently delete your API key. Continue?')) return;
    
    try {
      await spine.revokeApiKey();
      localStorage.removeItem('apiKey');
      setApiKeyStatus({ has_api_key: false });
      toast.success('API key revoked');
    } catch (error) {
      toast.error('Failed to revoke API key');
    }
  };
  
  return (
    <div>
      {newApiKey && (
        <Alert>
          <p>⚠️ Save this key - you won't see it again!</p>
          <code>{newApiKey}</code>
          <button onClick={() => navigator.clipboard.writeText(newApiKey)}>
            Copy
          </button>
        </Alert>
      )}
      
      {apiKeyStatus?.has_api_key ? (
        <div>
          <p>API Key: {apiKeyStatus.api_key_masked}</p>
          <p>Credits: {apiKeyStatus.credits}</p>
          <button onClick={generateNewKey}>Regenerate</button>
          <button onClick={revokeKey}>Revoke</button>
        </div>
      ) : (
        <div>
          <p>No API key found</p>
          <button onClick={generateNewKey}>Generate API Key</button>
        </div>
      )}
    </div>
  );
}

Using Both Authentication Methods

// Page that needs both user info and API operations
const spine = new AISpine({
  supabaseToken: session.access_token,  // For user account
  apiKey: savedApiKey,  // For API operations
  baseURL: 'https://ai-spine-api.up.railway.app'
});

// User account operation (uses Supabase token)
const profile = await spine.getUserProfile();

// API operation (uses API key)
const execution = await spine.executeFlow('credit-analysis', {
  customer_id: '12345'
});

🔧 Advanced Usage

Error handling

The SDK provides detailed error classes for different scenarios:

import { 
  AISpine, 
  AuthenticationError, 
  ValidationError, 
  NotFoundError,
  TimeoutError,
  isAISpineError 
} from '@ai-spine/sdk';

try {
  const result = await spine.executeFlow('non-existent-flow', { data: 'test' });
} catch (error) {
  if (isAISpineError(error)) {
    console.log(`AI Spine Error [${error.code}]: ${error.message}`);
    
    switch (error.constructor) {
      case AuthenticationError:
        console.log('Check your API key');
        break;
      case ValidationError:
        console.log('Validation errors:', error.validationErrors);
        break;
      case NotFoundError:
        console.log('Resource not found');
        break;
      case TimeoutError:
        console.log('Request timed out, try increasing timeout');
        break;
      default:
        console.log('Details:', error.details);
    }
  } else {
    console.log('Unexpected error:', error);
  }
}

Custom configuration updates

// Update configuration at runtime
spine.updateConfig({
  timeout: 60000,
  debug: true
});

// Get current configuration
const config = spine.getConfig();
console.log('Current base URL:', config.baseURL);

Input validation and sanitization

The SDK automatically validates and sanitizes inputs:

// This will throw a ValidationError
try {
  await spine.executeFlow('invalid-flow-id!', { data: 'test' });
} catch (error) {
  console.log('Validation failed:', error.message);
}

// This will be automatically sanitized (functions removed, etc.)
const result = await spine.executeFlow('my-flow', {
  validData: 'hello',
  invalidFunction: () => console.log('this will be removed'),
  nested: {
    validNested: 'world',
    undefinedValue: undefined // This will be removed
  }
});

🌟 Examples

Customer support bot

import { AISpine } from 'ai-spine-sdk';

const spine = new AISpine(process.env.AI_SPINE_API_KEY);

async function handleCustomerMessage(message: string, customerId: string) {
  try {
    // Execute customer support flow
    const execution = await spine.executeFlow('customer-support', {
      message,
      customer_id: customerId,
      priority: 'normal'
    });

    // Wait for AI response
    const result = await spine.waitForExecution(execution.execution_id, {
      onProgress: (exec) => {
        console.log(`Processing customer request... (${exec.status})`);
      }
    });

    return {
      response: result.output_data.response,
      category: result.output_data.category,
      escalate: result.output_data.escalate || false
    };
  } catch (error) {
    console.error('Customer support error:', error);
    return {
      response: 'I apologize, but I\'m having trouble processing your request right now. Please try again later.',
      category: 'system_error',
      escalate: true
    };
  }
}

// Usage
const response = await handleCustomerMessage(
  'I want to return my order from last week',
  'cust_123456'
);

console.log('AI Response:', response.response);
if (response.escalate) {
  console.log('⚠️ This request needs human attention');
}

Content generation pipeline

async function generateContent(topic: string, style: string) {
  const requests = [
    { id: 'outline', flowId: 'content-outline', input: { topic, style } },
    { id: 'intro', flowId: 'intro-generator', input: { topic, style } },
    { id: 'conclusion', flowId: 'conclusion-generator', input: { topic, style } }
  ];

  const results = await spine.executeBatch(requests, {
    concurrency: 3, // Generate all parts in parallel
    onProgress: (completed, total) => {
      console.log(`Content generation: ${completed}/${total} parts completed`);
    }
  });

  // Combine results
  const content = {
    outline: results.find(r => r.id === 'outline')?.result,
    intro: results.find(r => r.id === 'intro')?.result,
    conclusion: results.find(r => r.id === 'conclusion')?.result
  };

  return content;
}

🔗 Environment Support

The SDK works in multiple JavaScript environments:

  • Node.js - Server-side applications
  • Browser - Client-side web applications
  • Edge Functions - Vercel, Cloudflare Workers
  • React Native - Mobile applications
  • Electron - Desktop applications

📋 TypeScript

The SDK is built with TypeScript and provides full type safety:

import { AISpine, ExecutionContext, Flow } from '@ai-spine/sdk';

const spine = new AISpine(apiKey);

// Full type inference
const flows: Flow[] = await spine.listFlows();
const execution: ExecutionContext = await spine.getExecution('exec-123');

// Type-safe input/output
interface CustomerSupportInput {
  message: string;
  customer_id: string;
  priority: 'low' | 'normal' | 'high';
}

interface CustomerSupportOutput {
  response: string;
  category: string;
  confidence: number;
  escalate: boolean;
}

// This will be fully typed
const result = await spine.executeFlow('customer-support', {
  message: 'I need help',
  customer_id: 'cust_123',
  priority: 'normal'
} as CustomerSupportInput);

📡 Available Endpoints

The SDK provides access to the following AI Spine API endpoints:

Core operations

  • executeFlow(flowId, inputData) - Execute an AI workflow
  • getExecution(executionId) - Get execution status and results
  • waitForExecution(executionId, options) - Poll until execution completes
  • cancelExecution(executionId) - Cancel a running execution

Flow management

  • listFlows() - List all available flows
  • getFlow(flowId) - Get flow details and configuration

Agent management

  • listAgents() - List all registered agents
  • createAgent(agentConfig) - Register a new agent
  • deleteAgent(agentId) - Remove an agent

System information

  • healthCheck() - Check API health status
  • getMetrics() - Get system metrics

📊 Monitoring Executions

AI Spine uses polling to check execution status. The SDK provides convenient methods to wait for completion:

// Execute and wait for completion
const result = await spine.executeFlow('analysis-flow', inputData);

// Wait with custom options
const execution = await spine.waitForExecution(result.execution_id, {
  timeout: 300000,    // Maximum wait time: 5 minutes
  interval: 2000,     // Check every 2 seconds
  onProgress: (status) => {
    console.log(`Current status: ${status.status}`);
  }
});

// Or check status manually
const status = await spine.getExecution(result.execution_id);
console.log(`Status: ${status.status}`); // 'pending' | 'running' | 'completed' | 'failed'

🐛 Debugging

Enable debug mode to see detailed request/response logs:

const spine = new AISpine({
  apiKey: 'sk_test_...',
  debug: true // This will log all HTTP requests/responses
});

// Or enable at runtime
spine.updateConfig({ debug: true });

📄 License

MIT License - see LICENSE file for details.

🤝 Contributing

We welcome contributions! Please see our contributing guidelines for details.

📞 Support