Skip to main content

TypeScript SDK user guide

The Crusoe AI Platform TypeScript/Node.js SDK provides strongly typed, async/await interfaces for building frontend and backend applications on Node.js and modern JavaScript runtimes.


Installation​

The SDK is served as an npm pack tarball from your own platform's www host. Download it, verify its checksum, then install:

curl -fsSLO https://www.codyhill.net/sdk/typescript/crusoe-ai-platform-0.1.0.tgz
curl -fsSL https://www.codyhill.net/sdk/typescript/checksums.txt \
| grep crusoe-ai-platform-0.1.0.tgz | sha256sum -c -
npm install ./crusoe-ai-platform-0.1.0.tgz

npm records "@crusoe-ai/platform": "file:crusoe-ai-platform-0.1.0.tgz" in your package.json, so keep the tarball beside it (or re-download and re-verify it in CI). Install an SDK is the full guide.

npm install @crusoe-ai/platform will not work, and should not

The package is not on npm during the private beta, and nobody has registered the @crusoe-ai scope. A public-registry install of this name fetches somebody else's package, not ours. npm has no equivalent of pip's URL fragment, so do not shorten the three commands above to npm install https://…/crusoe-ai-platform-0.1.0.tgz either — that installs with nothing checking what arrived.

Requirements​

  • Node.js 18.0.0 or higher — the examples below call the built-in global fetch, so there is no HTTP client to install
  • TypeScript 4.5+ (if using TypeScript)

Authentication & Configuration​

The SDK reads CAI_API_KEY and CAI_PROJECT from process.env, or you can pass configuration explicitly:

import { Configuration } from '@crusoe-ai/platform';

const config = new Configuration({
basePath: process.env.CAI_API || 'https://api.codyhill.net',
headers: {
Authorization: `Bearer ${process.env.CAI_API_KEY || 'cai_pk_live_1234567890abcdef'}`
}
});

Code examples by service​

1. Agents​

Invoke agents asynchronously, handle streamed server-sent events, list user sessions, and memorize agent interactions.

const apiBase = process.env.CAI_API || 'https://api.codyhill.net';
const apiKey = process.env.CAI_API_KEY || 'cai_pk_live_1234567890abcdef';
const projectId = process.env.CAI_PROJECT || '0191f2c4-7777-7c3d-8e4f-5a6b7c8d9e0f';

const headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};

// 1. Synchronous agent invocation
async function invokeAgent(agentName: string, prompt: string, sessionId = 'sess_ts_001') {
const url = `${apiBase}/v1/agents/${agentName}/invoke?project=${projectId}`;
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ prompt, session_id: sessionId, user_id: 'user_node' })
});

const data = await response.json();
console.log('Agent Response:', data.response);
return data;
}

// 2. Streaming agent invocation (NDJSON)
async function invokeAgentStream(agentName: string, prompt: string, sessionId = 'sess_ts_001') {
const url = `${apiBase}/v1/agents/${agentName}/invoke/stream?project=${projectId}`;
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ prompt, session_id: sessionId })
});

if (!response.body) return;

for await (const chunk of response.body) {
const lines = chunk.toString().split('\n').filter(Boolean);
for (const line of lines) {
const parsed = JSON.parse(line);
if (parsed.text) {
process.stdout.write(parsed.text);
}
}
}
console.log();
}

// 3. Memorize session transcript
async function memorizeSession(agentName: string, sessionId: string) {
const url = `${apiBase}/v1/agents/${agentName}/sessions/${sessionId}/memorize?project=${projectId}`;
const response = await fetch(url, { method: 'POST', headers });
console.log('Memorize Status:', response.status);
}

// Example Execution
(async () => {
await invokeAgent('research-assistant', 'Explain vector database indexes.');
await memorizeSession('research-assistant', 'sess_ts_001');
})();

2. VectorDB​

Create vector indexes, upsert vector embeddings, query similar points, and scroll point collections.

const vectorBase = process.env.CAI_VECTORDB_API || 'https://api.codyhill.net';
const apiKey = process.env.CAI_API_KEY || 'cai_pk_live_1234567890abcdef';
const projectId = process.env.CAI_PROJECT || '0191f2c4-7777-7c3d-8e4f-5a6b7c8d9e0f';

const headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};

interface VectorPoint {
id: string;
vector: number[];
payload?: Record<string, any>;
}

// 1. Create a VectorDB index
async function createIndex(indexName: string, dimension = 1536) {
const url = `${vectorBase}/v1/projects/${projectId}/indexes`;
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ name: indexName, dimension, metric: 'cosine' })
});
console.log('Index created with status:', response.status);
}

// 2. Upsert vector points
async function upsertPoints(indexName: string, points: VectorPoint[]) {
const url = `${vectorBase}/v1/projects/${projectId}/indexes/${indexName}:upsert`;
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ points })
});
const data = await response.json();
console.log('Upsert result:', data);
}

// 3. Query vector similarity
async function queryVector(indexName: string, vector: number[], topK = 5) {
const url = `${vectorBase}/v1/projects/${projectId}/indexes/${indexName}:query`;
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ vector, top_k: topK, include_payload: true })
});
const data = await response.json();
console.log('Found matches:', data.matches?.length || 0);
return data;
}

// Example Execution
(async () => {
const samplePoints: VectorPoint[] = [
{
id: 'doc_101',
vector: new Array(1536).fill(0.02),
payload: { source: 'docs', topic: 'typescript-sdk' }
}
];
await upsertPoints('kb-ts-index', samplePoints);
await queryVector('kb-ts-index', new Array(1536).fill(0.02));
})();

3. Functions​

Trigger serverless functions, read output values, and tail function logs.

const apiBase = process.env.CAI_API || 'https://api.codyhill.net';
const apiKey = process.env.CAI_API_KEY || 'cai_pk_live_1234567890abcdef';
const projectId = process.env.CAI_PROJECT || '0191f2c4-7777-7c3d-8e4f-5a6b7c8d9e0f';

const headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};

// 1. Execute function
async function executeFunction(functionName: string, payload: Record<string, any>) {
const url = `${apiBase}/v1/agents/${functionName}/invoke?project=${projectId}`;
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify(payload)
});
const result = await response.json();
console.log('Function Execution Output:', result);
return result;
}

// 2. Fetch logs
async function getLogs(functionName: string) {
const url = `${apiBase}/v1/agents/${functionName}/logs?project=${projectId}`;
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const logs = await response.text();
console.log('Function Logs:\n', logs);
}

// Example execution
(async () => {
await executeFunction('image-resizer', { width: 800, height: 600, image_url: 'https://example.com/img.png' });
await getLogs('image-resizer');
})();

4. Secrets​

Manage secrets using @crusoe-ai/platform TypeScript API bindings.

import {
Configuration,
SecretsApi,
BindingsApi,
CreateSecretRequest,
PutBindingRequest
} from '@crusoe-ai/platform';

const config = new Configuration({
basePath: process.env.CAI_API || 'https://api.codyhill.net',
headers: {
Authorization: `Bearer ${process.env.CAI_API_KEY || 'cai_pk_live_1234567890abcdef'}`
}
});

const projectId = '0191f2c4-7777-7c3d-8e4f-5a6b7c8d9e0f';

async function manageSecrets() {
const secretsApi = new SecretsApi(config);
const bindingsApi = new BindingsApi(config);

// 1. Create a secret
const createReq: CreateSecretRequest = {
name: 'github-token',
value: 'ghp_1234567890abcdefghijklmnopqrstuvwxyz'
};
const secret = await secretsApi.createProjectSecret({ projectID: projectId, createSecretRequest: createReq });
console.log(`Created secret ${secret.name}, version: ${secret.version}`);

// 2. Bind secret to an agent
const bindReq: PutBindingRequest = {
secretName: 'github-token'
};
await bindingsApi.putAgentSecretBinding({
projectID: projectId,
agent: 'ci-bot',
envName: 'GITHUB_TOKEN',
putBindingRequest: bindReq
});
console.log('Bound secret to ci-bot');

// 3. Apply secret bindings
const applyResult = await bindingsApi.applyAgentSecretBindings({
projectID: projectId,
agent: 'ci-bot'
});
console.log('Applied bindings result:', applyResult);

// 4. Reveal secret value (Admin only, audited)
const revealed = await secretsApi.revealSecret({
projectID: projectId,
name: 'github-token'
});
console.log('Revealed secret:', revealed.value);
}

manageSecrets().catch(console.error);

5. MemoryStore​

Manage Redis-compatible instances, check live server metrics, and rotate instance keys.

const memBase = process.env.CAI_MEMORYSTORE_API || 'https://api.codyhill.net';
const apiKey = process.env.CAI_API_KEY || 'cai_pk_live_1234567890abcdef';
const projectId = process.env.CAI_PROJECT || '0191f2c4-7777-7c3d-8e4f-5a6b7c8d9e0f';

const headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};

// 1. Create instance
async function createStore(instanceName: string) {
const url = `${memBase}/v1/projects/${projectId}/memorystores`;
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ name: instanceName, max_memory_mb: 256 })
});
const data = await response.json();
console.log('MemoryStore Endpoint:', data.endpoint);
return data;
}

// 2. Fetch stats
async function getStoreStats(instanceName: string) {
const url = `${memBase}/v1/projects/${projectId}/memorystores/${instanceName}/stats`;
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const stats = await response.json();
console.log('MemoryStore connected clients:', stats.connected_clients);
}

(async () => {
await createStore('session-cache');
await getStoreStats('session-cache');
})();

6. PubSub​

Publish message objects, pull unacknowledged messages, and acknowledge processed IDs.

const pubsubBase = process.env.CAI_PUBSUB_API || 'https://api.codyhill.net';
const apiKey = process.env.CAI_API_KEY || 'cai_pk_live_1234567890abcdef';
const projectId = process.env.CAI_PROJECT || '0191f2c4-7777-7c3d-8e4f-5a6b7c8d9e0f';

const headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};

// 1. Publish message
async function publishMessage(topic: string, dataObj: Record<string, any>) {
const url = `${pubsubBase}/v1/projects/${projectId}/topics/${topic}:publish`;
const encoded = Buffer.from(JSON.stringify(dataObj)).toString('base64');

const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({
messages: [{ data: encoded, attributes: { env: 'production' } }]
})
});
const res = await response.json();
console.log('Published message IDs:', res.message_ids);
}

// 2. Pull messages
async function pullMessages(topic: string, subscription: string) {
const url = `${pubsubBase}/v1/projects/${projectId}/topics/${topic}/subscriptions/${subscription}:pull`;
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ max_messages: 10 })
});
const data = await response.json();
const ackIds: string[] = [];

for (const msg of data.received_messages || []) {
const raw = Buffer.from(msg.message.data, 'base64').toString('utf-8');
console.log('Received Message Payload:', JSON.parse(raw));
ackIds.push(msg.ack_id);
}
return ackIds;
}

// 3. Acknowledge messages
async function acknowledgeMessages(topic: string, subscription: string, ackIds: string[]) {
if (ackIds.length === 0) return;
const url = `${pubsubBase}/v1/projects/${projectId}/topics/${topic}/subscriptions/${subscription}:acknowledge`;
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ack_ids: ackIds })
});
console.log('Ack Response Status:', response.status);
}

// Example execution
(async () => {
await publishMessage('order-events', { order_id: 'ord_123', total: 49.99 });
const acks = await pullMessages('order-events', 'order-processor');
await acknowledgeMessages('order-events', 'order-processor', acks);
})();

Error handling​

Errors are returned as standard JavaScript Error objects or HTTP status codes:

try {
// Call SDK endpoint
} catch (error: any) {
console.error('API Error Message:', error.message);
if (error.response) {
console.error('HTTP Status:', error.response.status);
console.error('Request ID:', error.response.headers.get('x-request-id'));
}
}