WebSocket Events
The brain-engine exposes a WebSocket endpoint for real-time event streaming. Use it to build live dashboards, custom tooling, or CI integrations that react to memory activity as it happens.
Connection
ws://localhost:9090/ws
No authentication is required for local connections.
Why use WebSocket
The REST API is request/response — you ask, you get an answer. WebSocket is push-based: the brain-engine notifies your client the moment something happens.
Good uses:
- Live dashboards — watch memories accumulate in real time during an agent session
- Custom tooling — trigger downstream actions when a specific project gets a new memory
- CI integrations — detect when an audit run completes and pull the results immediately
- Debugging — observe cache hit/miss patterns without polling
Event types
All events are JSON objects with a type field identifying the event. Additional fields vary by type.
memory_write
Fired when a new memory is stored.
| Field | Type | Description |
|---|---|---|
type | string | "memory_write" |
id | string | Memory UUID |
content_hash | string | SHA-256 of the memory content |
memory_type | string | decision, fact, preference, pattern, etc. |
project | string | Project ID the memory belongs to |
tags | array | Tag list |
importance | float | Importance score (0.0–1.0) |
timestamp | string | ISO 8601 |
memory_archived
Fired when a memory is archived (soft-deleted).
| Field | Type | Description |
|---|---|---|
type | string | "memory_archived" |
id | string | Memory UUID |
project | string | Project ID |
timestamp | string | ISO 8601 |
memory_shared
Fired when a memory is shared to one or more agents via brain_share.
| Field | Type | Description |
|---|---|---|
type | string | "memory_shared" |
id | string | Memory UUID |
target_agents | array | Agent IDs the memory was shared with |
timestamp | string | ISO 8601 |
cache_check
Fired on every semantic cache lookup, whether it hits or misses.
| Field | Type | Description |
|---|---|---|
type | string | "cache_check" |
query_hash | string | Hash of the incoming query |
hit | bool | Whether the cache returned a result |
similarity | float | Cosine similarity score of the best match |
model | string | Model ID used for the embedding |
timestamp | string | ISO 8601 |
audit_complete
Fired when an audit run finishes.
| Field | Type | Description |
|---|---|---|
type | string | "audit_complete" |
run_id | string | Audit run UUID |
scope | string | Audit scope (project, global, etc.) |
project_id | string | Project ID (if scoped) |
finding_count | int | Number of findings produced |
timestamp | string | ISO 8601 |
agent_connected
Fired on agent heartbeat — when an agent checks in via MCP or the status endpoint.
| Field | Type | Description |
|---|---|---|
type | string | "agent_connected" |
agent_id | string | Agent identifier |
project_id | string | Project the agent is working in |
timestamp | string | ISO 8601 |
Example: Node.js listener
const WebSocket = require("ws");
const ws = new WebSocket("ws://localhost:9090/ws");
ws.on("open", () => {
console.log("connected to brain-engine");
});
ws.on("message", (data) => {
const event = JSON.parse(data);
console.log(event.type, event);
});
ws.on("close", () => {
console.log("disconnected");
});
ws.on("error", (err) => {
console.error("ws error", err.message);
});
Example: Python asyncio listener
import asyncio
import json
import websockets
async def listen():
async with websockets.connect('ws://localhost:9090/ws') as ws:
print('connected to brain-engine')
async for message in ws:
event = json.loads(message)
print(event['type'], event)
asyncio.run(listen())
Reconnection
WebSocket connections drop whenever the Docker stack restarts. Implement exponential backoff to reconnect automatically.
Example (Node.js):
const WebSocket = require("ws");
function connect(delay = 1000) {
const ws = new WebSocket("ws://localhost:9090/ws");
ws.on("open", () => {
console.log("connected");
delay = 1000; // reset backoff on successful connection
});
ws.on("message", (data) => {
const event = JSON.parse(data);
console.log(event.type, event);
});
ws.on("close", () => {
console.log(`disconnected — reconnecting in ${delay}ms`);
setTimeout(() => connect(Math.min(delay * 2, 30000)), delay);
});
}
connect();
Max backoff of 30 seconds is a reasonable ceiling — the stack typically restarts in under 10 seconds.