Skip to main content

Node.js Examples

Complete working examples for integrating the Sigmic AI API into your Node.js applications.

Setup

No additional dependencies required - uses built-in fetch (Node.js 18+).
const API_KEY = process.env.SIGMIC_API_KEY || 'sigmic_your_key_here';
const BASE_URL = 'https://api.sigmic.ai';

SSE Stream Parser

Reusable function to parse Server-Sent Events from the stream endpoint:
async function processSSEStream(taskId, handlers = {}) {
  const response = await fetch(`${BASE_URL}/api/v1/tasks/${taskId}/stream`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  });

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';
  let finalResponse = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    buffer += decoder.decode(value, { stream: true });
    const events = buffer.split('\n\n');
    buffer = events.pop() || '';

    for (const event of events) {
      if (!event.trim() || event.startsWith(':')) continue;

      const lines = event.split('\n');
      const eventType = lines[0]?.replace('event: ', '');
      const dataLine = lines[1]?.replace('data: ', '');

      if (!dataLine) continue;

      try {
        const data = JSON.parse(dataLine);

        // Call appropriate handler
        if (handlers[eventType]) {
          handlers[eventType](data);
        }

        // Capture final response
        if (eventType === 'done') {
          finalResponse = data.finalResponse;
        }
      } catch (e) {
        // Skip malformed JSON
      }
    }
  }

  return { finalResponse };
}

Create Task

async function createTask(message, options = {}) {
  const { systemPrompt, autoExecute = true, files = [] } = options;

  const formData = new FormData();
  formData.append('message', message);
  formData.append('autoExecute', String(autoExecute));

  if (systemPrompt) {
    formData.append('systemPrompt', systemPrompt);
  }

  for (const file of files) {
    formData.append('files', file);
  }

  const response = await fetch(`${BASE_URL}/api/v1/tasks`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}` },
    body: formData
  });

  const { data } = await response.json();
  const taskId = data.id;
  console.log(`Task created: ${taskId}`);

  // Stream the execution
  const result = await processSSEStream(taskId, {
    history_message: (data) => console.log(`[History] ${data.role}: ${data.content?.substring(0, 50)}...`),
    history_done: (data) => console.log(`[History] ${data.messageCount} messages, streaming: ${data.isStreaming}`),
    status: (data) => console.log(`[Status] ${data.message || data.status}`),
    thought: (data) => console.log(`[Thought] ${data.subject}`),
    content: (data) => process.stdout.write(data.text),
    tool_call: (data) => console.log(`[Tool] ${data.toolName}: ${data.status}`),
    error: (data) => console.error(`[Error] ${data.message}`),
    done: () => console.log('\n[Done]')
  });

  return { taskId, ...result };
}

Send Follow-up Message

async function sendFollowUp(taskId, message) {
  // Send the follow-up (fire-and-forget)
  await fetch(`${BASE_URL}/api/v1/tasks/${taskId}/messages`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ message })
  });

  // Stream the response
  return processSSEStream(taskId, {
    history_done: (data) => console.log(`[History] ${data.messageCount} messages loaded`),
    content: (data) => process.stdout.write(data.text),
    done: () => console.log('\n[Done]')
  });
}

Get Task Status

async function getTask(taskId) {
  const response = await fetch(`${BASE_URL}/api/v1/tasks/${taskId}`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  });

  const result = await response.json();
  if (!result.success) {
    throw new Error(result.error.message);
  }

  return result.data;
}

List Tasks

async function listTasks(limit = 50) {
  const response = await fetch(`${BASE_URL}/api/v1/tasks?limit=${limit}`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  });

  const result = await response.json();
  if (!result.success) {
    throw new Error(result.error.message);
  }

  return result.data;
}

Cancel Task

async function cancelTask(taskId) {
  const response = await fetch(`${BASE_URL}/api/v1/tasks/${taskId}`, {
    method: 'DELETE',
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  });

  const result = await response.json();
  if (!result.success) {
    throw new Error(result.error.message);
  }

  return result.data;
}

List & Download Artifacts

async function listArtifacts(taskId) {
  const response = await fetch(`${BASE_URL}/api/v1/tasks/${taskId}/artifacts`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  });

  const result = await response.json();
  if (!result.success) {
    throw new Error(result.error.message);
  }

  return result.data.files;
}

async function downloadArtifact(taskId, filePath) {
  const response = await fetch(
    `${BASE_URL}/api/v1/tasks/${taskId}/artifacts/download?path=${encodeURIComponent(filePath)}`,
    { headers: { 'Authorization': `Bearer ${API_KEY}` } }
  );

  if (!response.ok) {
    throw new Error(`Download failed: ${response.status}`);
  }

  return response.arrayBuffer();
}

Tool Approval Handler

async function createTaskWithApproval(message) {
  const formData = new FormData();
  formData.append('message', message);
  formData.append('autoExecute', 'false');

  // Create the task
  const createResponse = await fetch(`${BASE_URL}/api/v1/tasks`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}` },
    body: formData
  });

  const { data: { id: taskId } } = await createResponse.json();

  // Poll for pending approvals
  async function checkApprovals() {
    const task = await getTask(taskId);

    if (task.pendingApprovals?.length > 0) {
      for (const approval of task.pendingApprovals) {
        console.log(`Tool "${approval.toolName}" requires approval`);
        console.log('Args:', JSON.stringify(approval.args, null, 2));

        // Approve (in a real app, you'd prompt the user)
        await fetch(
          `${BASE_URL}/api/v1/tasks/${taskId}/tools/${approval.callId}/approve`,
          {
            method: 'POST',
            headers: {
              'Authorization': `Bearer ${API_KEY}`,
              'Content-Type': 'application/json'
            },
            body: JSON.stringify({ outcome: 'proceed_once' })
          }
        );
      }
    }

    if (!['completed', 'failed', 'cancelled'].includes(task.status)) {
      setTimeout(checkApprovals, 1000);
    }
  }

  // Start polling for approvals in background
  checkApprovals();

  // Stream the execution
  return processSSEStream(taskId, {
    content: (data) => process.stdout.write(data.text),
    done: () => console.log('\n[Done]')
  });
}

Complete Workflow Example

async function main() {
  console.log('=== Sigmic AI API Demo ===\n');

  // 1. Create a task
  console.log('1. Creating task...');
  const { taskId, finalResponse } = await createTask(
    'What are the three laws of robotics?'
  );
  console.log('Task ID:', taskId);
  console.log('Response:', finalResponse);

  // 2. Send follow-up (auto-restores session if expired)
  console.log('\n2. Sending follow-up...');
  const followUp = await sendFollowUp(taskId, 'Who created these laws?');
  console.log('Follow-up response:', followUp.finalResponse);

  // 3. Check task status
  console.log('\n3. Checking task status...');
  const task = await getTask(taskId);
  console.log('Status:', task.status);
  console.log('Created:', task.createdAt);
  console.log('Completed:', task.completedAt);

  // 4. List artifacts
  console.log('\n4. Listing artifacts...');
  const artifacts = await listArtifacts(taskId);
  console.log(`Found ${artifacts.length} files`);
  artifacts.forEach(f => console.log(`  - ${f.name} (${f.size} bytes)`));

  // 5. List recent tasks
  console.log('\n5. Listing recent tasks...');
  const tasks = await listTasks(5);
  console.log(`Found ${tasks.length} tasks:`);
  tasks.forEach(t => console.log(`  - ${t.id}: ${t.status}`));
}

main().catch(console.error);

File Upload Example

import { readFileSync } from 'fs';
import { Blob } from 'buffer';

async function analyzeFile(filePath, question) {
  const fileContent = readFileSync(filePath);
  const fileName = filePath.split('/').pop();
  const file = new Blob([fileContent]);

  const formData = new FormData();
  formData.append('message', question);
  formData.append('files', file, fileName);

  const response = await fetch(`${BASE_URL}/api/v1/tasks`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}` },
    body: formData
  });

  const { data: { id: taskId } } = await response.json();

  return processSSEStream(taskId, {
    content: (data) => process.stdout.write(data.text),
    done: () => console.log('\n')
  });
}

// Usage
await analyzeFile('./data.csv', 'Summarize the data in this CSV file');

Error Handling

class APIError extends Error {
  constructor(code, message) {
    super(message);
    this.code = code;
  }
}

async function makeRequest(url, options = {}) {
  const response = await fetch(url, {
    ...options,
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      ...options.headers
    }
  });

  const data = await response.json();

  if (!data.success) {
    throw new APIError(data.error.code, data.error.message);
  }

  return data;
}

// Usage with error handling
try {
  const task = await getTask('invalid-id');
} catch (error) {
  if (error.code === 'NOT_FOUND') {
    console.log('Task not found');
  } else if (error.code === 'INVALID_API_KEY') {
    console.log('Check your API key');
  } else {
    throw error;
  }
}