Skip to Content
DocsDeploymentWith a Server

Creating A Kastrax Server ✅

When developing or deploying a Kastrax application, it runs as an HTTP server that exposes your agents, workflows, and other functionality as API endpoints. This page explains how to configure and customize the server behavior.

Server Architecture ✅

Kastrax uses Ktor as its underlying HTTP server framework. Ktor is a lightweight, high-performance framework specifically designed for Kotlin applications. When you build a Kastrax application, it configures a Ktor-based HTTP server with all the necessary components.

The server provides:

  • REST API endpoints for all registered agents
  • API endpoints for all registered workflows
  • WebSocket support for real-time agent interactions
  • Custom route configuration
  • Flexible middleware pipeline
  • Comprehensive configuration options
  • Authentication and authorization support
  • CORS configuration

Server Configuration ✅

You can configure the server using the Kastrax DSL. The server configuration is specified within the server block of your Kastrax instance:

ServerConfig.kt
import ai.kastrax.core.kastrax import ai.kastrax.server.server // Create a Kastrax instance with server configuration val kastraxInstance = kastrax { // Configure server server { port = 8080 // Default: 8080 host = "0.0.0.0" // Default: 0.0.0.0 callTimeout = 30000 // Default: 30000 (30s) requestTimeout = 60000 // Default: 60000 (60s) enableSwagger = true // Default: false enableOpenAPI = true // Default: false enableCompression = true // Default: true enableMetrics = true // Default: false enableTracing = true // Default: false } // Other Kastrax configuration... }

You can also configure the server using environment variables:

application.conf
kastrax { server { port = ${?KASTRAX_SERVER_PORT} host = ${?KASTRAX_SERVER_HOST} callTimeout = ${?KASTRAX_SERVER_CALL_TIMEOUT} requestTimeout = ${?KASTRAX_SERVER_REQUEST_TIMEOUT} } }

Custom API Routes ✅

Kastrax automatically generates API routes for all registered agents and workflows. You can also define custom routes to extend the functionality of your server.

Custom routes can be defined within the server block using the routing function:

CustomRoutes.kt
import ai.kastrax.core.kastrax import ai.kastrax.server.server import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* val kastraxInstance = kastrax { server { // Configure server settings port = 8080 // Define custom routes routing { // Simple GET endpoint get("/api/status") { call.respond(HttpStatusCode.OK, mapOf("status" to "running")) } // Route with path parameters get("/api/agents/{agentId}/info") { val agentId = call.parameters["agentId"] val agent = kastraxInstance.getAgent(agentId ?: "") if (agent != null) { call.respond(HttpStatusCode.OK, mapOf( "name" to agent.name, "description" to agent.description )) } else { call.respond(HttpStatusCode.NotFound, mapOf("error" to "Agent not found")) } } // POST endpoint with request body post("/api/custom-generate") { val request = call.receive<CustomGenerateRequest>() val agent = kastraxInstance.getAgent(request.agentId) if (agent != null) { val response = agent.generate(request.prompt) call.respond(HttpStatusCode.OK, response) } else { call.respond(HttpStatusCode.NotFound, mapOf("error" to "Agent not found")) } } } } // Other Kastrax configuration... } // Request data class data class CustomGenerateRequest( val agentId: String, val prompt: String )

You can also define routes in a separate file and include them in your server configuration:

Routes.kt
import ai.kastrax.core.KastraX import io.ktor.server.application.* import io.ktor.server.response.* import io.ktor.server.routing.* // Define routes in a separate function fun Application.configureRoutes(kastraxInstance: KastraX) { routing { get("/api/custom/health") { call.respond(mapOf("status" to "healthy")) } // More routes... } }

Then include them in your server configuration:

ServerConfig.kt
import ai.kastrax.core.kastrax import ai.kastrax.server.server val kastraxInstance = kastrax { server { // Include custom routes install { application -> application.configureRoutes(kastraxInstance) } } }

CORS Configuration ✅

Kastrax allows you to configure CORS (Cross-Origin Resource Sharing) settings for your server. This is important when your frontend application is hosted on a different domain than your API server.

CorsConfig.kt
import ai.kastrax.core.kastrax import ai.kastrax.server.server import io.ktor.http.* val kastraxInstance = kastrax { server { // Configure CORS cors { allowHost("https://example.com") allowHost("https://app.example.com") allowMethod(HttpMethod.Get) allowMethod(HttpMethod.Post) allowMethod(HttpMethod.Options) allowHeader(HttpHeaders.ContentType) allowHeader(HttpHeaders.Authorization) exposeHeader(HttpHeaders.ContentLength) maxAgeInSeconds = 3600 allowCredentials = true } } // Other Kastrax configuration... }

Middleware Configuration ✅

Kastrax allows you to add custom middleware to the server pipeline. Middleware functions are executed in the order they are defined and can perform tasks like logging, authentication, and request transformation.

MiddlewareConfig.kt
import ai.kastrax.core.kastrax import ai.kastrax.server.server import io.ktor.server.application.* import io.ktor.server.plugins.callloging.* import io.ktor.server.plugins.compression.* import io.ktor.server.plugins.defaultheaders.* import io.ktor.server.plugins.ratelimit.* import org.slf4j.event.Level val kastraxInstance = kastrax { server { // Install middleware plugins install { application -> // Add default headers application.install(DefaultHeaders) { header("X-Engine", "Kastrax") header("X-Version", "1.0.0") } // Add call logging application.install(CallLogging) { level = Level.INFO filter { call -> call.request.path().startsWith("/api") } } // Add compression application.install(Compression) { gzip() deflate() } // Add rate limiting application.install(RateLimit) { global { rateLimiter(limit = 100, refillPeriod = 60000) } register(RateLimitName("critical-endpoints")) { rateLimiter(limit = 10, refillPeriod = 60000) } } // Custom authentication middleware application.intercept(ApplicationCallPipeline.Plugins) { val authHeader = call.request.headers["Authorization"] if (call.request.path().startsWith("/api/protected") && (authHeader == null || !authHeader.startsWith("Bearer "))) { throw UnauthorizedException("Invalid or missing authentication token") } } } } // Other Kastrax configuration... } // Custom exception class UnauthorizedException(message: String) : RuntimeException(message)

if you want to add a middleware to a single route, you can also specify that in the registerApiRoute using registerApiRoute.

registerApiRoute("/my-custom-route", { method: "GET", middleware: [ async (c, next) => { // Example: Add request logging console.log(`${c.req.method} ${c.req.url}`); await next(); }, ], handler: async (c) => { // you have access to kastrax instance here const kastrax = c.get("kastrax"); // you can use the kastrax instance to get agents, workflows, etc. const agents = await kastrax.getAgent("my-agent"); return c.json({ message: "Hello, world!" }); }, });

Middleware Behavior

Each middleware function:

  • Receives a Hono context object (c) and a next function
  • Can return a Response to short-circuit the request handling
  • Can call next() to continue to the next middleware or route handler
  • Can optionally specify a path pattern (defaults to ‘/api/*’)
  • Inject request specific data for agent tool calling or workflows

Authentication ✅

Kastrax supports various authentication methods through Ktor’s authentication features:

AuthConfig.kt
import ai.kastrax.core.kastrax import ai.kastrax.server.server import io.ktor.server.application.* import io.ktor.server.auth.* import io.ktor.server.auth.jwt.* val kastraxInstance = kastrax { server { // Configure authentication auth { // Basic authentication basic("auth-basic") { realm = "Kastrax Server" validate { credentials -> if (credentials.name == "admin" && credentials.password == "password") { UserIdPrincipal(credentials.name) } else { null } } } // JWT authentication jwt("auth-jwt") { realm = "Kastrax Server" verifier(JwtConfig.verifier) validate { credential -> if (credential.payload.getClaim("username").asString() != "") { JWTPrincipal(credential.payload) } else { null } } } } } // Other Kastrax configuration... }

CORS Support

{ handler: async (c, next) => { // Add CORS headers c.header("Access-Control-Allow-Origin", "*"); c.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); c.header("Access-Control-Allow-Headers", "Content-Type, Authorization"); // Handle preflight requests if (c.req.method === "OPTIONS") { return new Response(null, { status: 204 }); } await next(); }; }

Request Logging

{ handler: async (c, next) => { const start = Date.now(); await next(); const duration = Date.now() - start; console.log(`${c.req.method} ${c.req.url} - ${duration}ms`); }; }

Special Kastrax Headers

When integrating with Kastrax Cloud or building custom clients, there are special headers that clients send to identify themselves and enable specific features. Your server middleware can check for these headers to customize behavior:

{ handler: async (c, next) => { // Check for Kastrax-specific headers in incoming requests const isFromKastraxCloud = c.req.header("x-kastrax-cloud") === "true"; const clientType = c.req.header("x-kastrax-client-type"); // e.g., 'js', 'python' const isDevPlayground = c.req.header("x-kastrax-dev-playground") === "true"; // Customize behavior based on client information if (isFromKastraxCloud) { // Special handling for Kastrax Cloud requests } await next(); }; }

These headers have the following purposes:

  • x-kastrax-cloud: Indicates that the request is coming from Kastrax Cloud
  • x-kastrax-client-type: Specifies the client SDK type (e.g., ‘js’, ‘python’)
  • x-kastrax-dev-playground: Indicates that the request is from the development playground

You can use these headers in your middleware to implement client-specific logic or enable features only for certain environments.

Deployment ✅

Since Kastrax builds to a standard Node.js server, you can deploy to any platform that runs Node.js applications:

  • Cloud VMs (AWS EC2, DigitalOcean Droplets, GCP Compute Engine)
  • Container platforms (Docker, Kubernetes)
  • Platform as a Service (Heroku, Railway)
  • Self-hosted servers

Building

Build the application:

# Build from current directory ✅ kastrax build # Or specify a directory ✅ kastrax build --dir ./my-project

The build process:

  1. Locates entry file (src/kastrax/index.ts or src/kastrax/index.js)
  2. Creates .kastrax output directory
  3. Bundles code using Rollup with tree shaking and source maps
  4. Generates Hono HTTP server

See kastrax build for all options.

Starting the Server ✅

To start the server, you can use the kastrax dev command during development or deploy your application using one of the deployment methods described in the Deployment guide.

StartServer.kt
import ai.kastrax.core.kastrax import ai.kastrax.server.server fun main() { // Create and configure Kastrax instance val kastraxInstance = kastrax { server { port = 8080 host = "0.0.0.0" } // Configure agents, tools, etc. agent("assistant") { // Agent configuration } } // Start the server kastraxInstance.startServer() // The server is now running and will block the current thread // until the application is stopped }

During development, you can use the kastrax dev command, which will automatically restart the server when you make changes to your code.

Deployment Options ✅

Kastrax supports multiple deployment options:

  1. Standalone JVM Application: Deploy as a traditional Java application on any server
  2. Docker Container: Package your application as a Docker container
  3. Kubernetes: Deploy to a Kubernetes cluster for scalability and resilience
  4. GraalVM Native Image: Compile to a native executable for maximum performance
  5. Kastrax Cloud: Use the managed Kastrax Cloud service

See Deployment Options for detailed instructions on each deployment method.

Last updated on