Markdown for Agents vs llms.txt: Content Negotiation or Curated Index?
Two 2026 conventions are fighting for the same phrase: "serve Markdown to AI." One is a file that describes your site. The other is a request header that changes how a single page arrives. They are not competitors, and treating them as such is why a lot of agent-readiness work misses half the surface.
The Short Answer
| llms.txt | Markdown for Agents | |
|---|---|---|
| Question it answers | What exists on this site, and what is worth an agent's context window? | Can I have this one page as clean Markdown, please? |
| Unit of work | The whole site, or every page under a path such as /docs/llms.txt | A single URL per request |
| Mechanism | A static Markdown file you curate | HTTP content negotiation on the Accept header |
| Discovery | The /llms.txt convention and the rel="describedby" link relation | None — the client has to know to ask |
| Where you implement it | Your repo, CMS or static assets | Your CDN, edge worker, or framework routes |
The one-line version: llms.txt handles discovery, Markdown for Agents handles delivery. An agent that never finds your page does not benefit from your perfect Markdown endpoint, and an agent that finds your page but receives 180,000 tokens of div soup pays for the privilege.
llms.txt Is a Map, Not a Pipe
The proposal by Jeremy Howard was updated to v2 in August 2026 and still describes a plain
Markdown file: one H1, a blockquote summary, then H2 sections of linked resources with
one-line descriptions. The v2 text formalises what practitioners had already started doing —
the file can sit at the site root or at any path, covering the pages beneath it. That is why
Cloudflare's developer documentation ships a root
developers.cloudflare.com/llms.txt that is mostly a list of per-product files
(Workers, R2, D1, AI Gateway and so on), each with its own full index:
> Each product below links to its own llms.txt, which contains a full
> index of that product's documentation pages and is the recommended
> way to explore a specific product's content.
## Developer platform
- [Workers](https://developers.cloudflare.com/workers/llms.txt): Build, deploy, and scale serverless applications
- [D1](https://developers.cloudflare.com/d1/llms.txt): Create managed, serverless databases with SQL semantics What the file cannot do is hand over content. It points. Whether the agent then fetches HTML or Markdown is a separate decision — which is exactly the gap content negotiation fills. For the spec details, see the llms.txt v2 breakdown.
Markdown for Agents Is a Delivery Format
Cloudflare shipped "Markdown for Agents" on 12 February 2026: for zones with the feature
enabled, a request carrying Accept: text/markdown makes the network convert the
origin's HTML to Markdown in real time and return it from the same URL. Vercel published a
similar pattern on 3 February 2026, implemented as a rewrite in next.config.ts
that routes Markdown-preferring requests to a route handler, plus Markdown sitemaps at URLs
such as vercel.com/docs/sitemap.md.
curl https://developers.cloudflare.com/workers/ \
-H "Accept: text/markdown"
HTTP/2 200
content-type: text/markdown; charset=utf-8
vary: accept
x-markdown-tokens: 725
content-signal: ai-train=yes, search=yes, ai-input=yes
Three headers on that response are worth more than the Markdown itself. Vary: accept
keeps caches from serving the Markdown version to browsers. The
content-type tells the client it got what it asked for, so it skips its own
conversion step. And x-markdown-tokens is a hint about context cost that an agent
can use for chunking decisions.
Which Agents Actually Ask for Markdown
Content negotiation only pays off when the client sends the header. Checkly tested seven widely used coding agents in February 2026 by pointing their built-in web-fetch tools at a header echo endpoint. The result was a near-even split:
| Agent | Sends Accept: text/markdown? |
|---|---|
| Claude Code (Fetch, v2.1.38) | Yes — text/markdown, text/html, */* |
| Cursor (WebFetch, 2.4.28) | Yes — text/markdown with q-values |
| OpenCode (webfetch, 1.2.5) | Yes — text/markdown;q=1.0 |
| OpenAI Codex (Feb 2026 build) | No — browser-style HTML header |
| Gemini CLI (0.28.2) | No — */* |
| GitHub Copilot (fetch_webpage) | No |
| Windsurf (read_url_content) | No |
Treat the table as a snapshot, not a law: tool versions move monthly, and crawlers such as GPTBot or OAI-SearchBot are a different population from IDE agents. The underlying mechanics are also unchanged — a server that ignores the header loses nothing, because the client will fall back to HTML and convert it itself.
Where the Two Meet: Markdown Twins
The interesting design work happens when the map points at the pipe. llms.txt v2 recommends
publishing a Markdown twin for each listed page — either by appending the extension
(page.html.md) or replacing it (page.md) — and it defines two link
relations to make the pairing machine-readable: rel="alternate" type="text/markdown"
for the Markdown version of a page, and rel="describedby" for the llms.txt file that
covers it.
Checkly's live file, fetched in September 2026, is a clean example of both layers in one place:
it documents Accept: text/markdown support for every page URL, lists a set of
hand-authored twins (/pricing.md, /cli.md), and ships scoped indexes
at /docs/llms.txt and /product/llms.txt — so an agent can arrive
through the index and then read each page in its cheapest form. Vercel's post describes the
fallback for agents that never send the header: a link rel="alternate"
type="text/markdown" tag in the HTML head.
What Neither One Buys You
- Rankings. Google has consistently said llms.txt is not a Search signal, and changing the representation served to a requesting agent is not a ranking tactic either. Both belong to agent readiness, not to ranking.
- Citation share. Getting cited in an AI answer still depends on the content, not the container. Markdown reduces cost and latency; it does not make a thin page authoritative.
- Coverage. Markdown for Agents helps the agents that already browse your site. It does nothing for the ones that never discovered it — that is the index's job, and most published files still see very few fetches.
How to Ship Both in an Afternoon
- Publish the index first. Draft
/llms.txtfrom your sitemap with the generator, keep it to the 10–50 pages that answer real questions, and validate it with the checker before you touch the CDN. - Add the delivery layer. On Cloudflare, enable Markdown for Agents in the zone's Quick Actions. Off Cloudflare, read the
Acceptheader and return Markdown withContent-Type: text/markdown, or pre-generate twins at build time if your content is already authoring in Markdown. - Connect them. Point the links inside llms.txt at the Markdown twin where one exists, and add
rel="alternate" type="text/markdown"to the pages you care about most. - Verify both paths. One request per page: a plain fetch that must still return HTML, and an
Accept: text/markdownrequest that must return Markdown plusVary: accept. If the second returns HTML, the conversion never triggered — that is the failure to watch for.
Related reading: the same "two layers" split in the action domain, covered in llms.txt vs MCP, and the measured reality of who fetches these files in which AI engines read llms.txt.