Steadybase
API Reference

WebSocket API

Real-time event streaming via WebSocket for worker updates and workflow events.

WebSocket API

Steadybase provides a WebSocket server for real-time event streaming. Connected clients receive live updates for worker status changes, workflow progress, and task broadcasts.

Connection

wss://durableminds.steadybase.io/ws

For local development:

ws://localhost:3000/ws

Authentication

WebSocket connections require a valid JWT token:

// Browser
const ws = new WebSocket('wss://durableminds.steadybase.io/ws', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});
 
// Node.js (ws library)
const WebSocket = require('ws');
const ws = new WebSocket('wss://durableminds.steadybase.io/ws', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

:::warning Unauthenticated WebSocket connections are rejected immediately. :::

Event Types

Worker Status Update

Sent when a worker's status changes (e.g., started, waiting, stopped):

{
  "type": "worker-status",
  "workerId": "sarah-ae-west",
  "status": "running",
  "currentTask": "Preparing call brief for Acme Corp",
  "timestamp": "2026-03-04T10:00:00Z"
}

Workflow Progress

Sent when a workflow step completes or changes:

{
  "type": "workflow-progress",
  "workflowId": "client-onboarding-acme-001",
  "step": 3,
  "totalSteps": 5,
  "action": "Proposal generated",
  "status": "completed",
  "timestamp": "2026-03-04T10:05:00Z"
}

Drew Coordinator Update

Sent during Drew Coordinator execution as each step progresses:

{
  "type": "drew-update",
  "step": 2,
  "agent": "Lisa",
  "action": "Queried 12 Gong transcripts from last 30 days",
  "status": "completed",
  "timestamp": "2026-03-04T10:00:15Z"
}

Task Status Broadcast

Sent when task status is updated (from POST /api/tasks/status):

{
  "type": "task-update",
  "taskId": "task-001",
  "status": "completed",
  "message": "Call brief generated for Acme Corp",
  "timestamp": "2026-03-04T10:10:00Z"
}

Approval Request

Sent when a workflow reaches a human approval gate:

{
  "type": "approval-required",
  "workflowId": "drew-coord-2026-03-04-001",
  "step": 7,
  "description": "Review and approve outreach drafts for Tier 1 accounts",
  "timeout": "7 days",
  "timestamp": "2026-03-04T10:30:00Z"
}

Client Example

const ws = new WebSocket('wss://durableminds.steadybase.io/ws', {
  headers: { 'Authorization': `Bearer ${token}` }
});
 
ws.onopen = () => {
  console.log('Connected to Steadybase WebSocket');
};
 
ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
 
  switch (data.type) {
    case 'worker-status':
      updateWorkerPanel(data);
      break;
    case 'workflow-progress':
      updateWorkflowTracker(data);
      break;
    case 'drew-update':
      appendToActivityFeed(data);
      break;
    case 'approval-required':
      showApprovalDialog(data);
      break;
    case 'task-update':
      refreshTaskList(data);
      break;
  }
};
 
ws.onclose = (event) => {
  console.log('WebSocket closed:', event.code, event.reason);
  // Implement reconnection logic
};
 
ws.onerror = (error) => {
  console.error('WebSocket error:', error);
};

Reconnection

The server does not implement heartbeats. Clients should implement their own reconnection logic:

function connectWithRetry(url, token, maxRetries = 5) {
  let retries = 0;
 
  function connect() {
    const ws = new WebSocket(url, {
      headers: { 'Authorization': `Bearer ${token}` }
    });
 
    ws.onclose = () => {
      if (retries < maxRetries) {
        retries++;
        const delay = Math.min(1000 * Math.pow(2, retries), 30000);
        setTimeout(connect, delay);
      }
    };
 
    return ws;
  }
 
  return connect();
}

On this page