Content Negotiation voor AI Agents: Waarom Sentry Markdown Serveert in Plaats van HTML
David Cramer, medeoprichter en CPO van Sentry, publiceerde onlangs een praktische gids voor het optimaliseren van content voor AI agents . Zijn argument: "je moet content optimaliseren voor agents, net zoals je dingen optimaliseert voor mensen." Zijn methode vraagt geen nieuw protocol. Ze gebruikt HTTP content negotiation, een standaard die sinds 1999 in de specificatie staat.
Wanneer een verzoek
Accept: text/markdown
bevat, stuurt de server schone markdown terug in plaats van een volledige HTML-pagina. Navigatie, JavaScript en sidebar-widgets zijn gestript, en de agent ontvangt alleen de content.
Wat is Content Negotiation?
Content negotiation is een HTTP-mechanisme waarbij de client aan de server vertelt welk formaat de voorkeur heeft, en de server in dat formaat antwoordt. Het is gedefinieerd in
RFC 9110
en maakt sinds HTTP/1.1 deel uit van het web. Browsers gebruiken het altijd al. Wanneer je browser
Accept: text/html
stuurt, weet de server dat HTML teruggegeven moet worden.
AI agents kunnen hetzelfde mechanisme gebruiken. Wanneer een agent
Accept: text/markdown
stuurt, kan de server een gestripte markdown-versie van de pagina teruggeven. De URL en de content blijven gelijk, alleen de representatie verandert. De server heeft geen aparte API en geen speciale endpoints nodig.
GET /docs/getting-started HTTP/1.1
Host: docs.example.com
Accept: text/markdown, text/html;q=0.9
---
HTTP/1.1 200 OK
Content-Type: text/markdown; charset=utf-8
Vary: Accept
# Getting Started
Install the SDK with your package manager:
```bash
npm install @example/sdk
```
De Drie Optimalisatiegebieden
Cramer noemt drie gebieden waar contentoptimalisatie het meest uitmaakt voor agents. Hij baseert ze op hoe frontier-modellen webcontent verwerken:
Volgorde van Content
Agents lezen sequentieel van boven naar beneden. Als je belangrijkste informatie begraven ligt onder navigatie, breadcrumbs en sidebar-HTML, bereikt de agent het misschien nooit, of verspilt hij tokens om er te komen.
Contentgrootte
Frontier-modellen lezen vaak alleen het eerste deel van grote pagina's om contextvensters te beheren. Kleinere, gefocuste content betekent dat de agent het volledige beeld krijgt in plaats van een afgekapte versie.
Diepte van Nodes
Diep geneste HTML, met divs in divs in divs, voegt tokens toe zonder betekenis toe te voegen. Platte markdown behoudt dezelfde semantiek met een fractie van de markup.
Samen verklaren deze drie gebieden waarom HTML aan een agent tokens verspilt. Een documentatiepagina kan 15.000 tokens zijn als HTML en 3.000 tokens als markdown. De markdown behoudt de koppen, alinea's, codeblokken en links, en laat de structurele overhead weg.
Hoe Sentry Content Negotiation Implementeert
Sentry's aanpak heeft drie lagen. Elke laag lost een ander probleem op.
1. Documentatie: Echte Markdown Serveren
Wanneer een agent Sentry's documentatie opvraagt met Accept: text/markdown, stuurt de server de ruwe MDX-bron terug. Dit is de content die de HTML-pagina genereert, zonder de gerenderde navigatie, JavaScript-bundels of UI-chrome. Sentry herstructureert ook de linkhiërarchie, zodat agents gerelateerde pagina's vinden via een platte sitemap en geen geneste navigatiebomen hoeven te crawlen.
Dit patroon past op de meeste sites. Elke site met documentatie, helpartikelen of gestructureerde content kan de Accept-header detecteren en een gestripte representatie terugsturen.
2. Beveiligde Pagina's: Doorverwijzen naar Programmatische Alternatieven
Wanneer een agent een beveiligde pagina in de Sentry web-UI opvraagt, zoals een dashboard, een issue-detail of projectinstellingen, stuurt Sentry geen inlogscherm. Het verwijst de agent door naar een programmatisch alternatief: de MCP-server, de CLI-tool of de REST API. De agent leert zo waar hij wel toegang heeft tot de data.
3. Bootstrap Discovery: Agents Zichzelf Laten Configureren
Voor Sentry's CLI-tools en integraties kan een agent een markdown-document ophalen dat het doel, de mogelijkheden en de snelstartstappen van de tool beschrijft. De agent leert wat de tool doet en hoe hij hem gebruikt, zonder HTML-documentatiepagina's te parsen.
Dit is hetzelfde principe achter llms.txt . Dat bestand geeft agents een gecureerd, machine-leesbaar startpunt. Content negotiation bepaalt het formaat van een pagina, llms.txt bepaalt welke pagina's de agent eerst leest.
Wie Doet Dit Al?
Ook andere partijen gebruiken content negotiation richting agents:
Sentry
Content negotiation voor docs, beveiligde pagina's en tool-bootstrapping.
Vercel
Bouwde AEO-tracking voor coding agents en beveelt content negotiation aan in zijn State of AEO-rapport.
Cloudflare
Biedt markdown-transformatie en content negotiation als ingebouwde functie in de betaalde pakketten.
Coding Agents
Claude Code, Cursor, Windsurf en Bun sturen Accept-headers die markdown verkiezen bij het ophalen van documentatiepagina's.
Beide kanten bewegen. Sommige contentaanbieders serveren nu markdown, en sommige AI agents vragen erom.
Hoe Content Negotiation te Implementeren
De implementatie bestaat uit drie stappen.
Stap 1: Agent-Verzoeken Detecteren
Controleer de Accept-header op text/markdown. Vergelijk de q-waarden in plaats van alleen op de string te zoeken, zodat een browser die
*/*
stuurt HTML blijft krijgen. Zet ook
Vary: Accept
op elke response:
defmodule MyAppWeb.Plugs.ContentNegotiation do
import Plug.Conn
def init(opts), do: opts
def call(conn, _opts) do
conn
|> put_resp_header("vary", "accept")
|> assign(:prefer_markdown, prefers_markdown?(get_req_header(conn, "accept")))
end
# Markdown wins only when it has the highest q-value.
# A browser that sends */* keeps getting HTML.
defp prefers_markdown?(accept_headers) do
preferred =
accept_headers
|> Enum.flat_map(&String.split(&1, ","))
|> Enum.map(&parse_media_range/1)
|> Enum.max_by(fn {_type, q} -> q end, fn -> {"*/*", 1.0} end)
match?({"text/markdown", q} when q > 0, preferred)
end
defp parse_media_range(range) do
[type | params] = range |> String.split(";") |> Enum.map(&String.trim/1)
q =
Enum.find_value(params, 1.0, fn
"q=" <> value ->
case Float.parse(value) do
{q, _rest} -> q
:error -> 0.0
end
_param ->
nil
end)
{String.downcase(type), q}
end
end
// List text/html first: for Accept: */* Express picks the first type,
// so browsers and plain curl keep getting HTML.
function contentNegotiation(req, res, next) {
res.vary('Accept');
req.prefersMarkdown = req.accepts(['text/html', 'text/markdown'])
=== 'text/markdown';
next();
}
app.get('/docs/:slug', contentNegotiation, (req, res) => {
if (req.prefersMarkdown) {
res.type('text/markdown').send(getMarkdownContent(req.params.slug));
} else {
res.render('docs', { slug: req.params.slug });
}
});
Stap 2: Schone Markdown Serveren
Strip alles wat geen content is: navigatie, headers, footers, JavaScript, trackingpixels, cookiebanners. Wat overblijft moet dezelfde content zijn die op de gerenderde pagina verschijnt, maar als schone markdown met een correcte koppenstructuur.
- Wel opnemen: koppen, alinea's, codeblokken, links, lijsten, afbeeldingen met alt-tekst, tabellen
- Niet opnemen: navigatie-HTML, script-tags, style-blokken, trackingpixels, UI-framework markup
-
Wel instellen:
Content-Type: text/markdownenVary: Acceptheaders
De
Vary: Accept
header vertelt caches en CDN's dat de response afhangt van de Accept-header. Zonder deze header kan een cache een gecachte markdown-response aan een browser serveren.
Test beide representaties met curl. Het eerste verzoek moet
Content-Type: text/markdown
teruggeven, het tweede HTML, en beide moeten
Vary: Accept
bevatten:
curl -sI -H "Accept: text/markdown" https://docs.example.com/docs/getting-started
curl -sI https://docs.example.com/docs/getting-started
Stap 3: Belangrijke Informatie Vooraan Plaatsen
Agents lezen sequentieel en kunnen lange content afkappen, dus zet de belangrijkste informatie vooraan:
- Begin met een duidelijke titel en samenvatting van één alinea
- Zet installatie-/snelstartinstructies bovenaan
- Verplaats vereisten, achtergrondcontext en changelog naar onderaan
- Gebruik beschrijvende koppen die logisch zijn zonder de onderliggende content te lezen
Voorbij Developer Docs
Content negotiation begon bij developerdocumentatie, maar dezelfde aanpak past ook op andere contentrijke websites. Enkele voorbeelden:
| Websitetype | Wat als Markdown Serveren | Agent Use Case |
|---|---|---|
| Developer docs | API-referenties, handleidingen, tutorials | Coding agents die SDK-gebruiksvoorbeelden ophalen |
| E-commerce | Productspecificaties, vergelijkingen, reviews | Shopping agents die producten vergelijken voor gebruikers |
| SaaS helpcenters | Supportartikelen, FAQ's, installatiehandleidingen | Klantenservice-agents die vragen beantwoorden |
| Nieuws/media | Artikelcontent, gestructureerde data | Research agents die informatie verzamelen |
| Overheid/juridisch | Regelgeving, formulieren, procedures | Compliance agents die vereisten controleren |
Naarmate AI agents ook browsen, winkelen en onderzoek doen, ontvangen meer websites agent-verzoeken. Die sites kiezen of ze de content als markdown of als volledige HTML serveren.
Hoe Dit Past in AI Agent Readiness
Content negotiation is één onderdeel van agent readiness. Het werkt samen met de andere signalen waar agents naar zoeken:
llms.txt
llms.txt wijst agents naar de pagina's die het belangrijkst zijn. Content negotiation bepaalt hoe die pagina's worden geserveerd. Samen geven ze agents een kort pad naar je beste content.
Gestructureerde Data
JSON-LD en Schema.org geven agents context over je content: wat het is, wie het schreef en wanneer het is bijgewerkt. Markdown geeft ze de tekst zelf.
robots.txt & Crawler-toegang
Agents hebben toestemming nodig om je content op te halen. Een open robots.txt laat ze de content ophalen, en content negotiation laat ze die lezen met minder tokens.
Agent-protocollen
WebMCP, MCP en A2A laten agents acties uitvoeren. Content negotiation laat ze lezen.
De Conclusie
David Cramer's post beschrijft agent-optimalisatie met een bestaand middel: content negotiation, een 25 jaar oude HTTP-standaard, toegepast op agent-verzoeken.
Detecteer Accept: text/markdown, stuur schone markdown terug en zet je belangrijkste content vooraan. Verwijs agents bij beveiligde pagina's door naar API's en CLI's in plaats van naar inlogschermen. Bied voor discovery een gecureerd startpunt via
llms.txt
.
Sentry, Vercel en Cloudflare bouwen voor agents met standaarden die al bestaan. De belangrijkste drempel is dat weinig teams het mechanisme kennen.
Bronnen
- David Cramer: Optimizing Content for Agents (het originele artikel over Sentry's content negotiation-aanpak)
- RFC 9110: HTTP Semantics, Content Negotiation (de HTTP-specificatie voor content negotiation)
- How Vercel Built AEO Tracking for Coding Agents (Vercel's aanpak voor het meten van agent-verkeer)
- Cloudflare: Introducing Markdown for Agents (content negotiation en markdown-transformatie op platformniveau)
- IsAgentReady: AI-Crawlers Negeren llms.txt, Maar AI-Agents Niet (waarom llms.txt ertoe doet voor agents, niet voor crawlers)
- Checkly: The Current State of Content Negotiation for AI Agents (onderzoek naar welke coding agents Accept: text/markdown headers sturen)
- Cloudflare: Introducing Markdown for Agents (benchmark die 80% tokenreductie toont, van 16.180 HTML-tokens naar 3.150 markdown)
- llms.txt Specificatie (het originele voorstel van Jeremy Howard)