Skip to content

Swagger UI ​

Automatic OpenAPI documentation with interactive Swagger UI.

Overview ​

The agent server automatically generates OpenAPI documentation and provides an interactive Swagger UI for testing your API.

Enabling Swagger ​

typescript
const agentServer = createAgentServer({
  basePath: '/api/agents',
  storage,
  swagger: {
    enabled: true,
    path: '/docs',              // Default: '/docs'
    title: 'My Agent API',      // API title
    version: '1.0.0',           // API version
    description: 'AI Agent REST API documentation',
  },
});

Accessing Documentation ​

Once enabled, you can access:

  • Swagger UI: {basePath}/docs
  • OpenAPI JSON: {basePath}/docs/openapi.json

For example:

  • http://localhost:3000/api/agents/docs
  • http://localhost:3000/api/agents/docs/openapi.json

Configuration Options ​

typescript
interface SwaggerConfig {
  // Enable/disable Swagger UI and the OpenAPI document
  enabled: boolean;

  // Path of the Swagger UI, relative to basePath (default: '/docs')
  path?: string;

  // API title (default: 'Agent Server API')
  title?: string;

  // API version (default: '1.0.0')
  version?: string;

  // API description (default: 'REST API for AI agents - manage conversations and messages')
  description?: string;
}

The document has one server entry, your basePath. For contact, license or other servers, take the document from generateOpenAPISpec and add them yourself (Programmatic access).

Example Configuration ​

typescript
const agentServer = createAgentServer({
  basePath: '/api/agents',
  storage,
  swagger: {
    enabled: true,
    path: '/docs',
    title: 'My AI Agent API',
    version: '1.0.0',
    description: 'REST API for AI agents built with @cognipeer/agent-server',
  },
});

Generated Endpoints ​

The OpenAPI document lists every route of the server - agents, conversations (including messages, runs, events, actions, remembered tools, feedback, export and bulk delete), files and tasks. A test holds server.getRoutes() and the document to each other, so a route cannot exist without an entry. The same routes, with request and response examples, are in REST Endpoints.

Authentication in Swagger ​

When auth.enabled is true, the document declares a BearerAuth scheme and applies it to every operation:

yaml
securitySchemes:
  BearerAuth:
    type: http
    scheme: bearer
    bearerFormat: JWT

Use the "Authorize" button in Swagger UI to set your token. (The scheme describes a bearer header; if you changed auth.headerName, the UI's "Try it out" still sends Authorization.)

Schemas ​

components.schemas describes the request and response bodies of every route: Agent, Conversation, ConversationRuntime, Message, SendMessageRequest / SendMessageResponse, PendingAction, ResolveActionRequest, ListEventsResponse and WireEvent, CancelConversationResponse, FileRecord, AttachmentsCapability, SessionBudget, Task and its request and response types, the Stream*Event family, and Error. The Error schema lists every machine-readable error.code in its description.

Excluding Routes ​

Exclude routes from authentication while keeping them in docs:

typescript
auth: {
  enabled: true,
  provider: authProvider,
  excludeRoutes: ['/docs', '/docs/*'],  // Public access to docs
}

Production Considerations ​

Disable in Production ​

You might want to disable Swagger in production:

typescript
swagger: {
  enabled: process.env.NODE_ENV !== 'production',
}

Or Use Authentication ​

Keep it enabled but require authentication:

typescript
auth: {
  enabled: true,
  provider: authProvider,
  // Don't exclude /docs routes
  excludeRoutes: [],
}

What the spec covers ​

The spec lists every route of the server (a test holds server.getRoutes() and the document to each other), the request and response schemas, and the machine-readable error.codes in the description of the Error schema. It is generated from the configuration: auth.enabled adds the bearer scheme, title, version and description come from swagger, and the one server entry is your basePath. The document the server itself serves at <basePath>/docs/openapi.json is built from the statically registered agents; agents that config.agents(ctx) resolves per request are not part of it.

The UI loads from a CDN ​

The built-in page loads Swagger UI's script and stylesheet from unpkg.com (swagger-ui-dist@5). A server with no outbound internet access, or a page served with a strict Content-Security-Policy, needs its own copy: set swagger.enabled: false and serve your own page next to generateOpenAPISpec (Customizing the UI).

Customizing the UI ​

The generated Swagger UI uses the default SwaggerUI theme. For custom styling, you can:

  1. Serve your own Swagger UI:
typescript
// Disable built-in Swagger
swagger: { enabled: false }

// Serve custom Swagger UI
app.get('/docs', (req, res) => {
  res.send(customSwaggerHTML);
});

// Serve OpenAPI spec
app.get('/docs/openapi.json', async (req, res) => {
  res.json(generateOpenAPISpec(agentServer.getConfig(), await agentServer.getAgentsFor()));
});
  1. Use a different documentation tool:
typescript
// Generate OpenAPI spec
import { generateOpenAPISpec } from '@cognipeer/agent-server';
const spec = generateOpenAPISpec(agentServer.getConfig(), await agentServer.getAgentsFor());

// Use with Redoc, Rapidoc, etc.

Programmatic Access ​

Access the OpenAPI spec programmatically:

typescript
// Get the OpenAPI specification
import { generateOpenAPISpec } from '@cognipeer/agent-server';
const spec = generateOpenAPISpec(agentServer.getConfig(), await agentServer.getAgentsFor());

// Save to file
fs.writeFileSync('openapi.json', JSON.stringify(spec, null, 2));

// Use for code generation
generateClient(spec);

Troubleshooting ​

SymptomCause and fix
/docs answers 401Token auth covers the docs routes unless they are excluded: add /docs and /docs/* to auth.excludeRoutes (the routes skip resolveContext on their own).
/docs is a blank pageThe Swagger UI assets could not be loaded from unpkg.com (offline, firewall or CSP). See The UI loads from a CDN.
"Try it out" calls the wrong URLThe document's one server is basePath as the server knows it. If a proxy adds a prefix, post-process the spec from generateOpenAPISpec and serve it yourself.
An agent of mine is missing in the documentIt is resolved per request (config.agents(ctx)); only statically registered agents are in the served document.

Next Steps ​

Studio · Pulse · Console · Agent SDK and more — the Cognipeer documentation hub