Your API's first reader is an agent

The first consumer of a new service used to be a developer with a README. Now it's usually a coding agent with a context window. The service should hand that reader its own manual.

Think about what actually happens when someone points Claude or Cursor at your API today. The agent fetches /openapi.json, gets a wall of JSON designed for machines that render documentation, and starts inferring. OpenAPI is the right interchange format, but it's a poor first read: heavy on structure, silent on intent, expensive in tokens.

The llms.txt convention emerged for exactly this reader: a plain markdown index at a well-known path, written to be loaded into a context window. Documentation hosts generate it for doc sites. For live APIs, almost nobody serves one, because it's yet another artifact to keep in sync with the routes. That objection is the interesting part. A framework whose whole thesis is "one schema, every boundary" doesn't have a sync problem.

Served by default, derived from the registry

As of this week, app.start() serves two new paths alongside /openapi.json. Nothing to configure, nothing to regenerate:

GET /llms.txt        # compact index: one line per operation
GET /llms-full.txt   # every operation with its schemas inlined

Both render from the same assembled OpenAPI document the spec endpoint uses, which renders from the same Zod schemas the dispatcher validates with. Add a route, and the index updates. Tighten a schema, and the inlined JSON Schema in /llms-full.txt tightens with it. The documents also describe the error envelope, so an agent learns what failures look like before it sees one.

# orders-service

> Order management for the storefront.

This service is described by an OpenAPI 3.1 document at `/openapi.json`.

## Endpoints

- `GET /orders/{id}` — Fetch one order
- `POST /orders/{id}/refund` — Refund an order and notify the customer

## MCP (Model Context Protocol)

This service is also an MCP server: connect over Streamable HTTP at `/mcp`.

Tools:

- `refund_order` — Refund an order and notify the customer.

That MCP section isn't hardcoded. Components contribute sections by binding values under the AX_SECTION_TAG binding tag, and installMcpHttp contributes the tool listing when you mount the MCP transport. The same DI discovery that wires servers to controllers wires documentation to the components that have something to say. Your own components can join in with one binding.

A manual you can commit

Endpoints work for agents that browse. For coding agents working in a repo, the better delivery is a file they load automatically:

const spec = await server.getApiSpec();
await fs.writeFile(
  'AGENT.md',
  generateAgentContext(spec, {baseUrl: server.url}),
);

The output is a CLAUDE.md-shaped manual for the live API: base URL, auth schemes, the error contract, and every operation with its schemas. Regenerate it in CI and the manual can't drift from the service, because both are projections of the same registry.

Why this is a framework feature

Any team could write this generator in an afternoon, and that's the problem: it becomes one more artifact someone owns, three sprints from being stale. The reason to push it into the framework is the same reason OpenAPI emission lives there. Hand-maintained contracts drift; derived contracts can't. If the first reader of every new API is an agent, then "describes itself to agents" belongs next to "validates its inputs," not in a wiki page about best practices.