Comparison · Content negotiation · Updated 2026

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.txtMarkdown 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:

AgentSends 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

How to Ship Both in an Afternoon

  1. Publish the index first. Draft /llms.txt from 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.
  2. Add the delivery layer. On Cloudflare, enable Markdown for Agents in the zone's Quick Actions. Off Cloudflare, read the Accept header and return Markdown with Content-Type: text/markdown, or pre-generate twins at build time if your content is already authoring in Markdown.
  3. 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.
  4. Verify both paths. One request per page: a plain fetch that must still return HTML, and an Accept: text/markdown request that must return Markdown plus Vary: 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.