Skip to content

AI Event Prediction

The Mind-Reading Waiter Analogy

You go to your favorite restaurant every week. The waiter notices:

  • You always order coffee → then breakfast
  • You order salad → then ask for extra dressing
  • You finish meal → then request the check

After a few visits, the smart waiter predicts your needs:

  • Brings coffee without asking
  • Places dressing on the table preemptively
  • Has check ready when you finish

Nexus does this for your events.

The Problem: Repetitive User Behavior

Users follow predictable patterns:

  • View product → Add to cart (80% of the time)
  • Search "nike shoes" → Click first result (65%)
  • Open settings → Change theme (50%)

Traditional systems waste opportunities:

  • No prefetching → slow page loads
  • No pre-warming → cold caches
  • No anticipation → reactive, not proactive

The Solution: Markov Chain Learning

Nexus tracks event sequences and predicts what comes next:

typescript
const bus = new Nexus({
  predictionThreshold: 0.7, // Emit prediction at 70% confidence
  debug: true
});

// User behavior creates patterns
bus.emit('product:view', { id: 123 });
bus.emit('product:add-to-cart', { id: 123 });

bus.emit('product:view', { id: 456 });
bus.emit('product:add-to-cart', { id: 456 });

// After learning, Nexus predicts
bus.emit('product:view', { id: 789 });
// → Automatically emits: 'prediction:product:add-to-cart'

How Prediction Works

Markov Chain Model:

product:view → product:add-to-cart: 15 times
product:view → product:close: 5 times
product:view → search:new: 5 times

Probability of "add-to-cart" = 15/25 = 60%

Basic Example: Search Prefetching

typescript
const bus = new Nexus({
  predictionThreshold: 0.75  // 75% confidence
});

// Listen for predictions
bus.on('prediction:search:results', (data) => {
  // User typed "nike" and usually searches for "nike shoes"
  // Prefetch results now!
  prefetchSearchResults(data.originalPayload.query + ' shoes');
});

// User types
bus.emit('search:query', { query: 'nike' });
// After learning pattern, Nexus emits:
// 'prediction:search:results' with high confidence

Real-World Example: E-Commerce Optimization

typescript
const bus = new Nexus({
  predictionThreshold: 0.7,
  debug: true
});

// === LEARNING PHASE ===
// Track user journey
bus.on('product:view', (product) => {
  analytics.track('Product Viewed', product);
});

bus.on('product:add-to-cart', (product) => {
  analytics.track('Added to Cart', product);
});

// === PREDICTION PHASE ===
bus.on('prediction:product:add-to-cart', (data) => {
  console.log(`User likely to add to cart (${(data.probability*100).toFixed(0)}%)`);
  
  // Prefetch cart API
  fetch(`/api/cart?productId=${data.originalPayload.id}`);
  
  // Pre-warm inventory check
  checkInventory(data.originalPayload.id);
  
  // Show "Quick Add" button with animation
  showQuickAddButton(data.originalPayload.id);
});

bus.on('prediction:checkout:process', (data) => {
  // User likely to checkout - prefetch shipping calculations
  prefetchShippingRates();
  
  // Pre-load payment form
  initializePaymentSDK();
});

Real-World Example: Dashboard Preloading

typescript
const bus = new Nexus({ predictionThreshold: 0.65 });

// User navigates through dashboard tabs
bus.on('tab:switch', (tab) => {
  loadTabData(tab.name);
});

// Prediction listener
bus.on('prediction:tab:switch', (data) => {
  const likelyNextTab = predictNextTab(data);
  
  // Prefetch data in background
  bus.emit('data:prefetch', { tab: likelyNextTab }, { priority: 'background' });
});

bus.on('data:prefetch', async (payload) => {
  const data = await fetch(`/api/tabs/${payload.tab}`);
  cacheTabData(payload.tab, await data.json());
  console.log(`Prefetched ${payload.tab} (will load instantly when clicked)`);
});

Edge Case: Cold Start (No Data)

What if user is new (no patterns learned)?

typescript
// Nexus gracefully handles cold start
const bus = new Nexus({ predictionThreshold: 0.7 });

// First visit - no predictions (not enough data)
bus.emit('page:home', {});
bus.emit('page:products', {});

// No 'prediction:*' events emitted yet

// After 10+ transitions, predictions start appearing

Edge Case: Prediction Loops

Can predictions create infinite loops?

typescript
// NO - Predictions are ignored by the AI engine
bus.emit('product:view', { id: 123 });
// ^ This is learned

bus.emit('prediction:product:add-to-cart', { ... });
// ^ This is NOT learned (events starting with 'prediction:' are skipped)

Safety mechanism:

typescript
if (this.config.predictionThreshold > 0 && !eventName.startsWith('prediction:')) {
  this.learnAndPredict(eventName, payload);
}

Pattern: Confidence-Based Actions

Different actions at different confidence levels:

typescript
bus.on('prediction:checkout:process', (data) => {
  if (data.probability > 0.9) {
    // Very confident - auto-open checkout
    window.location.href = '/checkout';
  } else if (data.probability > 0.7) {
    // Somewhat confident - show prompt
    showCheckoutPrompt();
  } else {
    // Low confidence - just prefetch
    prefetchCheckoutData();
  }
});

Pattern: A/B Testing with Predictions

typescript
const bus = new Nexus({ predictionThreshold: 0.75 });

bus.on('prediction:product:add-to-cart', (data) => {
  // Randomly show different UX for high-intent users
  if (Math.random() < 0.5) {
    // Variant A: Show modal
    showQuickAddModal(data.originalPayload.id);
  } else {
    // Variant B: Highlight button
    highlightAddButton(data.originalPayload.id);
  }
  
  // Track which works better
  analytics.track('Prediction Shown', {
    variant: Math.random() < 0.5 ? 'A' : 'B',
    probability: data.probability
  });
});

Testing Predictions

typescript
import { describe, it, expect } from 'vitest';
import { Nexus } from '@caeligo/nexus-orchestrator';

describe('AI Prediction', () => {
  it('should predict after learning pattern', async () => {
    const bus = new Nexus({ predictionThreshold: 0.6 });
    
    let predictionEmitted = false;
    bus.on('prediction:step2', () => {
      predictionEmitted = true;
    });
    
    // Train the model
    for (let i = 0; i < 10; i++) {
      bus.emit('step1', {});
      bus.emit('step2', {});
    }
    
    // Trigger prediction
    bus.emit('step1', {});
    
    await new Promise(resolve => setTimeout(resolve, 100));
    
    expect(predictionEmitted).toBe(true);
  });
});

Performance Considerations

Memory: Transition map grows with unique event pairs. Typically ~1KB per 100 events.

CPU: Probability calculation is O(n) where n = possible next events (usually < 10).

Recommendation: Set threshold between 0.6-0.8 for best balance.

Next Steps

Quick Reference

Enable predictions:

typescript
const bus = new Nexus({
  predictionThreshold: 0.7  // 0.0 to 1.0
});

Listen for predictions:

typescript
bus.on('prediction:your-event', (data) => {
  console.log(`Confidence: ${data.probability}`);
  console.log(`Source: ${data.sourceEvent}`);
  console.log(`Original: ${data.originalPayload}`);
});

Disable predictions:

typescript
const bus = new Nexus(); // No predictionThreshold = disabled

Released under the MIT License.