Skip to main content

TypeScript SDK

The TypeScript SDK provides everything you need to build agents and interact with the Parallax control plane.

Installation

npm install @parallax/sdk-typescript

ParallaxAgent

The ParallaxAgent class is used to build agents that connect to the control plane and handle tasks.

Basic Usage

import { ParallaxAgent } from '@parallax/sdk-typescript';

const agent = new ParallaxAgent({
name: 'my-agent',
capabilities: ['text-analysis', 'summarization'],
controlPlaneUrl: 'http://localhost:8080',
});

agent.onTask(async (task) => {
const result = await processTask(task.input);
return {
result,
confidence: 0.85,
};
});

await agent.start();

Configuration Options

interface AgentConfig {
// Required
name: string; // Unique agent identifier
capabilities: string[]; // What this agent can do

// Connection
controlPlaneUrl?: string; // Control plane URL (default: env var)
reconnectInterval?: number; // MS between reconnect attempts (default: 5000)
heartbeatInterval?: number; // MS between heartbeats (default: 30000)
connectionTimeout?: number; // MS to wait for connection (default: 10000)

// Execution
maxConcurrentTasks?: number; // Parallel task limit (default: 1)
taskTimeout?: number; // MS before task times out (default: 60000)

// Metadata
metadata?: Record<string, any>; // Custom metadata
tags?: string[]; // Agent tags for filtering
}

Task Handlers

Register handlers for specific capabilities:

// Single handler for all tasks
agent.onTask(async (task) => {
return { result: 'done', confidence: 0.9 };
});

// Capability-specific handlers
agent.onTask('analysis', async (task) => {
return { result: analyze(task.input), confidence: 0.9 };
});

agent.onTask('summarization', async (task) => {
return { result: summarize(task.input), confidence: 0.85 };
});

// Default handler for unmatched capabilities
agent.onTask('*', async (task) => {
return { result: 'unhandled', confidence: 0.5 };
});

Task Object

interface Task<T = any> {
id: string; // Unique task ID
patternId: string; // Pattern that created this task
executionId: string; // Execution instance ID
capability: string; // Requested capability
input: T; // Task input data
timeout: number; // Task timeout in MS
metadata: Record<string, any>; // Additional metadata
createdAt: Date; // When task was created
}

Task Result

interface TaskResult<T = any> {
result: T; // The result data
confidence: number; // 0.0 to 1.0
metadata?: Record<string, any>; // Optional metadata
}

Events

agent.on('connected', () => {
console.log('Connected to control plane');
});

agent.on('disconnected', (reason) => {
console.log('Disconnected:', reason);
});

agent.on('reconnecting', (attempt) => {
console.log('Reconnecting, attempt:', attempt);
});

agent.on('task:received', (task) => {
console.log('Received task:', task.id);
});

agent.on('task:completed', (task, result) => {
console.log('Completed task:', task.id);
});

agent.on('task:failed', (task, error) => {
console.error('Task failed:', task.id, error);
});

agent.on('task:timeout', (task) => {
console.warn('Task timed out:', task.id);
});

agent.on('error', (error) => {
console.error('Agent error:', error);
});

Lifecycle Methods

// Start the agent
await agent.start();

// Check connection status
const isConnected = agent.isConnected();

// Get agent stats
const stats = agent.getStats();
// { tasksCompleted: 42, tasksFailed: 2, avgResponseTime: 150 }

// Graceful shutdown
await agent.stop();

// Force shutdown (doesn't wait for tasks)
await agent.stop({ force: true });

ParallaxClient

The ParallaxClient class is used to execute patterns and manage the control plane.

Basic Usage

import { ParallaxClient } from '@parallax/sdk-typescript';

const client = new ParallaxClient({
url: 'http://localhost:8080',
});

const result = await client.executePattern('sentiment-analysis', {
text: 'This product is amazing!',
});

console.log(result);
// { sentiment: 'positive', confidence: 0.92 }

Configuration

interface ClientConfig {
url: string; // Control plane URL
apiKey?: string; // API key for authentication
timeout?: number; // Default timeout in MS
retries?: number; // Number of retries on failure
retryDelay?: number; // MS between retries
logging?: {
level: 'debug' | 'info' | 'warn' | 'error';
format?: 'json' | 'text';
};
}

Execute Pattern

// Basic execution
const result = await client.executePattern('my-pattern', input);

// With options
const result = await client.executePattern('my-pattern', input, {
timeout: 60000, // Override timeout
version: '2.x', // Pattern version constraint
priority: 'high', // Execution priority
metadata: { userId: '123' }, // Custom metadata
});

Stream Pattern

For long-running patterns, stream partial results:

const stream = client.streamPattern('research-pipeline', {
query: 'quantum computing',
});

stream.on('progress', (progress) => {
console.log(`Step ${progress.step}/${progress.total}: ${progress.status}`);
});

stream.on('partial', (data) => {
console.log('Partial result:', data);
});

stream.on('complete', (result) => {
console.log('Final result:', result);
});

stream.on('error', (error) => {
console.error('Stream error:', error);
});

// Cancel if needed
stream.cancel();

Pattern Management

// List available patterns
const patterns = await client.listPatterns();
// [{ name: 'sentiment', version: '1.0.0', ... }, ...]

// Get pattern details
const pattern = await client.getPattern('sentiment-analysis');

// Get pattern by version
const pattern = await client.getPattern('sentiment-analysis', '2.0.0');

// Register a new pattern
await client.registerPattern(patternYaml);

// Update pattern
await client.updatePattern('my-pattern', updatedYaml);

// Delete pattern
await client.deletePattern('my-pattern');

Execution Management

// Get execution status
const execution = await client.getExecution(executionId);
// { id, status: 'running', progress: 0.6, ... }

// List executions
const executions = await client.listExecutions({
pattern: 'sentiment-analysis',
status: 'completed',
limit: 10,
});

// Cancel execution
await client.cancelExecution(executionId);

Agent Management (Admin)

// List connected agents
const agents = await client.listAgents();
// [{ name: 'agent-1', capabilities: [...], status: 'ready' }, ...]

// Get agent details
const agent = await client.getAgent('agent-1');

// Filter by capability
const analysts = await client.listAgents({
capability: 'analysis',
status: 'ready',
});

Type Definitions

Input/Output Types

Define types for your patterns:

interface SentimentInput {
text: string;
language?: string;
}

interface SentimentOutput {
sentiment: 'positive' | 'negative' | 'neutral';
confidence: number;
scores: {
positive: number;
negative: number;
neutral: number;
};
}

// Typed execution
const result = await client.executePattern<SentimentInput, SentimentOutput>(
'sentiment-analysis',
{ text: 'Great product!' }
);

// result is fully typed
console.log(result.sentiment); // TypeScript knows this is string

Generic Task Handler

interface AnalysisInput {
document: string;
options: {
extractEntities: boolean;
detectLanguage: boolean;
};
}

interface AnalysisOutput {
entities: string[];
language: string;
summary: string;
}

const handler: TaskHandler<AnalysisInput, AnalysisOutput> = async (task) => {
const { document, options } = task.input;

const entities = options.extractEntities
? await extractEntities(document)
: [];

const language = options.detectLanguage
? await detectLanguage(document)
: 'en';

return {
result: {
entities,
language,
summary: await summarize(document),
},
confidence: 0.88,
};
};

agent.onTask<AnalysisInput, AnalysisOutput>('analysis', handler);

Error Handling

import {
ParallaxError,
ConnectionError,
TimeoutError,
ValidationError,
PatternNotFoundError,
AgentNotFoundError,
ExecutionError,
} from '@parallax/sdk-typescript';

try {
const result = await client.executePattern('my-pattern', input);
} catch (error) {
if (error instanceof TimeoutError) {
// Pattern took too long
console.error(`Timeout after ${error.timeout}ms`);
} else if (error instanceof ValidationError) {
// Invalid input
console.error('Validation errors:', error.errors);
} else if (error instanceof PatternNotFoundError) {
// Pattern doesn't exist
console.error(`Pattern ${error.patternName} not found`);
} else if (error instanceof ExecutionError) {
// Execution failed
console.error('Execution failed:', error.reason);
console.error('Partial results:', error.partialResults);
} else if (error instanceof ConnectionError) {
// Network issues
console.error('Connection failed:', error.message);
} else {
// Unknown error
throw error;
}
}

Middleware

Add middleware to agents:

// Logging middleware
agent.use(async (task, next) => {
console.log('Starting task:', task.id);
const start = Date.now();

const result = await next(task);

console.log(`Task ${task.id} completed in ${Date.now() - start}ms`);
return result;
});

// Validation middleware
agent.use(async (task, next) => {
if (!task.input || typeof task.input !== 'object') {
throw new Error('Invalid task input');
}
return next(task);
});

// Retry middleware
agent.use(async (task, next) => {
let lastError;
for (let i = 0; i < 3; i++) {
try {
return await next(task);
} catch (error) {
lastError = error;
await sleep(1000 * (i + 1));
}
}
throw lastError;
});

Testing

Mock Agent

import { MockAgent } from '@parallax/sdk-typescript/testing';

const mockAgent = new MockAgent({
name: 'test-agent',
capabilities: ['analysis'],
});

// Set up mock responses
mockAgent.mockResponse('analysis', {
result: { sentiment: 'positive' },
confidence: 0.9,
});

// Or use a function
mockAgent.mockResponse('analysis', (task) => ({
result: processTestInput(task.input),
confidence: 0.85,
}));

Mock Client

import { MockClient } from '@parallax/sdk-typescript/testing';

const mockClient = new MockClient();

mockClient.mockPattern('sentiment-analysis', (input) => ({
sentiment: 'positive',
confidence: 0.88,
}));

// Use in tests
const result = await mockClient.executePattern('sentiment-analysis', {
text: 'test',
});

Next Steps