Client-Server Communication Summary
Quick reference guide for ElizaOS client-server architecture
Architecture Overview
ElizaOS implements a modern client-server architecture with:
- Server: Express.js + Socket.IO (
@elizaos/server
) - Client: React 19 SPA (
@elizaos/client
) - API Client: TypeScript SDK (
@elizaos/api-client
)
Key Components
Server Components
-
AgentServer Class
- Manages agent lifecycle
- Handles HTTP/WebSocket servers
- Database operations
- Message bus integration
-
REST API Router
- Domain-based organization
- Consistent response format
- Middleware stack (auth, rate limiting, CORS)
-
SocketIO Router
- Real-time message handling
- Channel management
- Log streaming
-
Internal Message Bus
- Event-driven agent communication
- Decoupled architecture
- Plugin integration
Client Components
-
React Application
- Provider-based architecture
- React Query for server state
- Socket.IO for real-time updates
-
SocketIO Manager
- Singleton pattern
- Channel subscriptions
- Message handling
-
API Client Services
- Typed service methods
- Error handling
- Request/response formatting
Communication Flow
REST API Flow
Client → HTTP Request → Server → Database
↓
Client ← HTTP Response ← Server
WebSocket Flow
Client → Socket Event → Server → Message Bus → Agents
↑ ↓
←── Socket Broadcast ←────┘
Message Processing
1. Client sends message via WebSocket
2. Server validates and stores in database
3. Server publishes to message bus
4. Agents subscribe and process messages
5. Agent responses broadcast to clients
Quick Start
Server Setup
const server = new AgentServer();
await server.initialize({
dataDir: "./data",
postgresUrl: process.env.DATABASE_URL,
});
await server.start(3000);
Client Connection
// API Client
const client = new ElizaClient({
baseUrl: "http://localhost:3000",
apiKey: process.env.API_KEY,
});
// WebSocket
const socketManager = SocketIOManager.getInstance();
socketManager.initialize(userId);
socketManager.joinChannel(channelId);
API Endpoints
Core Domains
/api/agents
- Agent management/api/messaging
- Messages & channels/api/memory
- Agent memory/api/audio
- Audio processing/api/media
- File management/api/server
- Runtime status/api/system
- Configuration
WebSocket Events
Client → Server:
ROOM_JOINING
- Join channelSEND_MESSAGE
- Send messagesubscribe_logs
- Log streaming
Server → Client:
messageBroadcast
- New messagecontrolMessage
- UI controllog_stream
- Log entries
Security
Authentication
- Optional API key via
X-API-KEY
header - Environment:
ELIZA_SERVER_AUTH_TOKEN
Security Features
- Helmet.js security headers
- CORS protection
- Rate limiting
- Input validation
- File upload restrictions
Performance
Optimizations
- Connection pooling
- Query caching
- Optimistic updates
- Event batching
- Resource cleanup
Scaling
- Horizontal scaling ready
- Message bus upgradeable to Redis/RabbitMQ
- Database connection pooling
- Load balancer compatible
Error Handling
API Errors
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human readable message",
"details": "Additional info"
}
}
WebSocket Errors
socket.on("messageError", (data) => {
console.error("Error:", data.error);
});
Development Tips
-
Enable Debug Logging
DEBUG=socket.io:* node server.js localStorage.debug = 'socket.io-client:*'
-
Monitor Events
socket.onAny((event, ...args) => { console.log(`Event: ${event}`, args); });
-
Test API Endpoints
curl -X GET http://localhost:3000/api/agents \ -H "X-API-KEY: your-key"
-
Mock Services
jest.mock("@/lib/api-client-config", () => ({ createElizaClient: () => mockClient, }));
Common Patterns
Optimistic Updates
// Update UI immediately
setMessages((prev) => [...prev, optimisticMessage]);
// Send to server
await socketManager.sendMessage(text, channelId);
// Handle confirmation/rollback
socket.on("messageAck", updateWithServerId);
Connection Management
const { status } = useConnection();
if (status === "connected") {
// Enable features
} else if (status === "disconnected") {
// Show offline UI
}
Error Recovery
try {
const result = await client.agents.create(data);
} catch (error) {
if (error.code === "NETWORK_ERROR") {
// Retry with backoff
}
}