Real-time Alerts

Updated

The SDK includes a WebSocket client that streams triggered alerts as they fire. This provides lower latency than polling the inbox API and is ideal for dashboards, bots, and monitoring systems.

Connecting

Call chaos.alerts.connect() to open a WebSocket connection. The method returns an AlertStream instance that emits typed events:

connect.ts
import { Chaos } from '@chaoslabs/ai-sdk';
 
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
 
const stream = chaos.alerts.connect();

The user is identified server-side from the API key. All alerts for the authenticated user are delivered to the stream.

Events

The AlertStream extends EventEmitter and emits five event types:

EventPayloadDescription
alertTriggeredAlertA new alert has fired
connectedWebSocket connection established
disconnectedstring (reason)Connection lost
errorErrorAn error occurred
pingServer heartbeat received
event-handling.ts
import { Chaos } from '@chaoslabs/ai-sdk';
import type { TriggeredAlert } from '@chaoslabs/ai-sdk';
 
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
const stream = chaos.alerts.connect();
 
stream.on('alert', (event: TriggeredAlert) => {
  console.log(`[${event.severity}] ${event.title}`);
  console.log(`  ${event.summary}`);
  console.log(`  Chain: ${event.chain}`);
  console.log(`  Subscription: ${event.subscriptionId}`);
 
  // Access evidence data
  for (const dp of event.evidence.dataPoints) {
    console.log(`  ${dp.label}: ${dp.value}`);
  }
});
 
stream.on('connected', () => {
  console.log('Connected — listening for alerts');
});
 
stream.on('disconnected', (reason) => {
  console.log('Disconnected:', reason);
});
 
stream.on('error', (err) => {
  console.error('Stream error:', err.message);
});
 
stream.on('ping', () => {
  // Server heartbeat — handled automatically
});

Auto-reconnect

The stream automatically reconnects when the connection drops. Reconnection uses exponential backoff starting at 1 second and doubling up to a maximum of 30 seconds:

AttemptDelay
11s
22s
34s
48s
516s
6+30s (max)

The backoff resets to 1 second after a successful connection.

[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop

Connection status

Check whether the stream is currently connected:

connection-status.ts
if (stream.isConnected) {
  console.log('Stream is live');
} else {
  console.log('Stream is disconnected (may be reconnecting)');
}

Graceful shutdown

Call close() to disconnect and stop auto-reconnect:

shutdown.ts
// Stop the stream
stream.close();
 
// Common pattern: close on process signal
process.on('SIGINT', () => {
  console.log('Shutting down...');
  stream.close();
  process.exit();
});
[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop

Complete example

A monitoring script that logs alerts and handles all lifecycle events:

realtime-monitor.ts
import { Chaos } from '@chaoslabs/ai-sdk';
import type { TriggeredAlert } from '@chaoslabs/ai-sdk';
 
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
 
const stream = chaos.alerts.connect();
 
stream.on('connected', () => {
  console.log(`[${new Date().toISOString()}] Connected — listening for alerts`);
});
 
stream.on('alert', (event: TriggeredAlert) => {
  const timestamp = new Date(event.triggeredAt).toLocaleString();
  console.log(`\n--- Alert at ${timestamp} ---`);
  console.log(`Severity: ${event.severity}`);
  console.log(`Title: ${event.title}`);
  console.log(`Summary: ${event.summary}`);
  console.log(`Chain: ${event.chain}`);
 
  if (event.evidence.dataPoints.length > 0) {
    console.log('Evidence:');
    for (const dp of event.evidence.dataPoints) {
      console.log(`  ${dp.label}: ${dp.value}${dp.unit ? ` ${dp.unit}` : ''}`);
    }
  }
 
  if (event.transactionContext) {
    console.log(`Transaction: ${event.transactionContext.transactionHash}`);
  }
});
 
stream.on('disconnected', (reason) => {
  console.log(`[${new Date().toISOString()}] Disconnected: ${reason}`);
  console.log('Auto-reconnecting...');
});
 
stream.on('error', (err) => {
  console.error(`[${new Date().toISOString()}] Error: ${err.message}`);
});
 
process.on('SIGINT', () => {
  console.log('\nShutting down...');
  stream.close();
  process.exit();
});
 
console.log('Alert monitor started. Press Ctrl+C to stop.');

Browser compatibility

The AlertStream works in both Node.js and browser environments:

  • Node.js / Bun: Uses the native WebSocket if available (Node 22+, Bun), otherwise falls back to the ws package
  • Browsers: Uses the native WebSocket API

Authentication uses a query parameter (?token=ck-...) for browser compatibility, since the browser WebSocket API does not support custom headers.

Next steps

Was this helpful?