Cogitator
Server Adapters

OpenAPI Generation

Auto-generate OpenAPI 3.0 specs and serve Swagger UI from any Cogitator server adapter.

Every Cogitator server adapter can serve an OpenAPI document and a Swagger UI. Express, Hono and Koa use the shared generator in @cogitator-ai/server-shared, which builds an OpenAPI 3.0.3 spec with one path per registered agent, workflow and swarm. Fastify delegates to @fastify/swagger, and Tetsu to @tetsujs/openapi — see their notes.

How It Works

With the shared generator, enableSwagger registers two routes:

RouteContent-TypeDescription
/openapi.jsonapplication/jsonRaw OpenAPI 3.0.3 spec
/docstext/htmlSwagger UI (loaded from CDN)

Express builds the spec once in init(), Hono on the first request (then caches it), and Koa on every request. All three build it from the agents, workflows and swarms you passed to the adapter.

Paths in the spec are relative to servers, so when you don't set swagger.servers each adapter fills in where its routes live: Express uses basePath (/cogitator by default), and Hono and Koa read the mount prefix from the request (app.route('/api/ai', cogitatorApp(...)) gives [{ url: '/api/ai' }]). Swagger UI's "Try it out" then calls the right URLs. Set swagger.servers yourself to publish absolute URLs, for example one per environment:

swagger: { servers: [{ url: 'https://api.example.com/cogitator' }] },

Enabling Swagger

Express

Swagger is on by default (enableSwagger: true):

const server = new CogitatorServer({
  app,
  cogitator,
  agents: { assistant },
  config: {
    enableSwagger: true,
    swagger: {
      title: 'My API',
      version: '2.0.0',
    },
  },
});

Hono & Koa

Both use the shared generator directly — no extra dependencies needed. Swagger is off until you enable it:

const app = cogitatorApp({
  cogitator,
  agents: { assistant },
  enableSwagger: true,
  swagger: { title: 'My API' },
});

Fastify and Tetsu

Fastify uses @fastify/swagger and @fastify/swagger-ui. Install them as dependencies:

pnpm add @fastify/swagger @fastify/swagger-ui
await fastify.register(cogitatorPlugin, {
  cogitator,
  agents: { assistant },
  enableSwagger: true,
  swagger: { title: 'My API', servers: [{ url: '/cogitator' }] },
});

Its document is generated from the Fastify route schemas: it describes the generic routes (/cogitator/agents/{name}/run, …) and their validated bodies, not one path per agent. Swagger UI is at <prefix>/docs and the JSON at <prefix>/docs/json.

Tetsu describes each route of cogitatorController with its Zod schemas and error responses; mount docs() from @tetsujs/openapi next to it to serve /openapi.json and /docs (Tetsu Adapter).

SwaggerConfig

Express, Fastify, Hono and Koa accept the same SwaggerConfig shape:

interface SwaggerConfig {
  title?: string; // default: 'Cogitator API'
  description?: string; // default: 'AI Agent Runtime API'
  version?: string; // default: '1.0.0'
  contact?: {
    name?: string;
    email?: string;
    url?: string;
  };
  license?: {
    name: string;
    url?: string;
  };
  servers?: Array<{
    url: string;
    description?: string;
  }>; // default: where the adapter's routes are mounted
  auth?: boolean; // default: whether the adapter has `auth`
}

Example with full configuration:

const swagger: SwaggerConfig = {
  title: 'Acme AI Platform',
  description: 'Internal agent runtime for Acme Corp',
  version: '3.1.0',
  contact: {
    name: 'Platform Team',
    email: 'platform@acme.com',
    url: 'https://docs.acme.com',
  },
  license: {
    name: 'MIT',
    url: 'https://opensource.org/licenses/MIT',
  },
  servers: [
    { url: 'https://api.acme.com/cogitator', description: 'Production' },
    { url: 'https://staging-api.acme.com/cogitator', description: 'Staging' },
    { url: 'http://localhost:3000/cogitator', description: 'Local' },
  ],
};

Generated Spec Structure

The spec organizes endpoints into six tags:

TagEndpoints
health/health, /ready
agents/agents, /agents/{name}/run, /agents/{name}/resume, /agents/{name}/stream
threads/threads/{id} (GET, DELETE), /threads/{id}/messages
tools/tools
workflows/workflows, /workflows/{name}/run, /workflows/{name}/stream
swarms/swarms, /swarms/{name}/run, /swarms/{name}/stream, /swarms/{name}/blackboard

Agent, workflow, and swarm endpoints are listed per registered name. If you register agents named assistant and coder, the spec includes /agents/assistant/run, /agents/assistant/resume, /agents/assistant/stream and the same three for coder. Paths are relative to servers.

Component Schemas

The generated spec includes schemas for all request and response types:

  • HealthResponse — status, uptime, timestamp
  • AgentListResponse — list of agent names, descriptions, and tool names
  • AgentRunRequest — input (required), context, threadId
  • AgentRunResponse — output, threadId, usage, toolCalls, reasoning, status (completed | paused), pendingApprovals
  • RunUsage — inputTokens, outputTokens, totalTokens, and reasoningTokens, cachedInputTokens, cacheWriteTokens when the model reported them
  • StreamFinishEvent — the last event of an agent stream: type, messageId, usage (the same RunUsage as the JSON run response)
  • AgentResumeRequest — threadId (required), decisions, defaultDecision
  • PendingApproval — toolCallId, toolName, arguments, description, sideEffects
  • ToolApprovalDecision — approved (required), reason
  • ThreadResponse — id, messages, createdAt, updatedAt
  • AddMessageRequest — role, content, metadata
  • ToolListResponse — tool names, descriptions, parameters
  • WorkflowListResponse — workflow names, entry points, node lists
  • WorkflowRunRequest — input, options (maxConcurrency, maxIterations, checkpoint)
  • WorkflowRunResponse — workflowId, state, duration, nodeResults
  • SwarmListResponse — swarm names, strategies, agent lists
  • SwarmRunRequest — input (required), context, threadId, timeout
  • SwarmRunResponse — swarmId, strategy, output, agentResults, usage
  • BlackboardResponse — sections
  • ErrorResponse — error message and code

Security Scheme

When the adapter has an auth function (or you set swagger.auth: true), the spec declares a bearerAuth scheme and an optional top-level requirement:

{
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    }
  },
  "security": [{ "bearerAuth": [] }, {}]
}

The empty {} keeps every operation callable without a token, since your auth function decides what a request needs; a token you enter under Authorize in Swagger UI is sent as Authorization: Bearer <token>. Without auth the spec has no security section. Set swagger.auth: false to leave it out even when auth is configured (for example when your auth reads a cookie, not a bearer token).

Fastify adds the same scheme and requirement to its @fastify/swagger document. Its paths already include the plugin prefix, so its servers stays [{ url: '/' }].

Using the Shared Generator Directly

If you need the OpenAPI spec outside of a server adapter (for code generation, testing, or CI), import the generator from @cogitator-ai/server-shared:

import { generateOpenAPISpec, generateSwaggerHTML } from '@cogitator-ai/server-shared';
import type { OpenAPIContext, SwaggerConfig } from '@cogitator-ai/server-shared';

const context: OpenAPIContext = {
  agents: { assistant: myAgent },
  workflows: {},
  swarms: {},
};

const config: SwaggerConfig = {
  title: 'My API',
  version: '1.0.0',
  servers: [{ url: '/cogitator' }],
  auth: true,
};

const spec = generateOpenAPISpec(context, config);
const html = generateSwaggerHTML(spec);

Called directly, generateOpenAPISpec uses servers as given ([{ url: '/' }] when unset) and declares bearerAuth only with auth: true.

The generateSwaggerHTML function returns a self-contained HTML page that loads Swagger UI from a CDN and embeds the spec inline. No server-side rendering or static files required. The spec's title is HTML-escaped and the embedded JSON is escaped for a <script> block, so agent names and descriptions can't inject markup into the page.

On this page