Real-time Alerts
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:
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:
| Event | Payload | Description |
|---|---|---|
alert | TriggeredAlert | A new alert has fired |
connected | — | WebSocket connection established |
disconnected | string (reason) | Connection lost |
error | Error | An error occurred |
ping | — | Server heartbeat received |
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:
| Attempt | Delay |
|---|---|
| 1 | 1s |
| 2 | 2s |
| 3 | 4s |
| 4 | 8s |
| 5 | 16s |
| 6+ | 30s (max) |
The backoff resets to 1 second after a successful connection.
Connection status
Check whether the stream is currently connected:
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:
// Stop the stream
stream.close();
// Common pattern: close on process signal
process.on('SIGINT', () => {
console.log('Shutting down...');
stream.close();
process.exit();
});Complete example
A monitoring script that logs alerts and handles all lifecycle events:
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
WebSocketif available (Node 22+, Bun), otherwise falls back to thewspackage - Browsers: Uses the native
WebSocketAPI
Authentication uses a query parameter (?token=ck-...) for browser compatibility, since the browser WebSocket API does not support custom headers.
Next steps
- Webhook Delivery — Push alerts to your server for headless integrations
- Alert Inbox — Catch up on missed alerts after reconnection
- Alerts API Reference — Full type definitions