The Labeah Agents Gateway provides real-time communication with AI agents through both WebSocket and REST APIs. Built with high-performance technologies (Fastify, ws, LiveKit), it supports text and audio streaming with multi-language capabilities.
π¬ Text Chat
Real-time text chat with AI agents using WebSocket streaming. Send text messages and receive streamed responses instantly.
ποΈ Audio Streaming
Bi-directional audio streaming with PCM16 format. Stream your voice and receive audio responses in real-time.
π Multi-Language
Support for English (en), Arabic (ar), and Urdu (ur) with language-specific AI agents.
β‘
High Performance
Handles 10K-50K concurrent WebSocket connections
π
Secure
Origin validation and token-based authentication
π‘
Real-Time
Live streaming with LiveKit integration
π―
Production Ready
Battle-tested with Redis session management
π Getting Started
Base URLs
API Server: http://localhost:8100 WebSocket Server: ws://localhost:8101
π Note: Replace localhost with your actual domain in production. Both servers support HTTPS/WSS when deployed behind a reverse proxy.
Supported Languages
Language
Code
Description
π¬π§ English
en
English language agent
πΈπ¦ Arabic
ar
Arabic language agent
π΅π° Urdu
ur
Urdu language agent
Quick Test
Test the API and WebSocket servers using our built-in testing console:
All API and WebSocket connections are protected by origin validation. Configure allowed origins in your environment:
# Allow specific domains
ALLOWED_ORIGINS=qiwa.sa,labeah.ai,localhost# Allow all origins (development only)
ALLOWED_ORIGINS=*# Leave empty to allow all (backward compatible)
ALLOWED_ORIGINS=
API Keys - Two Authentication Methods
Method 1: Authorization Header (Recommended for Clients)
Clients can provide their API key via the Authorization header. This allows each client to use their own API key:
// REST API
Authorization: Bearer your-api-key-here// Or without "Bearer" prefix
Authorization: your-api-key-here
π Priority: If an Authorization header is provided, it takes precedence over environment variables. This allows clients to use their own API keys while maintaining backward compatibility with server-configured keys.
β οΈ Security: Never expose your API keys in client-side code repositories. Store them securely and transmit them only over HTTPS/WSS in production.
π¬ Chat API (REST)
POSTSend a message and receive complete response (non-streaming)
π― Perfect for: Simple request/response patterns, serverless functions, or when you need the complete response at once without streaming complexity.
Conversation ID to maintain context. Auto-generated if not provided
Response
{
"success": true,
"response": "Artificial intelligence (AI) refers to...",
"conversationId": "conv_1234567890_abc123",
"processingTimeMs": 2847,
"connectionReused": true, // false for first message, true for subsequent"timestamp": "2025-10-16T09:30:50.343Z"
}
How It Works (Connection Pooling for Reduced Setup Time)
β‘ Persistent Connection Pool Strategy:
First Request: Creates LiveKit connection (~2-5s setup) + waits for AI response (~5-15s)
Connection Pooled: Connection stays alive for 5 minutes
Subsequent Requests: Reuses connection (saves 2-5s setup) + waits for AI response
Conversation Context: Maintained automatically in the LiveKit room
Smart Buffering: Uses 250ms silence detection for completion
Auto-Cleanup: Idle connections cleaned up after 5 minutes
β οΈ Understanding Latency: The total response time includes AI processing (5-15s), which is the same for both REST and WebSocket. The connection pool saves setup time (2-5s), but the AI still needs time to generate the response. For better perceived performance, use WebSocket streaming where chunks appear immediately as the AI generates them.
Interactive chat, live updates, long conversations
Latency
First: 7-20s, Subsequent: 5-15s (waits for complete response)
First chunk: ~50-200ms, Full response: same as REST
Perceived Performance
Slower - waits for everything
Faster - see chunks immediately β‘
Complexity
Very simple
Requires WebSocket handling
β±οΈ Timeout Behavior: The API waits up to 30 seconds for a complete response. If the agent is still responding after 30 seconds, you'll receive whatever has been collected. For very long responses, consider using the WebSocket Chat Stream instead.
Conversation ID (UUID format). Auto-generated if not provided.
lang
string
required
Language code: en, ar, or ur
Message Format
Sending Messages (Client β Server)
// Send as JSON
{
"text": "Hello, how can you help me?"
}
// Or send as plain text"Hello, how can you help me?"
Receiving Responses (Server β Client)
// Responses are sent as plain text chunks (streaming)"Hello! ""I'm ""here ""to ""help. ""What ""can ""I ""do ""for ""you?"// Error messages start with "Error:""Error: Invalid language"
Example: JavaScript/TypeScript
// Connect to chat stream with API keyconst conversationId = "c43d6fde-7822-4ad0-a121-1ad37c54af02";
const lang = "en";
const apiKey = "your-api-key-here"; // Optional - omit to use server config// Create WebSocket with Authorization headerconst ws = new WebSocket(
`ws://localhost:8101/api/external/v1/chat/stream?id=${conversationId}&lang=${lang}`,
{
headers: {
'Authorization': `Bearer ${apiKey}`
}
}
);
// Handle connection open
ws.onopen = () => {
console.log("Connected to chat stream");
// Send a message
ws.send(JSON.stringify({
text: "What is the weather today?"
}));
};
// Handle incoming messages (streaming chunks)let fullResponse = "";
ws.onmessage = (event) => {
const chunk = event.data;
// Check for errorsif (chunk.startsWith("Error:")) {
console.error(chunk);
return;
}
// Accumulate response
fullResponse += chunk;
console.log("Received chunk:", chunk);
console.log("Full response so far:", fullResponse);
};
// Handle errors
ws.onerror = (error) => {
console.error("WebSocket error:", error);
};
// Handle close
ws.onclose = () => {
console.log("Disconnected from chat stream");
};
β Best Practice: Keep the WebSocket connection open for the entire conversation. Each WebSocket maintains its own conversation context via the conversation ID.
const apiKey = "your-api-key-here"; // Optional - omit to use server configconst response = await fetch("http://localhost:8100/api/external/v1/tts/synthesize", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`// Include your API key
},
body: JSON.stringify({
text: "Hello, this is a test",
lang: "en"
})
});
const result = await response.json();
console.log(result);
π€ Speech-to-Text (WebSocket)
WebSocketReal-time speech transcription
Connection URL
ws://localhost:8101/api/external/v1/stt/stream
β οΈ Coming Soon: This endpoint is currently a placeholder. Full implementation is pending API specification.
Planned Features
β¨ Real-time audio transcription
β¨ Support for multiple audio formats
β¨ Multi-language support
β¨ Partial and final transcription results
β οΈ Error Handling
HTTP Error Codes
Code
Status
Description
400
Bad Request
Invalid request parameters or missing required fields
// Text messages starting with "Error:""Error: Invalid language. Must be one of: ar, en, ur""Error: Message text is required""Error: Failed to process your message"
Common Issues & Solutions
π Connection Rejected:
Origin not allowed: Add your domain to ALLOWED_ORIGINS environment variable
Invalid language: Use one of: en, ar, ur
Invalid conversation ID: Must be a valid UUID or leave empty for auto-generation