converra
v0.2.0
Published
Official Node.js SDK for Converra - AI agent optimization platform
Maintainers
Readme
converra
Official Node.js SDK for Converra - the AI agent optimization platform.
Installation
npm install converraQuick Start
import { Converra } from 'converra';
const converra = new Converra({
apiKey: process.env.CONVERRA_API_KEY
});
// Get your optimized prompt (cached automatically)
const prompt = await converra.prompts.get('prompt_123');
console.log(prompt.content);Integration Guide
Minimal Integration
The simplest way to integrate Converra - fetch prompts and log conversations:
import { Converra } from 'converra';
const converra = new Converra({
apiKey: process.env.CONVERRA_API_KEY
});
// 1. Fetch your prompt (cached for 5 minutes by default)
const prompt = await converra.prompts.get('prompt_123');
// 2. Use the prompt in your AI application
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'system', content: prompt.content },
{ role: 'user', content: userMessage }
]
});
// 3. Log the conversation for insights
await converra.conversations.create({
promptId: 'prompt_123',
content: `User: ${userMessage}\nAssistant: ${response.choices[0].message.content}`,
status: 'completed'
});Full Integration (Recommended)
For instant variant updates when optimizations complete, add webhook handling:
import { Converra, createWebhookHandler } from 'converra';
const converra = new Converra({
apiKey: process.env.CONVERRA_API_KEY,
cache: {
strategy: 'memory', // 'memory' (default) or 'none'
ttl: 5 * 60 * 1000 // 5 minutes (default)
}
});
// Create webhook handler with automatic cache invalidation
const webhookHandler = createWebhookHandler({
secret: process.env.CONVERRA_WEBHOOK_SECRET,
// Invalidate cache when a variant is applied
onPromptUpdated: (data) => {
converra.cache.invalidate(data.promptId);
console.log(`Prompt ${data.promptId} updated - cache invalidated`);
},
// Get notified when optimization completes
onOptimizationCompleted: (data) => {
if (data.results.winningVariantId) {
console.log(`Optimization complete! ${data.results.improvementPercentage}% improvement`);
}
},
});
// Register the webhook endpoint (Express example)
app.post('/webhooks/converra', express.raw({ type: 'application/json' }), async (req, res) => {
const result = await webhookHandler(req.body, req.headers['x-converra-signature']);
res.status(result.success ? 200 : 400).json(result);
});Next.js App Router Example
// app/api/webhooks/converra/route.ts
import { createWebhookHandler } from 'converra';
import { converra } from '@/lib/converra'; // your singleton instance
const handler = createWebhookHandler({
secret: process.env.CONVERRA_WEBHOOK_SECRET!,
onPromptUpdated: (data) => converra.cache.invalidate(data.promptId),
});
export async function POST(req: Request) {
const body = await req.text();
const signature = req.headers.get('x-converra-signature') || '';
const result = await handler(body, signature);
return Response.json(result, { status: result.success ? 200 : 400 });
}Caching
The SDK includes built-in caching for prompts to minimize API calls:
const converra = new Converra({
apiKey: process.env.CONVERRA_API_KEY,
cache: {
strategy: 'memory', // Default: in-memory cache
ttl: 5 * 60 * 1000 // Default: 5 minutes
}
});
// Cached automatically
const prompt = await converra.prompts.get('prompt_123');
// Bypass cache when needed
const fresh = await converra.prompts.get('prompt_123', { bypassCache: true });
// Manual cache operations
converra.cache.invalidate('prompt_123'); // Invalidate specific prompt
converra.cache.invalidateAll(); // Clear all cached prompts
converra.cache.stats(); // { size: 5, enabled: true, ttl: 300000 }
// Disable caching entirely
const noCache = new Converra({
apiKey: process.env.CONVERRA_API_KEY,
cache: { strategy: 'none' }
});Webhook Handler
The createWebhookHandler utility provides type-safe webhook handling:
import { createWebhookHandler } from 'converra';
const handler = createWebhookHandler({
secret: process.env.CONVERRA_WEBHOOK_SECRET!,
// Prompt events
onPromptUpdated: (data) => {
// data: { promptId, promptName, updateType, variantId?, appliedAt }
},
onPromptDeleted: (data) => {
// data: { promptId, deletedAt }
},
// Optimization events
onOptimizationStarted: (data) => {
// data: { processId, promptId, status, settings, startedAt }
},
onOptimizationCompleted: (data) => {
// data: { processId, promptId, results, duration, completedAt }
},
onOptimizationStopped: (data) => {
// data: { processId, promptId, reason, stoppedAt }
},
// Insight events
onInsightsGenerated: (data) => {
// data: { conversationId, promptId, insightsId, summary, sentiment }
},
// Conversation events
onConversationCreated: (data) => {
// data: { conversationId, promptId, status, createdAt }
},
// Catch-all handler
onEvent: (event, data, metadata) => {
console.log(`Received ${event}`, data);
},
// Error handler
onError: (error, event) => {
console.error(`Webhook error for ${event}:`, error);
},
});Prompts
// List all prompts
const { data: prompts } = await converra.prompts.list();
// Get a specific prompt (cached)
const prompt = await converra.prompts.get('prompt_123');
// Create a new prompt
const newPrompt = await converra.prompts.create({
name: 'Customer Support',
content: 'You are a helpful customer support agent...',
description: 'Main support chatbot prompt',
tags: ['support', 'production']
});
// Update a prompt
await converra.prompts.update('prompt_123', {
content: 'Updated prompt content...'
});Conversations
Log conversations to generate insights and enable optimization:
// Log a completed conversation
await converra.conversations.create({
promptId: 'prompt_123',
content: `User: I need help with my order
Assistant: I'd be happy to help! Could you provide your order number?
User: It's #12345
Assistant: Found it! Your order is scheduled for delivery tomorrow.`,
llmModel: 'gpt-4',
status: 'completed'
});
// Get insights for a conversation
const insights = await converra.conversations.getInsights('conv_456');
console.log(insights.sentiment); // 'positive'
console.log(insights.topics); // ['order tracking', 'delivery']Optimizations
Automatically optimize your prompts:
// Trigger an optimization
const optimization = await converra.optimizations.trigger({
promptId: 'prompt_123',
mode: 'exploratory', // 'validation' for statistical rigor
variantCount: 3,
intent: {
targetImprovements: ['clarity', 'task completion'],
hypothesis: 'Adding examples will improve understanding'
}
});
console.log(`Optimization started: ${optimization.id}`);
// Check optimization status
const status = await converra.optimizations.get(optimization.id);
console.log(status.progress);
// Get the variants being tested
const variants = await converra.optimizations.getVariants(optimization.id);
variants.forEach(v => {
console.log(`${v.name}: ${v.metrics?.lift}% lift`);
});
// Apply the winning variant
await converra.optimizations.applyVariant(optimization.id);Webhooks
Register webhooks to receive real-time notifications:
// Register a webhook
const webhook = await converra.webhooks.create({
url: 'https://your-app.com/webhooks/converra',
events: ['optimization.completed', 'prompt.updated', 'insights.generated'],
description: 'Production webhook'
});
// Save the secret - only shown once!
console.log('Webhook secret:', webhook.secret);Available Events
| Event | Description |
|-------|-------------|
| prompt.updated | Prompt content changed (e.g., variant applied) |
| prompt.deleted | Prompt was deleted |
| optimization.started | Optimization process began |
| optimization.completed | Optimization finished with results |
| optimization.stopped | Optimization was manually stopped |
| insights.generated | New insights available for a conversation |
| conversation.created | New conversation logged |
| batch.completed | Batch operation completed |
| batch.failed | Batch operation failed |
Personas
Manage simulation personas:
// List available personas
const { data: personas } = await converra.personas.list({
tags: ['enterprise', 'frustrated']
});
// Create a custom persona
await converra.personas.create({
name: 'Impatient Executive',
description: 'A busy C-level executive who values brevity...',
tags: ['enterprise', 'impatient', 'executive']
});Insights
Get aggregated performance data:
// Get insights for a specific prompt
const insights = await converra.insights.forPrompt('prompt_123', {
days: 30
});
console.log(`Task completion: ${insights.metrics.taskCompletionRate}%`);
console.log(`Avg sentiment: ${insights.metrics.avgSentiment}`);
// Get overall insights across all prompts
const overall = await converra.insights.overall({ days: 7 });Error Handling
import { Converra, ConverraError } from 'converra';
try {
await converra.prompts.get('nonexistent');
} catch (error) {
if (error instanceof ConverraError) {
console.error(`Error ${error.code}: ${error.message}`);
console.error(`Status: ${error.statusCode}`);
console.error(`Details:`, error.details);
}
}Configuration
const converra = new Converra({
apiKey: 'cvr_live_...', // Required
baseUrl: 'https://api.converra.io/v1', // Optional, for self-hosted
timeout: 30000, // Optional, request timeout in ms
cache: {
strategy: 'memory', // Optional: 'memory' or 'none'
ttl: 300000, // Optional: cache TTL in ms
},
});TypeScript
Full TypeScript support with exported types:
import type {
Prompt,
Conversation,
Optimization,
WebhookPayload,
WebhookEvent,
PromptUpdatedPayload,
OptimizationCompletedPayload,
} from 'converra';
// Type-safe webhook handling
import { createWebhookHandler } from 'converra';
const handler = createWebhookHandler({
secret: '...',
onPromptUpdated: (data: PromptUpdatedPayload) => {
console.log(data.promptId, data.updateType);
},
});Requirements
- Node.js 18+
- A Converra API key (get one here)
Support
License
MIT
