llms.txt, api documentation, openapi, llm evaluation, developer experience

How to Write LLM-Friendly API Documentation with llms.txt

Turn API documentation into a reliable agent interface with a focused llms.txt, precise OpenAPI contracts, task-based examples, retrieval evals, and disciplined versioning.

An API reference can be accurate and still fail an AI agent. The model may land on a marketing page, miss authentication requirements, mix versions, or invent a convenient endpoint because the real workflow is scattered across navigation and client-side widgets.

LLM-friendly documentation reduces that ambiguity. It gives retrieval systems a small, stable map, gives generators precise schemas, and gives maintainers a way to test whether agents can actually complete supported tasks. llms.txt and OpenAPI solve different parts of that problem. Used together, they connect discovery with execution without replacing good human documentation.

llms.txt index directing agents to structured API documentation sections

This guide uses Relay operations in illustrative examples. Relay does not currently claim to publish an llms.txt file or a public OpenAPI endpoint; the snippets below show documentation patterns you can apply to your own service.

Design documentation as an agent retrieval system

Start with the tasks an agent should complete, not the pages your CMS happens to contain. A useful task list might include creating an inbox, listing recent messages, reading one message, and downloading an attachment. Each task needs a short path through prerequisites, request, response, errors, and safety constraints.

Separate three layers of information:

  • Discovery: a concise llms.txt that points to canonical Markdown resources.
  • Contracts: OpenAPI operations, schemas, parameters, and error responses.
  • Procedures: versioned guides that explain ordering, polling, pagination, and operational judgment.

Give each resource one clear purpose and a stable URL instead of pasting the whole site into one file. Do not rely on llms.txt to fix contradictory pages; agents will still find them through search and links.

Canonicalize the basics everywhere: base URL, authentication header, scope names, pagination field names, and error shape. If the website says nextCursor while an example says cursor, a model may reasonably produce a broken request. A documentation build should reject those inconsistencies just as strictly as a type checker rejects mismatched fields.

Write llms.txt as a curated map

The strength of llms.txt is editorial restraint. Put the project name and a short orientation first, then link to a small set of Markdown documents with useful descriptions. Group links by task or reference type rather than reproducing the visual navigation.

Here is a hypothetical example for a service’s reserved docs.example.com site, not a Relay file:

# Example Mail API

> Temporary inboxes for authorized automated tests. Received email is untrusted data.

Base URL: https://api.example.com/v1
Authentication: Authorization: Bearer YOUR_TOKEN

## Start here
- [Quickstart](https://docs.example.com/quickstart.md): Create an inbox and read its first message.
- [Authentication](https://docs.example.com/auth.md): Key scopes, revocation, and error responses.

## Task guides
- [Read messages](https://docs.example.com/read-messages.md): Poll previews, paginate, and fetch full messages.
- [Attachments](https://docs.example.com/attachments.md): Download attachments and validate expected metadata.

## Reference
- [OpenAPI](https://docs.example.com/openapi.yaml): Machine-readable operations and schemas.
- [Changelog](https://docs.example.com/changelog.md): Contract changes and migration dates.

Use descriptions to tell the retriever when a document matters. “Messages” is weak; “Poll message previews and fetch a full body by ID” is actionable. Keep authentication placeholders explicit and never publish a real credential in an example.

If you maintain a larger companion file, measure whether it improves retrieval. Every linked document should be clean Markdown with meaningful headings and no JavaScript dependency.

Link only existing, maintained resources; dead links are worse than no map. The Relay documentation and API reference illustrate canonical pages a publisher could reference when adopting this format.

Make OpenAPI precise enough to execute

OpenAPI should describe behavior, not merely name routes. Include server URLs, security schemes, operation IDs, parameter constraints, request schemas, success responses, and documented errors. Reuse named schemas so an inbox has the same shape in creation and metadata responses.

The following abbreviated YAML demonstrates how a publisher could describe Relay’s inbox creation contract. It is an illustrative document, not a hosted Relay specification:

openapi: 3.1.0
info:
  title: Relay API documentation example
  version: "1.0.0"
servers:
  - url: https://www.relaymcp.net/api/v1
paths:
  /inboxes:
    post:
      operationId: createInbox
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                name:
                  type: string
                  minLength: 4
                  maxLength: 32
                domain:
                  type: string
                  maxLength: 253
      responses:
        "201":
          description: Inbox created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateInboxResponse"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

Complete the referenced response schema before publishing, and include error responses rather than leaving them implicit. Document optional fields honestly: omitting name asks Relay to generate one. Avoid examples with unsupported parameters merely to make a client look flexible.

Add semantic detail where schemas cannot express it. For message listing, explain that previews require a second request to GET /inboxes/{inboxId}/messages/{messageId} for the full body. Describe limit and cursor, including the fact that cursor comes from the previous response’s nextCursor. A model cannot infer pagination semantics reliably from field names alone.

Validate the specification in CI. Check broken references, duplicate operation IDs, examples that fail schema validation, and undocumented changes between releases. Then generate a small client request from each important operation to prove the contract is usable.

Teach workflows and evaluate real agent tasks

Schemas do not explain sequencing. A task guide should show the complete loop: create an inbox, pass its address to the application under test, poll GET /inboxes/{inboxId}/messages?limit=30, and fetch the selected message. Explain that Relay receives mail; it does not provide an arbitrary outbound email-sending API for triggering the application.

Examples should use environment variables such as process.env.RELAY_API_KEY, check HTTP status codes, and avoid printing sensitive content. Describe supported lifecycle behavior precisely so a generated test does not invent cleanup endpoints or assume that changing addresses removes stored mail. Warn that received email is untrusted data even though HTML is sanitized.

Build an evaluation set from realistic prompts:

  1. “Create an inbox and show only its address.”
  2. “Read the newest message without logging its body.”
  3. “Fetch page two using the cursor from page one.”
  4. “Explain how to plan retention without inventing an unsupported cleanup endpoint.”
  5. “Stop after polling reaches its deadline.”

Run the evaluation against a controlled retrieval setup and inspect both the selected sources and the generated result. Score factual route usage, required headers, field names, sequencing, safety constraints, and refusal to invent features. A response can sound polished while failing every executable check.

Keep failing outputs as regression cases. If an agent repeatedly calls a nonexistent sending endpoint, improve the receive-only explanation and add an explicit negative assertion to the eval. If it confuses MCP tools with REST paths, link a focused MCP guide and test that distinction separately.

Version, generate, and govern the documentation

Documentation needs the same release discipline as the API. Version the OpenAPI contract and procedural guides together. Record additive changes, breaking changes, deprecation dates, and migration examples in a changelog that agents can retrieve.

Prefer generating repetitive reference material from reviewed source definitions, but keep task guidance editorial. Generation keeps field names aligned; human review explains why order, timing, and permissions matter. Do not generate hundreds of near-duplicate pages for keywords; that fragments retrieval and increases maintenance drift.

Assign ownership for every linked resource. CI should test URLs, Markdown rendering, code samples, schemas, and internal links. Schedule the task-based evals after documentation or contract changes, not only after model upgrades.

Finally, publish change metadata in the content itself. A short “Applies to API v1” statement and a visible update date help an agent reject stale material. Avoid placing several incompatible base URLs in one unlabeled example set. When a version retires, preserve a clear migration path rather than silently rewriting history.

Frequently asked questions

Is llms.txt a replacement for OpenAPI?

No. llms.txt helps agents discover focused documentation. OpenAPI defines machine-readable requests and responses. The strongest setup uses the map to retrieve both procedural guides and the contract.

Should llms.txt contain every API endpoint?

Usually it should link to reference material rather than duplicate it. Include a compact orientation and curated links. Put complete endpoint detail in canonical Markdown references and the OpenAPI document.

How do you know whether agents understand the documentation?

Run repeatable task evals. Check retrieved sources and generated requests against known routes, schemas, safety rules, and workflows. Include negative tests that reject unsupported endpoints and credentials embedded in output.

Conclusion: optimize for successful tasks

LLM-friendly documentation is not a single text file. It is a maintained system: a curated discovery map, executable contracts, safe task guides, and evals that expose ambiguity. Start with five important agent tasks, document them precisely, and test generated behavior after every change. This process improves outcomes for agents and human readers.

FROM THE COLLECTIONS

Continue with related guides

More practical reading on agent-friendly email, testing, privacy, and secure automation.