Appearance
WebSocket Integration
Maintain a persistent WebSocket connection for real-time event streaming.
Overview
WebSocket provides lower latency and real-time bidirectional communication compared to HTTP webhooks. When a phone call starts, the AI Flow Service initiates a WebSocket connection to your application. Your application runs a WebSocket server that accepts these connections.
How It Works
Connection
When a phone call starts, the AI Flow Service initiates a WebSocket connection to your application. Your application must run a WebSocket server that accepts incoming connections.
WebSocket Server
Your application needs to expose a WebSocket endpoint that the AI Flow Service can connect to. The service will connect to your configured WebSocket URL when calls begin.
Connection URL
Configure your WebSocket server URL in the AI Flow dashboard. The service will connect to this URL, for example:
wss://your-domain.com/ai-flow/websocketor for local development:
ws://localhost:8080/websocketMessage Format
Receiving Events
Events are sent as JSON strings:
json
{
"type": "user_speak",
"text": "Hello",
"session": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"account_id": "account-123",
"phone_number": "+1234567890"
}
}Sending Actions
Send actions as JSON strings:
json
{
"type": "speak",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"text": "Hello! How can I help you?"
}Implementation Examples
Python
python
import asyncio
import websockets
import json
async def handle_message(websocket, path):
async for message in websocket:
event = json.loads(message)
if event['type'] == 'user_speak':
action = {
'type': 'speak',
'session_id': event['session']['id'],
'text': f"You said: {event['text']}"
}
await websocket.send(json.dumps(action))
async def main():
async with websockets.serve(handle_message, "localhost", 8765):
await asyncio.Future() # run forever
asyncio.run(main())Node.js
javascript
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
ws.on('message', (data) => {
const event = JSON.parse(data.toString());
if (event.type === 'user_speak') {
const action = {
type: 'speak',
session_id: event.session.id,
text: `You said: ${event.text}`
};
ws.send(JSON.stringify(action));
}
});
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
});Go
go
package main
import (
"encoding/json"
"github.com/gorilla/websocket"
"net/http"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func websocketHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
defer conn.Close()
for {
var event map[string]interface{}
err := conn.ReadJSON(&event)
if err != nil {
break
}
if event["type"] == "user_speak" {
session := event["session"].(map[string]interface{})
action := map[string]interface{}{
"type": "speak",
"session_id": session["id"],
"text": "You said: " + event["text"].(string),
}
conn.WriteJSON(action)
}
}
}
func main() {
http.HandleFunc("/ws", websocketHandler)
http.ListenAndServe(":8080", nil)
}Connection Management
The AI Flow Service manages the WebSocket connection lifecycle. When a call starts, it connects to your server. When the call ends, it may close the connection.
Handling Connections
Your WebSocket server should handle incoming connections from the AI Flow Service:
javascript
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws, req) => {
console.log('New connection from AI Flow Service');
ws.on('message', (data) => {
const event = JSON.parse(data.toString());
handleEvent(event, ws);
});
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
ws.on('close', () => {
console.log('Connection closed by AI Flow Service');
});
});Heartbeat
The AI Flow Service may send ping frames to keep the connection alive. Your server should respond with pong frames:
javascript
wss.on('connection', (ws) => {
ws.on('ping', () => {
ws.pong(); // Respond to ping with pong
});
// ... rest of connection handling
});Error Handling
python
async def handle_message(websocket, path):
try:
async for message in websocket:
try:
event = json.loads(message)
action = process_event(event)
if action:
await websocket.send(json.dumps(action))
except json.JSONDecodeError:
print(f"Invalid JSON: {message}")
except Exception as e:
print(f"Error processing event: {e}")
except websockets.exceptions.ConnectionClosed:
print("Connection closed")
except Exception as e:
print(f"WebSocket error: {e}")Advantages Over HTTP
- Lower Latency - No HTTP overhead
- Persistent Connection - No connection setup per request
- Bidirectional - Can send messages anytime, from either side
- Real-time - Instant event delivery
- Proactive Communication - Send actions without waiting for events; receive events without requests
When to Use WebSocket
WebSockets enable a more flexible communication pattern than HTTP webhooks. Unlike the request/response model of HTTP webhooks, WebSockets allow:
- Proactive event delivery - The AI Flow Service can send events to your application at any time, not just in response to a request
- Unsolicited actions - Your application can send actions to the service without waiting for an event first
- True bidirectional communication - Both sides can initiate communication independently
Use WebSocket when:
- You need the lowest possible latency
- You're handling high-volume traffic
- You can run a persistent WebSocket server
- You're building a real-time application
- You have control over your server infrastructure
- You need to send actions proactively without waiting for events
Use HTTP webhooks when:
- You're using serverless functions (which can't maintain WebSocket connections)
- You want simpler deployment
- You prefer the request/response model (each event triggers a response)
- You're building a simple integration
- You can't run a persistent server
Next Steps
- HTTP Webhooks - HTTP integration alternative
- Event Flow - Understand the event lifecycle
- Event Types - Complete event reference