Skip to main content

WebSocket Protocol

Aurora uses WebSocket connections for real-time, bidirectional communication with the AI agent. This enables streaming responses, live tool execution updates, and interactive confirmations.

Connection

Endpoint

ws://localhost:5006
(Use wss:// for production with TLS)

Authentication

Authentication is handled via the initialization message after connecting. Connection Example:
const ws = new WebSocket('ws://localhost:5006');

ws.onopen = () => {
  // Send initialization message
  ws.send(JSON.stringify({
    type: 'init',
    user_id: 'user_123'
  }));
};

Message Protocol

All messages follow a consistent JSON structure:
{
  "type": "message_type",
  "data": { /* type-specific payload */ },
  "session_id": "optional-session-id"
}

Client → Server Messages

Initialization

Sent immediately after connection to authenticate the user.
type
string
default:"init"
Message type identifier
user_id
string
required
Authenticated user identifier
Example:
{
  "type": "init",
  "user_id": "user_123"
}

Chat Query

Send a message to the AI agent.
query
string
required
User’s message text
user_id
string
required
User identifier
session_id
string
required
Chat session UUID (for context continuity)
model
string
LLM model to use (e.g., “gpt-4”, “claude-3-opus”)
mode
string
default:"agent"
Chat mode: agent (read-write) or ask (read-only)
selected_project_id
string
Active cloud project ID
attachments
array
default:"[]"
File attachments (images, PDFs, etc.)
ui_state
object
UI preferences to save with session
direct_tool_call
object
Direct tool invocation (bypasses AI decision-making)
Example:
{
  "query": "Create a GKE cluster in us-central1",
  "user_id": "user_123",
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "model": "gpt-4",
  "mode": "agent",
  "selected_project_id": "my-gcp-project",
  "ui_state": {
    "selectedModel": "gpt-4",
    "selectedMode": "agent",
    "selectedProviders": ["gcp"]
  }
}

Control Messages

Control ongoing operations.
type
string
default:"control"
Message type identifier
action
string
required
Control action: cancel
session_id
string
required
Session to control
user_id
string
required
User identifier
Example (Cancel):
{
  "type": "control",
  "action": "cancel",
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "user_id": "user_123"
}
Cancellation Behavior:
  • Stops ongoing AI workflow
  • Cancels pending infrastructure confirmations
  • Consolidates partial messages
  • Saves context for session resumption
  • Sends END status to client

Confirmation Response

Respond to infrastructure confirmation requests.
type
string
default:"confirmation_response"
Message type identifier
confirmation_id
string
required
ID of the confirmation request
approved
boolean
required
Whether the action is approved
user_id
string
required
User identifier
session_id
string
required
Session identifier
Example:
{
  "type": "confirmation_response",
  "confirmation_id": "conf_abc123",
  "approved": true,
  "user_id": "user_123",
  "session_id": "550e8400-e29b-41d4-a716-446655440000"
}

Server → Client Messages

Status Messages

Indicate connection and workflow status.
type
string
default:"status"
Message type
data
object
status
string
Status value: START or END
isComplete
boolean
Whether workflow is complete (only for END)
Example (Start):
{
  "type": "status",
  "data": {
    "status": "START"
  }
}
Example (End):
{
  "type": "status",
  "data": {
    "status": "END"
  },
  "isComplete": true,
  "session_id": "550e8400-e29b-41d4-a716-446655440000"
}

Message Chunks

Streamed response text from the AI agent.
type
string
default:"message"
Message type
data
object
text
string
Text content (single token or sentence)
is_chunk
boolean
default:true
Whether this is a streaming chunk
is_complete
boolean
default:false
Whether the message is complete
streaming
boolean
default:true
Whether streaming is active
session_id
string
Associated session ID
Example:
{
  "type": "message",
  "data": {
    "text": "I'll create a GKE cluster ",
    "is_chunk": true,
    "is_complete": false,
    "streaming": true
  },
  "session_id": "550e8400-e29b-41d4-a716-446655440000"
}
Streaming Behavior:
  • Text is sent incrementally as LLM generates it
  • Chunks are split at sentence boundaries for smooth display
  • Multiple chunks combine to form complete messages
  • Large chunks (>100 chars) are automatically split

Tool Call Events

Notify client of tool invocations.
type
string
default:"tool_call"
Message type
data
object
tool_name
string
Name of the tool being called
input
object
Tool parameters
status
string
Tool execution status: running, success, error
timestamp
string
ISO 8601 timestamp
tool_call_id
string
Unique identifier for this tool call
output
string
Tool execution result (when complete)
Example:
{
  "type": "tool_call",
  "data": {
    "tool_name": "gcp_compute",
    "input": {
      "action": "create_gke_cluster",
      "cluster_name": "prod-cluster",
      "region": "us-central1"
    },
    "status": "running",
    "timestamp": "2024-03-15T10:30:00Z",
    "tool_call_id": "call_abc123"
  },
  "session_id": "550e8400-e29b-41d4-a716-446655440000"
}

Tool Result Events

Report tool execution results.
type
string
default:"tool_result"
Message type
data
object
tool_name
string
Tool that was executed
result
any
Tool execution result (structure varies by tool)
session_id
string
Associated session

Confirmation Requests

Request user approval for infrastructure changes.
type
string
default:"confirmation_request"
Message type
data
object
confirmation_id
string
Unique confirmation identifier
action
string
Action requiring approval
details
object
Details about the proposed change
resources
array
Resources that will be created/modified

Usage Info

API cost tracking information.
type
string
default:"usage_info"
Message type
data
object
total_cost
number
Total API cost in USD (rounded to 2 decimals)
Example:
{
  "type": "usage_info",
  "data": {
    "total_cost": 0.15
  }
}

Error Messages

type
string
default:"error"
Message type
data
object
text
string
Error message
severity
string
Error severity: error, warning
code
string
Error code (e.g., “READ_ONLY_MODE”)
session_id
string
Associated session
Example:
{
  "type": "error",
  "data": {
    "text": "Failed to create cluster: insufficient permissions",
    "severity": "error",
    "session_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}

Rate Limiting

WebSocket connections are rate-limited:
  • Rate: 5 messages per 60 seconds per client
  • Enforcement: Token bucket algorithm
  • Response: Error message when limit exceeded
{
  "type": "error",
  "data": {
    "text": "Rate limit exceeded. Please wait and try again."
  }
}

Connection Lifecycle

  1. Connect - Establish WebSocket connection
  2. Initialize - Send init message with user_id
  3. Ready - Receive START status
  4. Chat - Exchange messages and receive responses
  5. Tools - Receive tool call events during execution
  6. Complete - Receive END status when done
  7. Disconnect - Close connection gracefully

Best Practices

Connection Management

  • Implement automatic reconnection with exponential backoff
  • Handle connection drops gracefully
  • Send init message immediately after connecting
  • Monitor connection state and show status to user

Message Handling

  • Buffer message chunks for display
  • Update UI progressively as chunks arrive
  • Show tool execution status in real-time
  • Handle out-of-order messages by session_id

Error Recovery

  • Retry failed messages with exponential backoff
  • Show connection errors to user
  • Allow manual retry of failed operations
  • Preserve unsent messages across reconnections

Performance

  • Keep WebSocket connection alive between messages
  • Reuse connections for multiple sessions
  • Close connections after extended inactivity
  • Monitor memory usage from buffered chunks

Example Client

class AuroraWebSocket {
  constructor(url, userId) {
    this.url = url;
    this.userId = userId;
    this.ws = null;
    this.messageHandlers = {};
  }

  connect() {
    this.ws = new WebSocket(this.url);
    
    this.ws.onopen = () => {
      console.log('Connected to Aurora');
      this.send({ type: 'init', user_id: this.userId });
    };
    
    this.ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      const handler = this.messageHandlers[message.type];
      if (handler) handler(message);
    };
    
    this.ws.onerror = (error) => {
      console.error('WebSocket error:', error);
    };
    
    this.ws.onclose = () => {
      console.log('Disconnected from Aurora');
      // Implement reconnection logic here
    };
  }

  send(message) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(message));
    }
  }

  on(type, handler) {
    this.messageHandlers[type] = handler;
  }

  sendChat(query, sessionId, options = {}) {
    this.send({
      query,
      user_id: this.userId,
      session_id: sessionId,
      model: options.model || 'gpt-4',
      mode: options.mode || 'agent',
      ...options
    });
  }

  cancel(sessionId) {
    this.send({
      type: 'control',
      action: 'cancel',
      session_id: sessionId,
      user_id: this.userId
    });
  }
}

// Usage
const aurora = new AuroraWebSocket('ws://localhost:5006', 'user_123');

aurora.on('message', (msg) => {
  console.log('Received:', msg.data.text);
});

aurora.on('tool_call', (msg) => {
  console.log('Tool call:', msg.data.tool_name);
});

aurora.on('status', (msg) => {
  if (msg.data.status === 'END') {
    console.log('Workflow complete');
  }
});

aurora.connect();

// Send a message
aurora.sendChat('Create a GKE cluster', 'session-123');

Build docs developers (and LLMs) love