Cogitator
Server Adapters

Koa Adapter

Integrate Cogitator into your Koa application using the middleware-chain pattern with @koa/router.

The @cogitator-ai/koa package provides cogitatorApp, a factory function that returns a @koa/router instance with all Cogitator routes, middleware, and error handling pre-configured. It follows Koa's middleware-chain philosophy — body parsing, context injection, auth, and error handling are composed as middleware layers.

Installation

pnpm add @cogitator-ai/koa koa @koa/router

Basic Setup

import Koa from 'koa';
import { Cogitator, Agent, tool } from '@cogitator-ai/core';
import { cogitatorApp } from '@cogitator-ai/koa';
import { z } from 'zod';

const app = new Koa();

const cogitator = new Cogitator({
  llm: {
    defaultProvider: 'openai',
    providers: {
      openai: { type: 'openai', apiKey: process.env.OPENAI_API_KEY!, model: 'gpt-4o' },
    },
  },
});

const translator = tool({
  name: 'translate',
  description: 'Translate text to a target language',
  parameters: z.object({
    text: z.string(),
    targetLanguage: z.string(),
  }),
  execute: async ({ text, targetLanguage }) => ({
    translated: `[${targetLanguage}] ${text}`,
  }),
});

const agent = new Agent({
  name: 'translator',
  instructions: 'You translate text between languages. Use the translate tool.',
  tools: [translator],
});

const cogitatorRouter = cogitatorApp({
  cogitator,
  agents: { translator: agent },
  enableSwagger: true,
});

app.use(cogitatorRouter.routes());
app.use(cogitatorRouter.allowedMethods());

app.listen(3000, () => {
  console.log('Koa server running on http://localhost:3000');
  console.log('Swagger UI: http://localhost:3000/docs');
});

App Options

interface CogitatorAppOptions {
  cogitator: Cogitator;
  agents?: Record<string, Agent>;
  workflows?: Record<string, Workflow>;
  swarms?: Record<string, SwarmConfig>;
  auth?: AuthFunction;
  enableSwagger?: boolean;
  swagger?: SwaggerConfig;
  enableWebSocket?: boolean;
  websocket?: WebSocketConfig;
}

Middleware Chain

The returned router applies middleware in this order:

  1. Error handler — catches errors and returns structured JSON responses
  2. Body parser — parses JSON request bodies
  3. Context middleware — injects CogitatorState into ctx.state
  4. Auth middleware — optional, runs your auth function
  5. Route handlers — health, agents, threads, tools, workflows, swarms
  6. Swagger routes — optional, /openapi.json and /docs

Authentication

The auth function receives a Koa Context and returns an AuthContext:

const cogitatorRouter = cogitatorApp({
  cogitator,
  agents: { translator: agent },
  auth: async (ctx) => {
    const token = ctx.headers.authorization?.replace('Bearer ', '');
    if (!token) return undefined;

    const user = await verifyToken(token);
    return { userId: user.id, roles: user.roles, permissions: user.permissions };
  },
});

The auth result is stored in ctx.state.auth for use in downstream middleware.

Mounting Under a Prefix

Use @koa/router's prefix feature to nest the Cogitator routes:

import Router from '@koa/router';

const root = new Router();

root.get('/', (ctx) => {
  ctx.body = { message: 'Welcome' };
});

const cogitatorRouter = cogitatorApp({
  cogitator,
  agents: { translator: agent },
  enableSwagger: true,
});

const prefixed = new Router({ prefix: '/api/v1' });
prefixed.use(cogitatorRouter.routes());
prefixed.use(cogitatorRouter.allowedMethods());

app.use(root.routes());
app.use(prefixed.routes());
app.use(prefixed.allowedMethods());

All Cogitator routes are now under /api/v1/agents/..., /api/v1/docs, etc.

Streaming

The KoaStreamWriter manages SSE responses through Koa's raw ctx.res object:

const response = await fetch('http://localhost:3000/agents/translator/stream', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    input: 'Translate "good morning" to Japanese, French, and Spanish.',
  }),
});

const reader = response.body!.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  process.stdout.write(decoder.decode(value));
}

WebSocket

WebSocket support requires the ws package. After creating your Koa app, call setupWebSocket with the HTTP server:

import { createServer } from 'http';
import { setupWebSocket } from '@cogitator-ai/koa';

const httpServer = createServer(app.callback());

setupWebSocket(httpServer, {
  cogitator,
  agents: { translator: agent },
  path: '/ws',
  pingInterval: 30_000,
});

httpServer.listen(3000);

State Type

The router is typed with CogitatorState, which provides full type safety in custom middleware:

import type { CogitatorState, RouteContext } from '@cogitator-ai/koa';
import Router from '@koa/router';

const custom = new Router<CogitatorState>();

custom.get('/custom', async (ctx) => {
  const { cogitator: routeCtx } = ctx.state;
  const { agents, workflows, swarms } = routeCtx;
  ctx.body = { agentCount: Object.keys(agents).length };
});

Exported Utilities

import {
  cogitatorApp,
  createContextMiddleware,
  createAuthMiddleware,
  createBodyParser,
  createErrorHandler,
  createHealthRoutes,
  createAgentRoutes,
  createThreadRoutes,
  createToolRoutes,
  createWorkflowRoutes,
  createSwarmRoutes,
  createSwaggerRoutes,
  KoaStreamWriter,
  setupSSEHeaders,
  setupWebSocket,
} from '@cogitator-ai/koa';

Each create*Routes() function returns a @koa/router instance that you can mount individually.

On this page