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
(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.
Authenticated user identifier
Example:
{
"type": "init",
"user_id": "user_123"
}
Chat Query
Send a message to the AI agent.
Chat session UUID (for context continuity)
LLM model to use (e.g., “gpt-4”, “claude-3-opus”)
Chat mode: agent (read-write) or ask (read-only)
File attachments (images, PDFs, etc.)
UI preferences to save with session
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.
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
ID of the confirmation request
Whether the action is approved
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.
Status value: START or END
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.
Text content (single token or sentence)
Whether this is a streaming chunk
Whether the message is complete
Whether streaming is active
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
Notify client of tool invocations.
type
string
default:"tool_call"
Message type
Name of the tool being called
Tool execution status: running, success, error
Unique identifier for this tool call
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"
}
Report tool execution results.
type
string
default:"tool_result"
Message type
Tool execution result (structure varies by tool)
Confirmation Requests
Request user approval for infrastructure changes.
type
string
default:"confirmation_request"
Message type
Unique confirmation identifier
Action requiring approval
Details about the proposed change
Resources that will be created/modified
Usage Info
API cost tracking information.
type
string
default:"usage_info"
Message type
Total API cost in USD (rounded to 2 decimals)
Example:
{
"type": "usage_info",
"data": {
"total_cost": 0.15
}
}
Error Messages
Error severity: error, warning
Error code (e.g., “READ_ONLY_MODE”)
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
- Connect - Establish WebSocket connection
- Initialize - Send init message with user_id
- Ready - Receive START status
- Chat - Exchange messages and receive responses
- Tools - Receive tool call events during execution
- Complete - Receive END status when done
- 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
- 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');