Agent Server & UI
Host agents with a visual playground
Launch a production-ready HTTP server with a beautiful React UI to test and interact with your agents. The server provides REST API endpoints for each agent, WebSocket support for real-time streaming, and a visual playground for testing. Perfect for demos, development, internal tools, and even production deployments.
Installation
Install the server package. It includes the React playground UI bundled, so no additional frontend setup is needed.
# ─────────────────────────────────────────────────────────────────────────────# Install @orka-js/server# The package includes the React playground UI bundled# ───────────────────────────────────────────────────────────────────────────── npm install @orka-js/server # Or with pnpmpnpm add @orka-js/server # The server uses Express.js under the hood# All dependencies are included, no additional setup neededKey Features
Built-in React UI for testing agents with chat interface
Auto-generated REST endpoints for each registered agent
Real-time token streaming via WebSocket connections
Built-in API key and JWT authentication support
Configurable CORS, rate limiting, and security headers
Basic Usage
Create a server with one or more agents. Each agent gets its own API endpoint automatically.
// ─────────────────────────────────────────────────────────────────────────────// Basic Server Setup//// This creates a server with a single agent and starts it on port 3000.// The playground UI will be available at http://localhost:3000/playground// ───────────────────────────────────────────────────────────────────────────── import { createOrkaServer } from '@orka-js/server';import { StreamingToolAgent } from '@orka-js/agent';import { OpenAIAdapter } from '@orka-js/openai'; // ─── Step 1: Create your LLM adapter ───────────────────────────────────────── const llm = new OpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY!, model: 'gpt-4o', // Use any OpenAI model}); // ─── Step 2: Define your agent's tools ─────────────────────────────────────── const searchKnowledgeBase = { name: 'searchKnowledgeBase', description: 'Search the company knowledge base for information', parameters: { type: 'object', properties: { query: { type: 'string', description: 'The search query' }, }, required: ['query'], }, execute: async ({ query }: { query: string }) => { // Your search logic here return { results: ['Result 1', 'Result 2'] }; },}; // ─── Step 3: Create your agent ─────────────────────────────────────────────── const supportAgent = new StreamingToolAgent({ // The agent's purpose - guides its behavior goal: 'Help customers find answers to their questions about our products', // System prompt for additional context systemPrompt: `You are a helpful customer support agent.Be friendly, professional, and thorough in your responses.Always search the knowledge base before answering questions.`, // Tools the agent can use tools: [searchKnowledgeBase],}, llm); // ─── Step 4: Create and start the server ───────────────────────────────────── const server = createOrkaServer({ // Register agents with their names // The name becomes part of the API endpoint: /api/agents/{name} agents: { support: supportAgent, },}, { // Server port (default: 3000) port: 3000, // Automatically open the playground in your browser openBrowser: true, // Enable CORS for cross-origin requests cors: true,}); // Start the serverserver.start(); // Output:// ┌─────────────────────────────────────────────────────────────┐// │ OrkaJS Server v1.0.0 │// │ │// │ API: http://localhost:3000/api │// │ Playground: http://localhost:3000/playground │// │ │// │ Agents: │// │ • support POST /api/agents/support │// │ │// │ Ready to accept connections │// └─────────────────────────────────────────────────────────────┘Multi-Agent Server
Register multiple agents with different capabilities. The playground UI lets you switch between them.
// ─────────────────────────────────────────────────────────────────────────────// Multi-Agent Server//// Register multiple agents with different capabilities.// Each agent gets its own endpoint and appears in the playground dropdown.// ───────────────────────────────────────────────────────────────────────────── import { createOrkaServer } from '@orka-js/server';import { StreamingToolAgent, ReActAgent } from '@orka-js/agent';import { OpenAIAdapter } from '@orka-js/openai';import { AnthropicAdapter } from '@orka-js/anthropic'; // Different LLMs for different agentsconst openai = new OpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY! });const anthropic = new AnthropicAdapter({ apiKey: process.env.ANTHROPIC_API_KEY! }); // ─── Support Agent: Fast responses with GPT-4o ─────────────────────────────── const supportAgent = new StreamingToolAgent({ goal: 'Help customers with product questions', tools: [searchProducts, checkOrderStatus],}, openai); // ─── Research Agent: Deep analysis with Claude ─────────────────────────────── const researchAgent = new ReActAgent({ goal: 'Conduct thorough research and analysis', tools: [webSearch, summarizeDocument, analyzeData], maxIterations: 10, // Allow more reasoning steps}, anthropic); // ─── Sales Agent: Product recommendations ──────────────────────────────────── const salesAgent = new StreamingToolAgent({ goal: 'Help customers find the perfect product', systemPrompt: 'You are a friendly sales assistant. Ask questions to understand customer needs.', tools: [searchProducts, getProductDetails, checkInventory],}, openai); // ─── Create server with all agents ─────────────────────────────────────────── const server = createOrkaServer({ agents: { // Each key becomes the agent's endpoint name support: supportAgent, // POST /api/agents/support research: researchAgent, // POST /api/agents/research sales: salesAgent, // POST /api/agents/sales }, // Optional: Add metadata for the playground UI agentMetadata: { support: { displayName: 'Customer Support', description: 'Get help with orders and products', icon: '🎧', }, research: { displayName: 'Research Assistant', description: 'Deep analysis and research', icon: '🔬', }, sales: { displayName: 'Sales Assistant', description: 'Find the perfect product', icon: '🛒', }, },}, { port: 3000, cors: true,}); server.start();Authentication
Protect your agents with API key or JWT authentication. You can also add custom middleware.
// ─────────────────────────────────────────────────────────────────────────────// Authentication & Security//// Protect your agents with API keys, JWT tokens, or custom middleware.// ───────────────────────────────────────────────────────────────────────────── import { createOrkaServer } from '@orka-js/server'; const server = createOrkaServer({ agents: { support: supportAgent },}, { port: 3000, // ─── API Key Authentication ──────────────────────────────────────────────── // Clients must include: Authorization: Bearer <api-key> auth: { type: 'api-key', // List of valid API keys apiKeys: [ process.env.API_KEY_1!, process.env.API_KEY_2!, ], // Or use a validation function for dynamic keys validateKey: async (key: string) => { // Check against your database const isValid = await db.apiKeys.exists(key); return isValid; }, }, // ─── JWT Authentication ──────────────────────────────────────────────────── // Clients must include: Authorization: Bearer <jwt-token> // auth: { // type: 'jwt', // secret: process.env.JWT_SECRET!, // // // Optional: Extract user info from token // extractUser: (payload) => ({ // id: payload.sub, // email: payload.email, // }), // }, // ─── Rate Limiting ───────────────────────────────────────────────────────── // Prevent abuse by limiting requests per IP/user rateLimit: { // Maximum requests per window max: 100, // Time window in milliseconds (1 minute) windowMs: 60 * 1000, // Custom key generator (default: IP address) keyGenerator: (req) => req.headers['x-user-id'] || req.ip, // Custom response when rate limited message: 'Too many requests, please try again later', }, // ─── Custom Middleware ───────────────────────────────────────────────────── // Add your own Express middleware middleware: [ // Logging middleware (req, res, next) => { console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`); next(); }, // Custom auth middleware async (req, res, next) => { const userId = req.headers['x-user-id']; if (userId) { req.user = await db.users.findById(userId); } next(); }, ], // ─── Security Headers ────────────────────────────────────────────────────── security: { // Enable Helmet.js security headers helmet: true, // Content Security Policy csp: { directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'"], }, }, },}); server.start();Server Configuration
Full configuration options for customizing the server behavior.
// ─────────────────────────────────────────────────────────────────────────────// Full Server Configuration//// All available options for customizing the server.// ───────────────────────────────────────────────────────────────────────────── import { createOrkaServer } from '@orka-js/server'; const server = createOrkaServer({ agents: { support: supportAgent },}, { // ─── Basic Settings ──────────────────────────────────────────────────────── port: 3000, // Server port (default: 3000) host: '0.0.0.0', // Host to bind to (default: localhost) // ─── Playground UI ───────────────────────────────────────────────────────── playground: { enabled: true, // Enable/disable playground (default: true) path: '/playground', // URL path for playground title: 'My Agent Playground', // Custom title theme: 'dark', // 'light' | 'dark' | 'system' }, // ─── CORS Configuration ──────────────────────────────────────────────────── cors: { origin: ['http://localhost:3001', 'https://myapp.com'], methods: ['GET', 'POST'], credentials: true, }, // ─── WebSocket Settings ──────────────────────────────────────────────────── websocket: { enabled: true, // Enable WebSocket support path: '/ws', // WebSocket endpoint path pingInterval: 30000, // Keep-alive ping interval (ms) }, // ─── Logging ─────────────────────────────────────────────────────────────── logging: { level: 'info', // 'debug' | 'info' | 'warn' | 'error' format: 'json', // 'json' | 'pretty' // Log specific events logRequests: true, // Log incoming requests logResponses: true, // Log outgoing responses logToolCalls: true, // Log agent tool executions }, // ─── Request Limits ──────────────────────────────────────────────────────── limits: { maxRequestSize: '10mb', // Maximum request body size timeout: 120000, // Request timeout in ms (2 minutes) }, // ─── Hooks ───────────────────────────────────────────────────────────────── hooks: { // Called before each agent request beforeRequest: async (req, agentName) => { console.log(`Request to agent: ${agentName}`); }, // Called after each agent response afterResponse: async (req, res, agentName, duration) => { console.log(`Agent ${agentName} responded in ${duration}ms`); }, // Called on errors onError: async (error, req, agentName) => { console.error(`Error in agent ${agentName}:`, error); // Send to error tracking service await errorTracker.capture(error); }, }, // ─── Browser Auto-Open ───────────────────────────────────────────────────── openBrowser: true, // Open playground on start}); // ─── Server Methods ────────────────────────────────────────────────────────── // Start the serverawait server.start(); // Stop the server gracefullyawait server.stop(); // Get the Express app instance (for custom routes)const app = server.getApp();app.get('/health', (req, res) => res.json({ status: 'ok' })); // Get registered agentsconst agents = server.getAgents();console.log('Registered agents:', Object.keys(agents));API Endpoints
The server automatically creates these endpoints for each agent:
# ─────────────────────────────────────────────────────────────────────────────# Auto-Generated API Endpoints## For each agent registered, the server creates these endpoints:# ───────────────────────────────────────────────────────────────────────────── # ─── Chat Endpoint (POST) ─────────────────────────────────────────────────────# Send a message to the agent and get a response POST /api/agents/{agentName}Content-Type: application/json { "message": "What products do you have?", "sessionId": "optional-session-id", # For conversation memory "stream": false # Set to true for streaming} # Response (non-streaming):{ "response": "We have a wide variety of products...", "toolCalls": [ { "name": "searchProducts", "args": { "query": "all" }, "result": [...] } ], "usage": { "promptTokens": 150, "completionTokens": 200 }} # ─── Streaming Endpoint (POST) ────────────────────────────────────────────────# Get real-time token streaming via Server-Sent Events POST /api/agents/{agentName}/streamContent-Type: application/json { "message": "Tell me about your products"} # Response: Server-Sent Events streamdata: {"type":"token","content":"We"}data: {"type":"token","content":" have"}data: {"type":"tool_start","name":"searchProducts","args":{}}data: {"type":"tool_end","name":"searchProducts","result":[...]}data: {"type":"token","content":" many"}data: {"type":"done","usage":{"promptTokens":150,"completionTokens":200}} # ─── Agent Info (GET) ─────────────────────────────────────────────────────────# Get information about a specific agent GET /api/agents/{agentName}/info # Response:{ "name": "support", "goal": "Help customers with product questions", "tools": ["searchProducts", "checkOrderStatus"], "metadata": { "displayName": "Customer Support", "icon": "🎧" }} # ─── List Agents (GET) ────────────────────────────────────────────────────────# Get a list of all registered agents GET /api/agents # Response:{ "agents": [ { "name": "support", "displayName": "Customer Support" }, { "name": "sales", "displayName": "Sales Assistant" } ]} # ─── Health Check (GET) ───────────────────────────────────────────────────────# Check if the server is running GET /api/health # Response:{ "status": "ok", "uptime": 3600, "agents": 2 }Deployment Tips
- Use environment variables for API keys and secrets
- Enable rate limiting in production to prevent abuse
- Set up proper CORS origins for your frontend domains
- Use the health endpoint for load balancer health checks
- Consider disabling the playground in production (playground.enabled: false)