
# Markdown für Agenten: Accept: text/markdown ausliefern

Ein Agent fragt Ihre Seite an und bekommt HTML. Dann wirft er das meiste davon weg: Navigation, Fußzeile, Cookie-Banner, Inline-Skripte, Klassenattribute, SVG-Symbole. Übrig bleiben ein paar Absätze Text.

Die Version, die er wollte, haben Sie längst. Fast niemand liefert sie aus.

## Was das Markup kostet

Vergleichen Sie, was Sie senden, mit dem, was übrig bleibt:

```bash
curl -s https://beispiel.de/about | wc -c
curl -s -H "Accept: text/markdown" https://beispiel.de/about | wc -c
```

Sind beide Zahlen gleich, liefern Sie allen dieselbe Repräsentation aus und das Aufräumen erledigt der Agent. Diese Arbeit ist nicht umsonst. Alles im `<head>`, jedes umschließende `<div>`, jedes `data-`-Attribut und jedes Analytics-Snippet landet im Kontextfenster, bevor irgendetwas entscheidet, dass es Rauschen war. Auf einer Seite, deren eigentlicher Inhalt eine Überschrift und acht Absätze sind, ist der größte Teil der Bytes Gerüst.

Der Markdown-Zwilling behält Überschriftenebenen, Links, Listen, Tabellen und Codeblöcke. Er verliert Navigation, Gestaltung und Skripte, und davon wäre ohnehin nie etwas zitiert worden.

## Wie die Aushandlung über Accept funktioniert

Der Client sagt, was er verwerten kann:

```
GET /about HTTP/1.1
Host: beispiel.de
Accept: text/markdown
```

Der Server wählt für dieselbe URL eine Repräsentation:

```
HTTP/1.1 200 OK
Content-Type: text/markdown; charset=utf-8
Vary: Accept
```

Ein Browser sendet `Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8` und bekommt HTML. Ein Client, der `text/markdown` verlangt, bekommt Markdown. Die kanonische URL bleibt dieselbe, es gibt also weiterhin nur eine Adresse zum Verlinken und eine Seite zum Teilen.

## Vary: Accept, oder wie ein Browser eine Textdatei herunterlädt

`Vary` ist nicht optional, und genau diesen Teil lassen die meisten weg.

Jeder Cache zwischen Ihnen und dem Leser (Ihr CDN, ein Reverse Proxy, der Browser-Cache selbst) schlüsselt Antworten nach URL. Liefern Sie zwei verschiedene Rümpfe unter einer URL aus, ohne das anzukündigen, gilt die zuerst gecachte Antwort für alle. Ein Agent fragt `/about` mit `Accept: text/markdown` an, Ihr CDN legt das Markdown ab, und der nächste Mensch, der `/about` öffnet, sieht eine Seite voller Sternchen oder einen Download-Dialog.

```
Vary: Accept
```

Diese Zeile weist den Cache an, den `Accept`-Header in den Schlüssel aufzunehmen, sodass HTML und Markdown getrennt gespeichert werden. Senden Sie sie in **beiden** Antworten, nicht nur in der Markdown-Antwort.

Das hat einen realen Preis: `Accept`-Header unterscheiden sich stark zwischen Clients, eine Variation darüber zersplittert also Ihren Cache. Das ist ein ehrliches Argument für die folgende Alternative.

## Der .md-Zwilling

Die einfachere Variante ist eine zweite URL. `/about` liefert HTML, `/about.md` liefert denselben Inhalt als Markdown. Keine Aushandlung, kein `Vary`, nichts, was in einem Cache schiefgehen kann. Es ist eine ganz normale URL, also verlinkbar, als Lesezeichen speicherbar, in die Sitemap eintragbar und von jedem Client abrufbar, auch von einem, der überhaupt keinen brauchbaren `Accept`-Header schickt.

Sagen Sie dann, dass es sie gibt. Im HTML:

```html
<link rel="alternate" type="text/markdown" href="https://beispiel.de/about.md">
```

Und in den Antwort-Headern, für alles, was ein `HEAD` macht und den Rumpf nie parst:

```
Link: <https://beispiel.de/about.md>; rel="alternate"; type="text/markdown"
```

Beides zusammen kostet je eine Zeile und deckt die Clients ab, die nur an einer Stelle nachsehen.

## Prüfen Sie Ihre eigene Seite

```bash
# 1. Antwortet dieselbe URL unterschiedlich?
curl -s -H "Accept: text/markdown" https://beispiel.de/about | head -20

# 2. Gibt die HTML-Antwort zu, dass der Zwilling existiert?
curl -sI https://beispiel.de/about | grep -i "vary\|link"

# 3. Funktioniert die .md-URL für sich allein?
curl -sI https://beispiel.de/about.md | grep -i "content-type\|vary"
```

Der zweite Befehl fängt den üblichen Fehler ab. Eine Seite kann einen tadellosen `.md`-Zwilling haben, den nie jemand findet, weil kein Header und kein Tag darauf zeigt.

## Was wir hier tun

Jede Seite dieser Website hat einen Markdown-Zwilling, und `packages/web/src/lib/content-negotiation.js` ist das Ganze: rund neunzig Zeilen.

Eine feste Tabelle listet die statischen Pfade und ihre Zwillinge: `/` → `/index.md`, `/about` → `/about.md`, jede Tool-Seite und so weiter. Pfade mit einer ID oder einem Slug (Berichte unter `/r/<uuid>`, Leitfäden, Blogbeiträge wie dieser) werden stattdessen über ein Muster erkannt und bekommen `<pfad>.md`.

Die Prüfung der Anfrage ist absichtlich grob: Enthält der `Accept`-Header die Zeichenkette `text/markdown`, wird Markdown gesendet. Keine Gewichtung nach `q`-Werten. Ein Browser sendet diese Zeichenkette nie, in der Praxis trennt das die beiden Fälle also sauber, aber ein Client, der `text/markdown` mit niedriger Priorität aufführt, bekommt trotzdem Markdown.

Jede Markdown-Antwort geht mit diesen Headern hinaus:

```
Content-Type: text/markdown; charset=utf-8
Content-Signal: search=yes, ai-input=yes, ai-train=no
Vary: Accept
X-Markdown-Tokens: 4213
Cache-Control: public, max-age=3600
```

`Content-Signal` sagt, was mit dem Inhalt geschehen darf, und nicht nur, ob er abgerufen werden darf. `X-Markdown-Tokens` ist eine Größenangabe: Sie trägt heute die Zeichenzahl des Rumpfs, keine echte Token-Zahl.

HTML-Antworten einer Seite mit Zwilling bekommen `Vary: Accept` und den `Link`-Header, und in den `<head>` kommt das `rel="alternate"`-Tag aus derselben Tabelle.

Dieses letzte Detail hat uns gebissen. Die Tabelle speiste das Template, aber die über Muster erkannten Routen standen nicht in der Tabelle. Jeder Analysebericht lieferte also seinen Markdown-Zwilling aus und kündigte ihn im `Link`-Header an, während sein HTML nichts davon sagte. Der Zwilling existierte und war für alles unsichtbar, was das Markup las.

## Eine Konvention, kein Standard

`Accept: text/markdown` ist gewöhnliche HTTP-Content-Negotiation, und die ist ein Standard. Sie für Markdown zu nutzen, ist eine Konvention, die aus dem llms.txt-Vorschlag entstanden ist, und kein Crawler ist verpflichtet, danach zu fragen. Ehrlich gesagt ist der `.md`-Zwilling der Teil, der verlässlich funktioniert, weil er eine URL wie jede andere ist und alles ihn abrufen kann, während die Aushandlung einen Header kostet und sich bei den Clients auszahlt, die tatsächlich fragen. Schaden wird Ihnen keins von beidem, und was genutzt wird, erfahren Sie aus Ihren Logs, nicht aus Ankündigungen.

[Testen Sie Ihre Markdown-Aushandlung](/de/tools/markdown-tester) · [Erzeugen Sie Ihre llms.txt](/de/tools/llms-txt-generator)
