Node.js Examples
Complete working examples for integrating the Sigmic AI API into your Node.js applications.Setup
No additional dependencies required - uses built-infetch (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;
}
}