Skip to content
anymd
← All posts
article#markdown#llm#tokens#ai-agents

Why Markdown Is the Language of AI Agents

HTML is built for browsers. Models read tokens. Here is why Markdown keeps the structure, drops the noise, and wins the context window.

Duy /zuey/ · Sep 21, 2026 · 6 min read

Ask a language model to write you a document and watch what comes out. Headings with #. Lists with -. Code in triple backticks. Bold in double asterisks.

Nobody told it to. It just speaks Markdown.

That is not an accident, and it is the whole reason anymd.cc exists. If Markdown is what models write, it is also the best thing to feed them. Here is why.

Models read tokens, not pages

A browser sees a web page as a DOM tree. It styles it, lays it out, and paints pixels. Most of the HTML is instructions for that process: classes for the stylesheet, attributes for the scripts, wrappers for the layout grid.

A model sees none of that rendering. It sees a flat sequence of tokens. Every class="flex items-center justify-between" is tokens. Every data-testid, every inline SVG path, every aria-hidden wrapper is tokens. The model has to read all of it, and you pay for all of it.

Three costs stack up:

  1. Money. Input tokens are billed. Markup is input.
  2. Context. Windows are big now, but not infinite. Markup crowds out the content you actually wanted in there, or the other documents you wanted alongside it.
  3. Attention. More noise means more for the model to skip. Models are good at skipping, but not free at it. Clean input is easier to reason about than cluttered input.

A small worked example

Here is a realistic snippet from a modern blog template. Utility classes, a framework's scoped-style attribute, a breadcrumb, a newsletter prompt. Nothing exotic.

<div class="post-wrapper" data-v-3f2a>
  <nav class="breadcrumbs"><a href="/">Home</a> › <a href="/blog">Blog</a></nav>
  <article class="prose lg:prose-xl">
    <h2 class="text-2xl font-bold mt-8" id="setup">Setup</h2>
    <p class="mb-4">Install the CLI, then run <code class="inline-code">init</code>.</p>
    <ul class="list-disc pl-6">
      <li class="mb-1"><strong>Fast</strong>: runs on the edge</li>
      <li class="mb-1"><strong>Open</strong>: MIT licensed</li>
    </ul>
  </article>
  <div class="newsletter-cta">Subscribe for updates!</div>
</div>

Here is the same content as Markdown, after the breadcrumb and the newsletter prompt are recognized as page furniture and dropped:

## Setup

Install the CLI, then run `init`.

- **Fast**: runs on the edge
- **Open**: MIT licensed

Now the numbers. These are illustrative, for this one snippet. Exact token counts depend on the tokenizer and the model.

HTML Markdown
Characters about 560 about 100
Tokens (rough estimate) roughly 150 to 180 roughly 25 to 30
Content preserved heading, paragraph, code, list, emphasis heading, paragraph, code, list, emphasis

Same information. Roughly a fifth of the characters, and markup tends to tokenize less efficiently than prose, so the token gap is usually wider than the character gap. On a real page, with a header, footer, sidebar, related-posts grid and a few kilobytes of inline JSON, the gap gets a lot bigger.

And notice what did not get lost. The heading is still a heading. The list is still a list. The code is still code. That is the part people miss.

Plain text is too plain

If markup is the problem, why not strip everything and send plain text?

Because structure carries meaning. Try it on the snippet above:

Setup Install the CLI, then run init. Fast: runs on the edge Open: MIT licensed

Where does the heading end? Is init a command or a word? Are "Fast" and "Open" list items or a sentence fragment? The model can guess. Guessing is how you get subtle mistakes.

Markdown sits in the sweet spot:

  • Headings give the model a table of contents. It knows which section a sentence belongs to.
  • Lists keep items separate and parallel.
  • Code fences mark exact text. Commands, config and identifiers stay verbatim, with a language hint.
  • Tables keep rows and columns aligned instead of collapsing into a word salad.
  • Links keep their targets, so citations survive.
  • Emphasis survives, cheaply.

All of it costs a character or two, not a whole attribute soup.

Models already think in it

Markdown is everywhere in the text models learn from: READMEs, docs sites, forums, notebooks, wikis. It is also the default output format of nearly every chat interface. Models read it fluently and write it fluently.

Feeding a model Markdown means input and output share a format. Summaries keep the source's headings. Quotes keep their code fences. An agent that reads a Markdown page can cite a section by its heading and be understood.

Chunking gets easier

If you do retrieval-augmented generation, you split documents into chunks before embedding them. Splitting HTML well is painful. Splitting plain text well is guesswork.

Markdown gives you natural boundaries for free. Split on ##. Keep each chunk's heading path as context. Do not break inside a code fence or a table. You end up with chunks that make sense on their own, which is exactly what an embedding model and a retriever want.

Frontmatter is metadata the model can see

Good Markdown documents start with YAML frontmatter. An anymd.cc conversion looks something like this (fields appear only when the source provides them):

---
title: "Setup guide"
author: "Example Author"
published: "2026-09-01"
source: "https://example.com/blog/setup"
domain: "example.com"
language: "en"
kind: web
word_count: 1240
---

That is metadata in the same file, in a format both a parser and a model can read. Your pipeline can filter on it. Your model can use it to say where a fact came from and when it was written. No separate side-channel, no lost context when the document is copied around.

Every anymd.cc conversion comes with frontmatter like this on top.

Humans can read it too

This matters more than it sounds. When an agent's output looks wrong, you debug by reading what went in. Reading 40 KB of minified HTML to figure out why a summary is off is miserable. Reading the Markdown takes a minute.

It also means the same file works in Obsidian, in a Git diff, in a code review, in an email. Markdown is the rare format that is equally at home in a model's context window and in a human's editor.

Where HTML still wins

To be fair: Markdown is not a replacement for HTML everywhere. Complex layouts, interactive widgets, forms and precise visual design are HTML's job. Some pages lose something in conversion, like an elaborate data visualization or a layout that carries meaning by position.

For those cases anymd.cc can also return cleaned HTML with ?format=html: the same extracted content, with the page furniture stripped but HTML semantics kept. And for pipelines that want structured fields, send Accept: application/json.

But for the job of "give a model the content of this page", Markdown is the right default.

The hard part is not the format

Everyone agrees Markdown is nice. The hard part is getting good Markdown out of the real web:

  • Finding the article inside the template, and dropping the rest.
  • Handling pages that render nothing until JavaScript runs.
  • Handling content that is not an article at all: an X thread with quotes and polls, a YouTube video whose content is the transcript, a Hacker News comment tree, a PDF.

That is the work anymd.cc does. It pairs a proven content-extraction engine with site-aware handlers for the platforms where generic extraction falls down.

Try it on the most cluttered page you know:

curl https://anymd.cc/stephango.com/saw

Then read how to convert any URL, give your agent a Markdown memory over MCP, or check the docs. The free plan includes 500 credits a month, and pricing is simple after that.

Models speak Markdown. Stop making them read HTML.

Give your agent clean Markdown.

500 free credits every month. No card.

Start free
# Markdown
Open .md