OrkaJS
Orka.JS

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 pnpm
pnpm add @orka-js/server
 
# The server uses Express.js under the hood
# All dependencies are included, no additional setup needed

Key Features

Visual Playground

Built-in React UI for testing agents with chat interface

REST API

Auto-generated REST endpoints for each registered agent

WebSocket Streaming

Real-time token streaming via WebSocket connections

Authentication

Built-in API key and JWT authentication support

CORS & Security

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.

server.ts
// ─────────────────────────────────────────────────────────────────────────────
// 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 server
server.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.ts
// ─────────────────────────────────────────────────────────────────────────────
// 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 agents
const 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.

secure-server.ts
// ─────────────────────────────────────────────────────────────────────────────
// 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.

config.ts
// ─────────────────────────────────────────────────────────────────────────────
// 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 server
await server.start();
 
// Stop the server gracefully
await 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 agents
const agents = server.getAgents();
console.log('Registered agents:', Object.keys(agents));

API Endpoints

The server automatically creates these endpoints for each agent:

api-reference.http
# ─────────────────────────────────────────────────────────────────────────────
# 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}/stream
Content-Type: application/json
 
{
"message": "Tell me about your products"
}
 
# Response: Server-Sent Events stream
data: {"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)