Skip to main content

Overview

The CauseFlow Relay exposes a bidirectional WebSocket endpoint using JSON-RPC 2.0 over WSS. Clients use the relay to send commands to AI agents and receive streaming responses without polling. WebSocket URL: wss://relay.causeflow.ai/v1/connect Required role: admin or member
This is a WebSocket endpoint, not a standard HTTP endpoint. Authenticate using JWT in the Authorization header during the initial HTTP upgrade handshake.

Request headers

Authorization
string
required
JWT Bearer token. Format: Bearer <your-jwt>.

Connection handshake

Connect with the Authorization header and optional X-Tenant-Id header:
GET wss://relay.causeflow.ai/v1/connect HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Authorization: Bearer eyJhbGc...
X-Tenant-Id: ten_EXAMPLE_ABC123
Sec-WebSocket-Key: <key>
On successful upgrade, the server sends a connected notification:
{
  "jsonrpc": "2.0",
  "method": "connected",
  "params": {
    "connectionId": "conn_01HX9VTPQR3KF8MZWBYD5N6JCE",
    "tenantId": "ten_EXAMPLE_ABC123",
    "serverTime": "2024-04-01T14:30:00Z"
  }
}

JSON-RPC 2.0 protocol

All messages follow the JSON-RPC 2.0 specification. Requests include an id field; notifications omit it.

Send a command (client → server)

{
  "jsonrpc": "2.0",
  "id": "req_001",
  "method": "investigation.subscribe",
  "params": {
    "incidentId": "inc_EXAMPLE_01JX"
  }
}

Receive a response (server → client)

{
  "jsonrpc": "2.0",
  "id": "req_001",
  "result": {
    "subscriptionId": "sub_01HX9VTPQR3KF8MZWBYD5N6JCE",
    "incidentId": "inc_EXAMPLE_01JX"
  }
}

Receive a push notification (server → client, no id)

{
  "jsonrpc": "2.0",
  "method": "investigation.progress",
  "params": {
    "incidentId": "inc_EXAMPLE_01JX",
    "message": "AI agent found 10,000 errors in the last 30 minutes",
    "agentName": "log analysis",
    "timestamp": "2024-04-01T14:32:10Z"
  }
}

Supported methods

MethodDirectionDescription
investigation.subscribeClient → ServerSubscribe to live updates for an incident investigation
investigation.unsubscribeClient → ServerStop receiving updates for an investigation
remediation.subscribeClient → ServerSubscribe to remediation events for an incident
pingClient → ServerSend a keepalive ping
connectedServer → ClientSent on successful connection
investigation.progressServer → ClientInvestigation step completed
investigation.completedServer → ClientFull investigation pipeline done
remediation.proposedServer → ClientRemediation plan ready for approval
pongServer → ClientResponse to client ping

Heartbeat

Send a ping every 30 seconds to keep the connection alive through proxies:
{ "jsonrpc": "2.0", "id": "ping_001", "method": "ping", "params": {} }
Server responds:
{ "jsonrpc": "2.0", "id": "ping_001", "result": { "pong": true } }
If no heartbeat is received within 60 seconds, the server closes the connection with code 1008 (Policy Violation).

Error codes

CodeMeaning
-32700Parse error — malformed JSON
-32600Invalid request — missing jsonrpc or method
-32601Method not found
-32602Invalid params
-32001Authentication expired — reconnect with fresh JWT
-32002Subscription not found

Examples

const token = "eyJhbGc...";
const ws = new WebSocket(
  "wss://relay.causeflow.ai/v1/connect",
  [],
);

// Note: browser WebSocket does not support custom headers.
// Use a server-side proxy or query param token for browser clients.

ws.onopen = () => {
  // Subscribe to investigation updates
  ws.send(JSON.stringify({
    jsonrpc: "2.0",
    id: "req_001",
    method: "investigation.subscribe",
    params: { incidentId: "inc_EXAMPLE_01JX" },
  }));

  // Start heartbeat
  setInterval(() => {
    ws.send(JSON.stringify({ jsonrpc: "2.0", id: "ping", method: "ping", params: {} }));
  }, 30000);
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  if (msg.method === "investigation.progress") {
    console.log(`[${msg.params.agentName}] ${msg.params.message}`);
  }
  if (msg.method === "investigation.completed") {
    console.log("Investigation complete — root cause:", msg.params.rootCause);
  }
};

ws.onclose = (event) => {
  if (event.code === 1008) {
    console.log("Connection closed by server (policy violation) — check heartbeat");
  }
};

Relay status

Check relay health before connecting

Notifications stream

Alternative: SSE-based event delivery