# How to write agent-readable documentation for AI agents.

> Agent-readable documentation in practice: what documentation for AI agents must answer, how to shape a page around one decision, and how to keep it true.

Published: 2026-09-05  
Updated: 2026-10-13  
Changelog: 2026-10-14: Corrected Codex instruction layering and qualified the Markdown-twin drift claim.  
Changelog: 2026-09-16: Expanded from a short note into a full guide with sources, examples and FAQ.  
Canonical: https://agentexperience.tech/insights/make-documentation-legible/  
Tags: documentation, discovery, tools, llms.txt, openapi

**Summary**

Agent-readable documentation is the text an agent holds at the moment it commits to an action: a Markdown copy of a page, an `llms.txt` index, an OpenAPI document, a tool description, a repository `AGENTS.md`. Documentation for AI agents works when a single page answers six things without a second fetch: what the capability is for, what must already be true, what it needs and where that comes from, what a success looks like, how it fails, and which neighbouring capability is the better choice.

1. Documentation for AI agents is a narrower set of artefacts than the phrase our docs suggests, each with its own consumer, and an index such as llms.txt is not a contract.
2. The model and the harness read different things: OpenAPI and JSON Schema are mostly consumed by the runtime, while the model sees the narrower description the harness gives it.
3. The six questions are purpose, preconditions, inputs and where they come from, the shape of success, named failure modes and the neighbouring capability.
4. Retrieval fetches fragments rather than whole sites, so each section has to make sense without the ones above it.
5. Guard against drift: review the text in the pull request that changes the behaviour, date each page against the system it describes, and keep cases for mistakes already fixed.

Documentation for AI agents is working context. It is read at the moment the agent chooses, by a reader with no colleague to ask and no memory of last quarter.

A person reading your documentation brings a great deal that is not on the page. They remember the migration, they know which colleague owns the billing service, they have learned to check the changelog before believing an example. An agent may lack that history. What it can inspect depends on its harness and available sources, so a page should make the next decision possible without unstated context. Agent-readable documentation is there to close that gap, and that is mostly a writing problem rather than a formatting one.

## Which documents does an agent actually read?

Fewer than the phrase "our docs" suggests. Agent harnesses pick up a small, well-known set of artefacts, and each one has a different consumer.

| Artefact | What it carries | Who consumes it | Status |
| --- | --- | --- | --- |
| [`llms.txt`](https://llmstxt.org/) | A short Markdown index at the site root pointing to the pages worth reading | Retrieval agents and doc navigators | A published convention, not a standards-track document |
| Markdown twin of a page | The same content as the HTML page without navigation, scripts or layout | Anything that fetches and reads | An implementation choice, not a spec |
| [OpenAPI 3.2.0](https://spec.openapis.org/oas/v3.2.0.html) | Operations, parameters, authentication and response shapes for an HTTP API | Usually the harness or a code generator, then converted into tool metadata | Published specification |
| [JSON Schema 2020-12](https://json-schema.org/specification) | Machine-checkable shapes for tool arguments and outputs | Validators and structured-output runtimes | Current meta-schema |
| Tool names, descriptions and annotations | What an action is for, when it is wrong, what it needs | The model, at the moment of selection | Defined by the [MCP specification](https://modelcontextprotocol.io/specification/2026-07-28/server/tools) and equivalent vendor formats |
| [`AGENTS.md`](https://agents.md/) | Durable repository conventions: build commands, hazards, house rules | Coding agents and CLI or IDE harnesses | Open format with no required fields |

Two distinctions in that table matter. The model and the harness read different things: OpenAPI and JSON Schema are mostly consumed by the runtime, which validates against them, while the model sees whatever narrower description the harness synthesises. And an index does not bind anything. [OpenAI's guidance on `AGENTS.md`](https://learn.chatgpt.com/docs/agent-configuration/agents-md) describes an instruction chain: global guidance, then project files from the root down to the working directory. Codex combines those files, with later, more local guidance taking precedence when instructions conflict. It selects at most one instruction file per directory and applies a combined size limit; check the active chain rather than assuming only the nearest file is read. Some services now publish one more artefact for agents: a file such as `auth.md` that explains how an agent can register, or start without an account, which is the subject of [Let agents start before anyone signs up](/insights/let-agents-start-before-sign-up/).

## The six questions a page has to answer

An agent can only act once the page has settled six things. The list is a working checklist rather than anyone's standard, though it echoes a decomposition the literature uses: selection, argument construction and execution fail independently, which is how [API-Bank](https://aclanthology.org/2023.emnlp-main.187/) (Li et al., EMNLP 2023) was built.

1. **Purpose, in the language of the job.** What situation is this for? "Reconcile a payment that arrived without a reference" beats "wraps the reconciliation endpoint".
2. **Preconditions.** What must already be true: an authenticated session, a record in a particular state, a prior step completed. Unstated preconditions become malformed calls.
3. **Inputs and their provenance.** Not only the field names but where each value comes from. "The customer ID returned by the lookup call, not an email address" removes a round trip of guessing.
4. **The shape of success.** What the caller gets back, in enough detail to branch on. If the result is a status, enumerate the statuses.
5. **Failure modes, named.** An agent that cannot tell "not found" from "not permitted" will retry the wrong thing. Errors it can tell apart let it recover instead of retrying blindly.
6. **The neighbouring capability.** Say plainly what this is not for, and name what to use instead. Ambiguity between two similar options is the costly kind.

[Diátaxis](https://diataxis.fr/) makes a related argument for human readers: a page that tries to be a tutorial, a reference and an explanation at once serves none of them. The agent-facing version is stricter, because an agent will not notice that it has landed in the wrong kind of page.

## What the rewrite looks like

Here is the same capability documented twice. Both versions are invented for illustration and describe no real product.

```markdown
<!-- Before -->
### POST /v3/holds

Creates a hold. Requires a valid token. Returns 201 on success.
Params: `acct`, `amt`, `cur`, `exp`.
```

```markdown
<!-- After -->
### Place a temporary hold on a customer account

**Use this when** you need to reserve funds before a shipment is confirmed,
and you expect to capture or release them within seven days.
**Do not use this** to take payment. Capturing a hold is a separate action
(`capture_hold`); releasing it early is `release_hold`.

**Preconditions.** The account must be `active` and already have a verified
payment method. A held account or one in `review` returns `409`.

**Inputs**
- `account_id` (string): as returned by `find_account`. Not an email address.
- `amount_minor` (integer): minor units, so £12.50 is `1250`.
- `currency` (string): ISO 4217, one of `GBP`, `EUR`, `USD`.
- `expires_at` (RFC 3339 timestamp, UTC): at most seven days ahead.
  Omitting it defaults to 72 hours.

**On success.** `201` with `{ "hold_id": "...", "state": "held",
"expires_at": "..." }`. The hold is visible to the customer immediately.

**Failure modes**
- `409 account_not_eligible`: do not retry, check account state first.
- `422 amount_exceeds_limit`: the limit is per account, not per hold.
- `429`: retry with backoff, holds are idempotent on `idempotency_key`.

Last verified against the API: 2026-09-19.
```

The second version is longer, and the extra length is useful. It removes the reasons an automated caller would get this wrong: the wrong unit, the wrong identifier, a retry on an error that will never succeed, a capture that was actually a hold. Note the date at the bottom, too.

![The rewritten hold page from top to bottom, each part labelled with the question it answers. 1, purpose: the heading, Place a temporary hold, and the 'Use this when' line, reserving funds before a shipment is confirmed. 6, the neighbouring capability, highlighted and placed second: 'Do not use this' to take payment, with capture_hold and release_hold named. 2, preconditions: the account is active and has a verified payment method. 3, inputs and where they come from: account_id from find_account, amounts in minor units, an ISO 4217 currency. 4, the shape of success: 201 with hold_id, state and expires_at. 5, failure modes: 409, 422 and 429, each with what to do next. Last, the date the page was verified: 2026-09-19.](https://agentexperience.tech/diagrams/documentation-six-questions.svg)

*Figure: The six questions, answered in the rewritten example.*

## How this site publishes its own documentation

The only setup we can describe first-hand is this site's own. Every guide in the library is served twice: as HTML at `/insights/<slug>/`, and as Markdown at `/insights/<slug>.md`, generated from the same content collection to reduce drift; the build checks that the Markdown twins are present and correctly linked. The field map at `/research/` and the reference pages under `/resources/` carry the same twins. A curated index lives at `/llms.txt`, and the whole library concatenated lives at `/llms-full.txt`, for agents that would rather read once than crawl twenty times.

The repository has an `AGENTS.md` at its root, and it is deliberately not a wiki. It carries build and check commands, the import rules the serverless function requires, and the hazards that have actually broken a deployment. It is kept short because a repository instruction file competes with the task for context. None of this is offered as evidence that it works. It is a description of the artefacts, and anyone can inspect them.

## What the research says about documentation and retrieval

Researchers started treating tool documentation as infrastructure fairly early. Hsieh et al. (2023), in [*Tool Documentation Enables Zero-Shot Tool-Usage with Large Language Models*](https://arxiv.org/abs/2308.00675), compare documentation-only prompting with few-shot demonstrations and argue that tool documentation deserves first-class treatment in its own right. [Gorilla](https://arxiv.org/abs/2305.15334) (Patil et al., NeurIPS 2024) pairs a retriever over API documents with fine-tuning so that a model can adapt when the documentation changes rather than when the weights do.

Two consequences follow. Because retrieval fetches fragments rather than whole sites, a fragment has to stand on its own: a section that only makes sense after the three above it will be retrieved without them. And because documentation is the adaptation layer, keeping it current is a functional requirement. [Wu et al. (ACL 2026 Findings)](https://aclanthology.org/2026.findings-acl.1082/) argue that static toolsets are unrealistic and study continual documentation adaptation as APIs version, deprecate and reappear. [Guo et al. (2026)](https://arxiv.org/abs/2602.20426) go further and treat rewriting the description itself as something you can work on deliberately.

## Keeping it true

Documentation review exists mainly to catch drift. [StableToolBench](https://aclanthology.org/2024.findings-acl.664/) (ACL 2024 Findings) introduced simulated APIs and caching to build a stable benchmark at all, because the real ones kept changing underneath it. Your documentation has the same problem without the caching layer.

Three habits keep it in check. Review the text in the pull request that changes the behaviour. Date each page against the system it describes, so a reader can weigh a stale example correctly. And keep a small set of cases encoding mistakes you have already fixed, so a rewrite cannot quietly reintroduce an ambiguity you removed last month. The [MCP tool-description test-case fixture](/resources/mcp-tool-description-test-cases/) is a public example of that shape: a target intent, the nearest competing tool, valid and schema-invalid inputs, the result shape, and a changed retry path.

## Frequently asked questions

**What is agent-readable documentation?**
It is documentation written so that an automated reader can act on one page without fetching three more. In practice that means a stated purpose, the preconditions, the exact inputs and where they come from, the shape of a successful result, the named failure modes, and a pointer to the neighbouring capability. The format matters less than whether those six things are present in the same place.

**Which files do AI agents actually read?**
It depends on the harness, but the common set is small: an `llms.txt` index at the site root, Markdown versions of documentation pages, OpenAPI documents and JSON Schemas consumed by the harness rather than the model, tool names and descriptions delivered over a protocol such as MCP, and repository files such as `README` and `AGENTS.md` for coding agents. Treat each as a different audience with a different budget.

**Does writing documentation for AI agents make it worse for people?**
It should not, because the two readers want the same things in a different order. Stating preconditions, naming error cases and linking the nearest alternative helps a new engineer as much as an agent. What changes is that implicit context stops being acceptable, since the automated reader cannot recover it from a colleague.

**How often should agent-facing documentation be reviewed?**
Review it in the same change that alters the behaviour it describes, and record the date the text was last checked against the running system. Research on tool-using agents treats documentation drift as a first-class problem rather than an editorial afterthought, with work such as Wu et al. (ACL 2026 Findings) arguing that static toolsets are unrealistic. A wrong description is more dangerous than a missing one, because it is followed confidently.

Read your own page the way an agent gets it: one document, no history, and a decision to make at the end.
