@ceo-ai/sdk
v1.0.1
Published
Node.js SDK for CEO.AI API
Readme
SDK README
ceo-sdk/README.md
@ceo-ai/sdk
Lightweight Node.js SDK for the CEO.AI API. Zero external dependencies — uses only Node.js built-in modules.
Installation
npm install @ceo-ai/sdk Quick Start
const { CeoAI } = require('@ceo-ai/sdk');
const ceo = new CeoAI({ apiKey: 'sk_live_your_api_key_here' });
// Send a prompt and wait for the result
const { response, metadata } = await ceo.promptAndWait('What was our Q4 revenue?');
console.log(response);
// => { answer: "Q4 revenue was $12.5M, representing a 15% increase..." }
console.log(metadata);
// => { agentId: '...', agentName: 'Financial Analyst', model: 'claude-sonnet-4-5', estimatedCredits: 10} API Reference
new CeoAI(options)
Create a new client instance.
const ceo = new CeoAI({
apiKey: 'sk_live_...', // Required
endpoint: 'https://...', // Optional. Default: 'https://ingest.api.ceo.ai'
timeout: 30000, // Optional. Request timeout in ms. Default: 30000
pollInterval: 2000, // Optional. Default polling interval in ms. Default: 2000
pollTimeout: 120000 // Optional. Default polling timeout in ms. Default: 120000
}); | Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| apiKey | string | ✅ | — | Your API key (sk_live_...) |
| endpoint | string | — | https://ingest.api.ceo.ai | API endpoint URL |
| timeout | number | — | 30000 | HTTP request timeout in ms |
| pollInterval | number | — | 2000 | Default interval between poll attempts in ms |
| pollTimeout | number | — | 120000 | Default max time to wait when polling in ms |
ceo.prompt(prompt, options?)
Send a prompt to your AI agent. Returns immediately with a presigned URL where results will be written.
const result = await ceo.prompt('What was our Q4 revenue?');
console.log(result);
// {
// presignedUrl: 'https://ceo-ai-api-output-results.s3.amazonaws.com/...',
// message: 'Processing request',
// estimatedCredits: 10,
// agentId: 'abc-123',
// agentName: 'Financial Analyst',
// model: 'claude-sonnet-4-5',
// tenantId: 'tenant-456'
// } Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| prompt | string | ✅ | The prompt text to send |
| options.ragMode | boolean | — | Enable/disable RAG. Default: true (server-side) |
| options.conversationHistory | Array | — | Previous messages for context |
Returns: Promise<PromptResponse>
ceo.promptAndWait(prompt, options?)
Send a prompt and automatically poll until the result is ready. This is the most convenient method for typical usage.
const { response, metadata } = await ceo.promptAndWait('What was our Q4 revenue?', {
pollInterval: 3000,
pollTimeout: 60000,
onPoll: (attempt, elapsed) => {
console.log(`Waiting... attempt ${attempt} (${elapsed}ms)`);
}
});
console.log(response); // The AI response
console.log(metadata); // Agent/model/credits info Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| prompt | string | ✅ | The prompt text to send |
| options.ragMode | boolean | — | Enable/disable RAG |
| options.conversationHistory | Array | — | Previous messages for context |
| options.pollInterval | number | — | Override polling interval in ms |
| options.pollTimeout | number | — | Override polling timeout in ms |
| options.onPoll | Function | — | Callback: (attempt, elapsed) => {} |
Returns: Promise<{ response: any, metadata: Object }>
ceo.pollForResult(presignedUrl, options?)
Poll a presigned URL until content is available. Useful when you've stored a presigned URL from a previous prompt() call and want to check for results later.
const result = await ceo.pollForResult(presignedUrl, {
interval: 3000,
timeout: 60000,
onPoll: (attempt, elapsed) => {
console.log(`Attempt ${attempt} (${elapsed}ms elapsed)`);
}
}); Parameters:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| presignedUrl | string | ✅ | The presigned URL to poll |
| options.interval | number | — | Polling interval in ms |
| options.timeout | number | — | Max wait time in ms |
| options.onPoll | Function | — | Callback: (attempt, elapsed) => {} |
Returns: Promise<Object | string> — Parsed JSON if possible, raw string otherwise.
CeoAPIError
Custom error class thrown for API errors.
const { CeoAI, CeoAPIError } = require('@ceo-ai/sdk');
try {
await ceo.promptAndWait('Hello');
} catch (error) {
if (error instanceof CeoAPIError) {
console.log(error.message); // Error message
console.log(error.statusCode); // HTTP status code
console.log(error.details); // Additional details (if any)
// Convenience getters
error.isAuthError; // true if 401
error.isInsufficientCredits; // true if 402
error.isRateLimited; // true if 429
error.isTimeout; // true if 408
}
} Usage Examples
Simple Query
const { CeoAI } = require('@ceo-ai/sdk');
const ceo = new CeoAI({ apiKey: process.env.CEO_API_KEY });
const { response } = await ceo.promptAndWait('Summarize our sales this quarter');
console.log(response); Fire and Forget (Store URL for Later)
const { CeoAI } = require('@ceo-ai/sdk');
const ceo = new CeoAI({ apiKey: process.env.CEO_API_KEY });
// Submit the prompt
const submission = await ceo.prompt('Generate a detailed report');
console.log('Presigned URL:', submission.presignedUrl);
// Store submission.presignedUrl in your database
// ...
// Later (even in a different process), retrieve the result:
const result = await ceo.pollForResult(storedPresignedUrl);
console.log(result); Conversation History
const { CeoAI } = require('@ceo-ai/sdk');
const ceo = new CeoAI({ apiKey: process.env.CEO_API_KEY });
// First message
const first = await ceo.promptAndWait('What was our Q4 revenue?');
console.log(first.response);
// Follow-up with context
const second = await ceo.promptAndWait('How does that compare to Q3?', {
conversationHistory: [
{ role: 'user', content: 'What was our Q4 revenue?' },
{ role: 'assistant', content: JSON.stringify(first.response) }
]
});
console.log(second.response); Disable RAG Mode
const { response } = await ceo.promptAndWait('What is 2 + 2?', {
ragMode: false
}); Progress Tracking
const { response } = await ceo.promptAndWait('Complex analysis...', {
pollInterval: 3000,
pollTimeout: 300000, // 5 minutes
onPoll: (attempt, elapsed) => {
const seconds = Math.round(elapsed / 1000);
console.log(`⏳ Waiting for response... ${seconds}s (attempt ${attempt})`);
}
}); Error Handling
const { CeoAI, CeoAPIError } = require('@ceo-ai/sdk');
const ceo = new CeoAI({ apiKey: process.env.CEO_API_KEY });
try {
const { response } = await ceo.promptAndWait('What was our Q4 revenue?');
console.log(response);
} catch (error) {
if (error instanceof CeoAPIError) {
switch (true) {
case error.isAuthError:
console.error('❌ Invalid or expired API key');
console.error(' Get a new key at https://app.ceo.ai/apikeys');
break;
case error.isInsufficientCredits:
console.error('❌ Insufficient credits');
console.error(` Required: ${error.details?.requiredCredits}`);
console.error(` Available: ${error.details?.availableCredits}`);
console.error(' Add credits at https://app.ceo.ai/usercredits');
break;
case error.isTimeout:
console.error('❌ Request timed out');
console.error(' Try increasing pollTimeout');
break;
case error.isRateLimited:
console.error('❌ Rate limited. Please wait and try again.');
break;
default:
console.error(`❌ API error (${error.statusCode}): ${error.message}`);
}
} else {
console.error('❌ Unexpected error:', error.message);
}
} Express.js Integration
const express = require('express');
const { CeoAI, CeoAPIError } = require('@ceo-ai/sdk');
const app = express();
app.use(express.json());
const ceo = new CeoAI({ apiKey: process.env.CEO_API_KEY });
// Async endpoint — returns presigned URL
app.post('/api/ask', async (req, res) => {
try {
const result = await ceo.prompt(req.body.question);
res.json({
presignedUrl: result.presignedUrl,
estimatedCredits: result.estimatedCredits
});
} catch (error) {
if (error instanceof CeoAPIError) {
res.status(error.statusCode).json({ error: error.message });
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
});
// Sync endpoint — waits for result
app.post('/api/ask/sync', async (req, res) => {
try {
const { response, metadata } = await ceo.promptAndWait(req.body.question, {
pollTimeout: 60000
});
res.json({ response, metadata });
} catch (error) {
if (error instanceof CeoAPIError) {
res.status(error.statusCode).json({
error: error.message,
details: error.details
});
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
});
app.listen(3000); Batch Processing
const { CeoAI } = require('@ceo-ai/sdk');
const ceo = new CeoAI({ apiKey: process.env.CEO_API_KEY });
const questions = [
'What was Q1 revenue?',
'What was Q2 revenue?',
'What was Q3 revenue?',
'What was Q4 revenue?'
];
// Submit all prompts concurrently
const submissions = await Promise.all(
questions.map(q => ceo.prompt(q))
);
console.log(`Submitted ${submissions.length} prompts`);
// Wait a bit, then collect all results
await new Promise(r => setTimeout(r, 10000));
const results = await Promise.all(
submissions.map(s => ceo.pollForResult(s.presignedUrl, {
timeout: 60000
}))
);
results.forEach((result, i) => {
console.log(`\n--- ${questions[i]} ---`);
console.log(result);
}); Getting Your API Key
- Log in to the CEO.AI Dashboard
- Navigate to API Keys
- Click Create API Key (NB: you must have a paid subscription to create api keys)
- Select the agent you want to use
- Copy the generated key — it will only be shown once
Requirements
- Node.js 16 or later
- Zero external dependencies
License
MIT
