--- name: retellai-reliability-patterns description: | Implement Retell AI reliability patterns including circuit breakers, idempotency, and graceful degradation. Use when building fault-tolerant Retell AI integrations, implementing retry strategies, or adding resilience to production Retell AI services. Trigger with phrases like "retellai reliability", "retellai circuit breaker", "retellai idempotent", "retellai resilience", "retellai fallback", "retellai bulkhead". allowed-tools: Read, Write, Edit version: 1.0.0 license: MIT author: Jeremy Longshore --- # Retell AI Reliability Patterns ## Overview Production-grade reliability patterns for Retell AI integrations. ## Prerequisites - Understanding of circuit breaker pattern - opossum or similar library installed - Queue infrastructure for DLQ - Caching layer for fallbacks ## Circuit Breaker ```typescript import CircuitBreaker from 'opossum'; const retellaiBreaker = new CircuitBreaker( async (operation: () => Promise) => operation(), { timeout: 30000, errorThresholdPercentage: 50, resetTimeout: 30000, volumeThreshold: 10, } ); // Events retellaiBreaker.on('open', () => { console.warn('Retell AI circuit OPEN - requests failing fast'); alertOps('Retell AI circuit breaker opened'); }); retellaiBreaker.on('halfOpen', () => { console.info('Retell AI circuit HALF-OPEN - testing recovery'); }); retellaiBreaker.on('close', () => { console.info('Retell AI circuit CLOSED - normal operation'); }); // Usage async function safeRetell AICall(fn: () => Promise): Promise { return retellaiBreaker.fire(fn); } ``` ## Idempotency Keys ```typescript import { v4 as uuidv4 } from 'uuid'; import crypto from 'crypto'; // Generate deterministic idempotency key from input function generateIdempotencyKey( operation: string, params: Record ): string { const data = JSON.stringify({ operation, params }); return crypto.createHash('sha256').update(data).digest('hex'); } // Or use random key with storage class IdempotencyManager { private store: Map = new Map(); getOrCreate(operationId: string): string { const existing = this.store.get(operationId); if (existing && existing.expiresAt > new Date()) { return existing.key; } const key = uuidv4(); this.store.set(operationId, { key, expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), }); return key; } } ``` ## Bulkhead Pattern ```typescript import PQueue from 'p-queue'; // Separate queues for different operations const retellaiQueues = { critical: new PQueue({ concurrency: 10 }), normal: new PQueue({ concurrency: 5 }), bulk: new PQueue({ concurrency: 2 }), }; async function prioritizedRetell AICall( priority: 'critical' | 'normal' | 'bulk', fn: () => Promise ): Promise { return retellaiQueues[priority].add(fn); } // Usage await prioritizedRetell AICall('critical', () => retellaiClient.processPayment(order) ); await prioritizedRetell AICall('bulk', () => retellaiClient.syncCatalog(products) ); ``` ## Timeout Hierarchy ```typescript const TIMEOUT_CONFIG = { connect: 5000, // Initial connection request: 30000, // Standard requests upload: 120000, // File uploads longPoll: 300000, // Webhook long-polling }; async function timedoutRetell AICall( operation: 'connect' | 'request' | 'upload' | 'longPoll', fn: () => Promise ): Promise { const timeout = TIMEOUT_CONFIG[operation]; return Promise.race([ fn(), new Promise((_, reject) => setTimeout(() => reject(new Error(`Retell AI ${operation} timeout`)), timeout) ), ]); } ``` ## Graceful Degradation ```typescript interface Retell AIFallback { enabled: boolean; data: any; staleness: 'fresh' | 'stale' | 'very_stale'; } async function withRetell AIFallback( fn: () => Promise, fallbackFn: () => Promise ): Promise<{ data: T; fallback: boolean }> { try { const data = await fn(); // Update cache for future fallback await updateFallbackCache(data); return { data, fallback: false }; } catch (error) { console.warn('Retell AI failed, using fallback:', error.message); const data = await fallbackFn(); return { data, fallback: true }; } } ``` ## Dead Letter Queue ```typescript interface DeadLetterEntry { id: string; operation: string; payload: any; error: string; attempts: number; lastAttempt: Date; } class Retell AIDeadLetterQueue { private queue: DeadLetterEntry[] = []; add(entry: Omit): void { this.queue.push({ ...entry, id: uuidv4(), lastAttempt: new Date(), }); } async processOne(): Promise { const entry = this.queue.shift(); if (!entry) return false; try { await retellaiClient[entry.operation](entry.payload); console.log(`DLQ: Successfully reprocessed ${entry.id}`); return true; } catch (error) { entry.attempts++; entry.lastAttempt = new Date(); if (entry.attempts < 5) { this.queue.push(entry); } else { console.error(`DLQ: Giving up on ${entry.id} after 5 attempts`); await alertOnPermanentFailure(entry); } return false; } } } ``` ## Health Check with Degraded State ```typescript type HealthStatus = 'healthy' | 'degraded' | 'unhealthy'; async function retellaiHealthCheck(): Promise<{ status: HealthStatus; details: Record; }> { const checks = { api: await checkApiConnectivity(), circuitBreaker: retellaiBreaker.stats(), dlqSize: deadLetterQueue.size(), }; const status: HealthStatus = !checks.api.connected ? 'unhealthy' : checks.circuitBreaker.state === 'open' ? 'degraded' : checks.dlqSize > 100 ? 'degraded' : 'healthy'; return { status, details: checks }; } ``` ## Instructions ### Step 1: Implement Circuit Breaker Wrap Retell AI calls with circuit breaker. ### Step 2: Add Idempotency Keys Generate deterministic keys for operations. ### Step 3: Configure Bulkheads Separate queues for different priorities. ### Step 4: Set Up Dead Letter Queue Handle permanent failures gracefully. ## Output - Circuit breaker protecting Retell AI calls - Idempotency preventing duplicates - Bulkhead isolation implemented - DLQ for failed operations ## Error Handling | Issue | Cause | Solution | |-------|-------|----------| | Circuit stays open | Threshold too low | Adjust error percentage | | Duplicate operations | Missing idempotency | Add idempotency key | | Queue full | Rate too high | Increase concurrency | | DLQ growing | Persistent failures | Investigate root cause | ## Examples ### Quick Circuit Check ```typescript const state = retellaiBreaker.stats().state; console.log('Retell AI circuit:', state); ``` ## Resources - [Circuit Breaker Pattern](https://martinfowler.com/bliki/CircuitBreaker.html) - [Opossum Documentation](https://nodeshift.dev/opossum/) - [Retell AI Reliability Guide](https://docs.retellai.com/reliability) ## Next Steps For policy enforcement, see `retellai-policy-guardrails`.