Stop Wasting Tokens on Bad API Docs: SWAGENT Is the Fix
Your AI agent just burned through $12 in API credits trying to understand your API. It choked on Swagger UI's JavaScript↗ Bright Coding Blog bundles, got lost in Redoc's nested schemas, and finally gave up after parsing 47,000 tokens of navigation chrome, CSS classes, and repeated error definitions. Meanwhile, your human developers are scrolling through the same bloated documentation, hunting for the one parameter they actually need.
Here's the brutal truth: we built API documentation for humans, then forced machines to read it. LLM agents don't need dark mode toggles. They don't care about your logo. They need dense, structured information delivered with surgical precision. Every wasted token is latency, cost, and degraded performance in production.
Enter SWAGENT — the open-source documentation generator that serves three formats from one URL using standard HTTP content negotiation. Token-optimized llms.txt for AI agents. Full markdown↗ Smart Converter for developers. Semantic HTML for browsers. Same endpoint, right format, zero configuration.
Sound impossible? That's what the team at X24Labs thought until they proved it. Let's dissect why SWAGENT is becoming the secret weapon for API-first teams.
What Is SWAGENT?
SWAGENT is an open-source documentation generator created by X24Labs that transforms OpenAPI specifications into three distinct output formats optimized for their respective consumers. The project — currently at v0.1.8 on npm — is built in TypeScript 5.7 and supports seven major Node.js frameworks plus Bun and Deno runtimes.
The name itself signals the mission: SWAGENT = Swagger for AGENTs. But don't mistake this for yet another Swagger UI skin. SWAGENT fundamentally reimagines how API documentation gets consumed in the agent era.
The project emerged from a simple observation: LLM context windows are expensive, yet we're feeding them documentation formats designed for eyeballs, not transformers. Swagger UI renders beautifully in browsers but ships kilobytes of JavaScript. Redoc produces gorgeous interactive docs that LLMs can't parse. Raw OpenAPI JSON is complete but verbose — every schema gets repeated, every field carries redundant metadata.
SWAGENT solves this with content negotiation — an HTTP feature as old as the spec itself, yet criminally underused in API tooling. The same URL responds with HTML when your browser requests it, markdown when your curl client asks, and ultra-compact llms.txt when an AI agent comes knocking. No separate endpoints to maintain. No discovery step. No "did you mean /llms.txt?" confusion.
The project has gained traction among teams building AI-native products, API platforms serving both human and machine clients, and developers frustrated with maintaining parallel documentation pipelines.
Key Features That Separate SWAGENT from the Pack
True AI-First Architecture via HTTP Content Negotiation
SWAGENT doesn't bolt on AI support as an afterthought. The core design principle: agents should use the same URL as humans. When an LLM agent sends Accept: text/markdown, the root path returns token-optimized documentation automatically. No special paths, no configuration, no training your agent to append /llms.txt.
~75% Token Reduction Over Raw OpenAPI JSON
SWAGENT's compact notation eliminates redundant metadata. Required fields become name* instead of nested JSON Schema objects. Types inline as age:number rather than "age": { "type": "number" }. Authentication collapses to JWT, KEY, or NONE shorthands. Common errors get defined once in conventions, not repeated per endpoint.
Zero-Dependency Semantic HTML Landing Page
The HTML output requires no JavaScript, no build step, no framework lock-in. Dark theme by default, categorized endpoints, built-in content negotiation awareness. It works offline, loads instantly, and won't break when your CDN hiccups.
Seven Framework Adapters + CLI
Fastify, Express, Hono, Elysia, Koa, h3/Nitro/Nuxt, and NestJS — all supported with idiomatic integration patterns. The CLI generates static files for any hosting scenario. Core library available for custom implementations.
Built-In Production Hardening
ETag caching with 304 Not Modified responses. Cache-Control headers optimized per format. Graceful degradation when specs are malformed — your API stays up even when docs generation fails. Optional token-based authentication for private documentation.
Per-Format Token Transparency
The markdown response includes x-markdown-tokens: N header showing estimated token count. LLM orchestration systems can make informed decisions about context budget before downloading.
Real-World Use Cases Where SWAGENT Dominates
AI-Native API Platforms
You're building the next Stripe or Twilio, but your primary consumers are autonomous agents, not human developers. Your documentation needs to be machine-parseable at scale. SWAGENT lets you tell customers: "Point your agent at https://api.yourservice.com and it just works." No custom parsers, no scraping logic, no "please also check our /llms.txt endpoint" caveats.
Multi-Tenant SaaS with Embedded APIs
Your platform lets customers build integrations. Each tenant gets their own API subdomain. Maintaining separate docs for humans and machines across hundreds of subdomains is a nightmare. SWAGENT's per-request base URL detection means one deployment serves all tenants automatically, with each getting properly linked documentation.
Internal Microservices Mesh
Your engineering team runs 200+ services. LLM-based internal tools need to discover and call these APIs dynamically. Traditional docs are too token-heavy for effective in-context learning. SWAGENT's compressed format lets you fit service documentation into tight context windows, enabling truly autonomous service orchestration.
Cost-Conscious AI Integration Workflows
You're processing thousands of API calls through LLM pipelines. Every token in the system prompt, every character in the function definition, directly impacts your margin. SWAGENT's 75% reduction in documentation tokens translates to measurable cost savings at scale — especially with models priced per million tokens.
Framework-Agnostic Documentation Pipelines
Your organization uses Fastify for APIs, NestJS for microservices, and Express for legacy systems. Standardizing on one documentation tool seems impossible. SWAGENT's consistent API across all adapters means your DevOps↗ Bright Coding Blog team writes one integration pattern, applied everywhere.
Step-by-Step Installation & Setup Guide
Prerequisites
- Node.js 18+, Bun 1.0+, or Deno 2.0+
- An existing OpenAPI 3.x specification (or
@fastify/swaggerif using Fastify)
Fastify Setup (Recommended for New Projects)
Fastify integration is the most streamlined — SWAGENT reads your spec directly from @fastify/swagger:
# Install the Fastify adapter
npm install @swagent/fastify
# Ensure you have @fastify/swagger registered with your routes
npm install @fastify/swagger
import Fastify from 'fastify';
import swagger from '@fastify/swagger';
import { swagentFastify } from '@swagent/fastify';
const app = Fastify();
// Register swagger with your API metadata
app.register(swagger, {
openapi: {
info: { title: 'My API', version: '1.0.0' },
servers: [{ url: 'https://api.example.com' }],
},
});
// Define your routes with schemas as usual...
// app.get('/users', { schema: {...} }, handler);
// Three lines to enable SWAGENT
app.register(swagentFastify, {
baseUrl: 'https://api.example.com',
});
await app.listen({ port: 3000 });
What you get automatically:
GET /→ HTML landing page (orllms.txtwithAccept: text/markdown)GET /llms.txt→ Token-optimized AI documentationGET /to-humans.md→ Full markdown referenceGET /openapi.json→ Raw OpenAPI spec passthrough
Express Setup (Existing Projects)
For Express applications with an existing OpenAPI spec file:
npm install @swagent/express
import fs from 'fs';
import express from 'express';
import { swagentExpress } from '@swagent/express';
const app = express();
// Load your existing OpenAPI specification
const spec = JSON.parse(fs.readFileSync('./openapi.json', 'utf-8'));
// Mount SWAGENT at root or subpath
app.use(swagentExpress(spec, { baseUrl: 'https://api.example.com' }));
// Or mount on a subpath for namespacing:
// app.use('/docs', swagentExpress(spec, { baseUrl: 'https://api.example.com' }));
app.listen(3000);
Content is lazily cached on first request, minimizing startup impact.
CLI for Static Site Generation
Don't want to integrate into your application? Generate static files:
# Install globally or use npx
npx swagent generate ./openapi.json
# Full configuration
swagent generate ./openapi.json \
-o ./docs \
-b https://api.example.com \
-f all \
--theme dark
# Generate from remote spec
swagent generate https://api.example.com/openapi.json
# Single format for specific use cases
swagent generate ./spec.json -f llms-txt # AI-optimized only
swagent generate ./spec.json -f human # Developer markdown only
swagent generate ./spec.json -f html # Landing page only
# Development mode with auto-regeneration
swagent generate ./spec.json --watch
Outputs land in ./docs by default: llms.txt, to-humans.md, index.html.
Configuration for Subpath Mounting
When mounting under a parent router, set prefix to ensure self-referencing links resolve correctly:
// Elysia example with prefix
const PREFIX = '/docs';
new Elysia({ prefix: PREFIX }).use(
swagentElysia(spec, {
baseUrl: 'https://api.example.com',
prefix: PREFIX // Critical for correct link generation
}),
);
Without this, <link rel="alternate"> tags and format-card footers 404.
REAL Code Examples from SWAGENT
Example 1: The Three-Line Fastify Integration
This is the integration that launched a thousand deployments. The README's "three lines, four endpoints" promise delivers:
import { swagentFastify } from '@swagent/fastify';
// After registering @fastify/swagger with your routes:
app.register(swagentFastify, { baseUrl: 'https://api.example.com' });
// GET / -> HTML landing page
// GET /llms.txt -> Token-optimized for AI agents
// GET /to-humans.md -> Full markdown docs
// GET /openapi.json -> OpenAPI JSON spec
Why this matters: Fastify's plugin architecture means @fastify/swagger has already collected all route schemas during registration. SWAGENT taps into this existing metadata — no duplicate schema definitions, no manual spec maintenance. The baseUrl parameter ensures all generated links and references point to your canonical API domain. Content generates once at startup, then serves from memory with ETag validation.
Example 2: Content Negotiation in Action
This cURL demonstration from the README reveals SWAGENT's core innovation:
# Browser gets HTML landing page — standard request, no headers needed
curl https://api.example.com/
# LLM agent gets token-optimized docs — same URL, standard HTTP
curl -H "Accept: text/markdown" https://api.example.com/
The technical depth: This uses HTTP's Accept header negotiation, defined in RFC 7231. SWAGENT's server layer inspects incoming headers and routes to format-specific generators. The Vary: accept response header ensures CDNs cache variants separately — your edge cache won't serve markdown to browsers or HTML to agents. The x-markdown-tokens: 1842 header (shown in curl -I responses) lets LLM orchestrators pre-check context window fit.
Example 3: Compact Notation Deep Dive
The llms.txt format is where SWAGENT's token optimization shines. Here's the README's 20-endpoint Pet Store example:
# Pet Store API
> A sample API for managing pets and orders.
Base: https://api.petstore.io
Docs: [HTML](https://api.petstore.io/) | [OpenAPI JSON](https://api.petstore.io/openapi.json)
## Auth Methods
- JWT: `Authorization: Bearer <token>` via POST /auth/login
- API Key: `X-API-Key: <key>` header
## Conventions
- Auth: JWT = Bearer token, KEY = API Key, JWT|KEY = either, NONE = no auth
- `*` after field name = required, all fields string unless noted with `:type`
- Common errors: 400/401/404 return `{success:false, error}`
---
## Auth
### POST /auth/login - Login | NONE
Body: `{email*, password*}`
200: `{token, expiresIn:number}`
## Pets
### GET /pets - List pets | JWT
Query: ?page:integer ?limit:integer ?species
200: `{data:[{id, name, species, age:number}], total:number}`
### POST /pets - Create pet | JWT
Body: `{name*, species*, age:number, vaccinated:boolean}`
200: `{id, name}`
### GET /pets/{petId} - Get pet | JWT|KEY
Path: :petId*
200: `{id, name, species, age:number, vaccinated:boolean, owner:{id, name}}`
Decoding the compression:
email*— asterisk denotes required; replaces"email": { "required": true, "type": "string" }age:number— colon-type notation; replaces full JSON Schema type declaration{id, name, species}— inline object shorthand; no$refresolution neededJWT|KEY— auth shorthand; replaces full security scheme references- Convention deduplication — 400/401/404 errors defined once, not per endpoint
- Response focus — only 200 responses shown; errors covered by conventions
An LLM parsing this learns the entire API surface in ~1,800 tokens versus 7,000+ for equivalent OpenAPI JSON.
Example 4: Programmatic Core Usage
For custom integrations or build pipelines, SWAGENT's core library exposes direct generators:
import { generate } from '@swagent/core';
import fs from 'fs';
// Load and parse your OpenAPI specification
const spec = JSON.parse(fs.readFileSync('./openapi.json', 'utf-8'));
// Generate all three output formats
const output = generate(spec, { baseUrl: 'https://api.example.com' });
// Token-optimized string for AI agents
output.llmsTxt; // Compact notation, ~75% smaller than JSON
// Full markdown for human developers
output.humanDocs; // Complete reference with ToC and tables
// Semantic HTML string for browsers
output.htmlLanding; // Zero-dependency, dark theme, instant load
Advanced pattern: Use this in CI/CD pipelines to pre-generate documentation artifacts, then deploy to static hosting or embed in container images. The synchronous generate() call means zero runtime dependency on OpenAPI parsers in production.
Example 5: Private Documentation with Token Auth
For internal APIs, SWAGENT's built-in auth gate protects all doc routes without affecting your application endpoints:
# Set token via environment variable (recommended)
export SWAGENT_TOKEN=sk_your_long_random_token
import { swagentFastify } from '@swagent/fastify';
app.register(swagentFastify, {
baseUrl: 'https://api.example.com',
// Auto-reads from SWAGENT_TOKEN env if omitted
auth: { token: process.env.SWAGENT_TOKEN },
});
Client access patterns:
# LLM agent with query parameter (best for copy-paste URLs)
curl "https://api.example.com/llms.txt?access_token=sk_..."
# Programmatic client with Bearer header
curl -H "Authorization: Bearer sk_..." -H "Accept: text/markdown" https://api.example.com/
# Browser: visit /, submit token in form, HttpOnly cookie handles rest
Security details: constant-time token comparison prevents timing attacks. Cache-Control: no-store on 401s prevents credential caching. Cookie is HttpOnly, SameSite=Lax, Secure by default.
Advanced Usage & Best Practices
Optimize for Your LLM Provider's Tokenizer
SWAGENT's token estimates use a generic approximation. For production cost optimization, pass generated llms.txt through your provider's actual tokenizer (OpenAI's tiktoken, Anthropic's tokenizer) and adjust compression settings if needed.
Leverage ETags for Agent Memory Systems
If your agent caches API documentation between sessions, store the ETag from initial fetch. Subsequent requests with If-None-Match return 304 Not Modified — zero bytes transferred, instant validation. This matters for agents that "re-learn" APIs on each invocation.
Combine with Function Calling Schemas
Generate llms.txt for semantic understanding, but pair with structured function definitions for actual tool use. SWAGENT's compact notation helps the LLM choose the right endpoint; your existing JSON Schema validates parameters at runtime.
Use --watch Mode for Documentation-Driven Development
Run swagent generate ./spec.json --watch during API design. The instant feedback loop lets you see how schema changes affect token count and readability before committing.
Mount on Subpaths for Versioned APIs
app.use('/v1/docs', swagentExpress(v1Spec, { baseUrl: 'https://api.example.com/v1' }));
app.use('/v2/docs', swagentExpress(v2Spec, { baseUrl: 'https://api.example.com/v2' }));
Each version gets independent documentation with correct self-references.
Comparison with Alternatives
| Feature | SWAGENT | Swagger UI | Redoc | Raw OpenAPI JSON | Custom /llms.txt |
|---|---|---|---|---|---|
| AI-optimized format | ✅ Native llms.txt |
❌ Unparseable | ❌ Unparseable | ❌ Verbose | ✅ Manual maintenance |
| Human-readable docs | ✅ Markdown + HTML | ✅ Interactive UI | ✅ Interactive UI | ❌ Raw JSON | ❌ None |
| Single URL serving | ✅ Content negotiation | ❌ Separate paths | ❌ Separate paths | ❌ Separate file | ❌ Separate file |
| Token efficiency | ✅ ~75% reduction | ❌ N/A (UI) | ❌ N/A (UI) | ❌ Baseline | ✅ Variable |
| Zero client config | ✅ Standard HTTP | ✅ Browser only | ✅ Browser only | ✅ Any HTTP | ❌ Hardcoded path |
| Framework adapters | ✅ 7 + CLI | ❌ Standalone | ❌ Standalone | ❌ N/A | ❌ DIY |
| Built-in auth | ✅ Token gate | ❌ None | ❌ None | ❌ None | ❌ DIY |
| CDN cache friendly | ✅ ETag + Vary | ⚠️ Static assets | ⚠️ Static assets | ✅ Simple | ✅ Simple |
| Maintenance overhead | ✅ One spec, three outputs | ⚠️ UI updates | ⚠️ UI updates | ✅ None | ❌ Parallel docs |
The verdict: Swagger UI and Redoc remain excellent for human exploration but actively harm AI integration. Raw OpenAPI JSON is complete but wasteful. Custom /llms.txt files work until they drift from your canonical spec. SWAGENT eliminates the false choice between human and machine readability.
FAQ
Is SWAGENT a replacement for Swagger UI or Redoc?
No — it's a complement that adds AI-native documentation to your existing toolchain. You can run SWAGENT alongside traditional docs during migration, or replace them entirely if your audience skews technical/automated.
Does SWAGENT require me to rewrite my OpenAPI spec?
Absolutely not. SWAGENT consumes standard OpenAPI 3.x specifications. If you already use @fastify/swagger, SwaggerModule in NestJS, or maintain a openapi.json file, you're ready to integrate.
How does content negotiation work with CDNs and proxies?
SWAGENT returns Vary: accept on all responses, instructing caches to key on the Accept header. ETags are format-specific, so If-None-Match validates correctly for both HTML and markdown variants.
Can I disable routes I don't need?
Yes — set any route to false in the configuration:
{ routes: { humanDocs: false, openapi: false } }
This serves only AI-optimized and HTML formats.
Is the token count header accurate for all LLM providers?
The x-markdown-tokens header provides a reasonable estimate based on whitespace-delimited tokens. For precise budgeting with specific providers (Claude, GPT-4, Llama), pass the content through the provider's actual tokenizer.
Does SWAGENT support OpenAPI 2.0 / Swagger 2.0?
Currently OpenAPI 3.x only. Convert legacy specs using swagger2openapi or similar tools before ingestion.
What happens if my OpenAPI spec is malformed?
All adapters serve fallback content with a 200 status — your application stays available. Check server logs for generation errors, fix the spec, and restart to regenerate.
Conclusion: The Documentation Paradigm Shift Is Here
We've spent a decade optimizing API documentation for human consumption — prettier UIs, better search, interactive try-it panels. Then LLM agents arrived, and suddenly every navigation wrapper, every repeated schema, every pixel-perfect animation became a tax on intelligence.
SWAGENT represents a fundamental rethinking: one canonical source, multiple optimized outputs, zero configuration for consumers. The same URL serves your human developers, your AI integrations, and your browser-based explorers without maintaining parallel pipelines or training agents on custom discovery conventions.
The 75% token reduction isn't a marginal improvement — it's the difference between fitting API documentation into a 4K context window versus failing entirely. It's the difference between sub-second agent initialization and timeouts. It's the difference between profitable AI integrations and runaway inference costs.
I've evaluated dozens of documentation tools. None nail the AI-native requirement while preserving human usability. SWAGENT's content negotiation approach is so obviously correct in retrospect that you'll wonder why it wasn't standard practice years ago.
Ready to stop wasting tokens? Install SWAGENT, point your agent at your API root, and watch it just work. The future of API documentation is multi-species — human and machine, served from one source of truth.
⭐ Star SWAGENT on GitHub — and tell your AI agent: "Learn https://api.example.com"