
# Markdown para agentes: servir Accept: text/markdown

Um agente pede a tua página e recebe HTML. Depois deita fora quase tudo: o menu, o rodapé, o aviso de cookies, os scripts, os atributos de classe, os ícones SVG. Fica com alguns parágrafos de texto.

A versão que ele queria já a tens. Quase ninguém a serve.

## O que custa a marcação

Compara o que envias com o que sobrevive:

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

Se os dois números forem iguais, serves uma única representação a toda a gente e é o agente que faz a limpeza. Esse trabalho não é grátis. Tudo o que está dentro do `<head>`, cada `<div>` de embrulho, cada atributo `data-` e cada excerto de analítica entra na janela de contexto antes de alguma coisa decidir que era ruído. Numa página cujo conteúdo real é um título e oito parágrafos, a maior parte dos bytes é andaime.

O gémeo em Markdown mantém os níveis de título, as ligações, as listas, as tabelas e os blocos de código. Perde navegação, estilo e scripts, dos quais nada iria alguma vez ser citado.

## Como funciona a negociação com Accept

O cliente diz o que consegue usar:

```
GET /about HTTP/1.1
Host: exemplo.com
Accept: text/markdown
```

O servidor escolhe uma representação para o mesmo URL:

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

Um navegador envia `Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8` e recebe HTML. Um cliente que peça `text/markdown` recebe Markdown. O URL canónico não muda, por isso continua a haver um só endereço para ligar e uma só página para partilhar.

## Vary: Accept, ou como um navegador acaba a descarregar um ficheiro de texto

O `Vary` não é opcional e é justamente a parte que as pessoas saltam.

Cada cache entre ti e quem lê (o teu CDN, um proxy inverso, o armazenamento do próprio navegador) indexa as respostas por URL. Se serves dois corpos diferentes num mesmo URL sem avisar, a primeira resposta guardada vale para todos. Um agente pede `/about` com `Accept: text/markdown`, o teu CDN guarda o Markdown, e a próxima pessoa que abrir `/about` recebe uma página de asteriscos ou uma janela de descarga.

```
Vary: Accept
```

Essa linha diz à cache para incluir o cabeçalho `Accept` na sua chave, de modo que HTML e Markdown fiquem guardados em separado. Envia-a nas **duas** respostas, não só na do Markdown.

Tem um custo real: os cabeçalhos `Accept` variam muito entre clientes, por isso variar por eles fragmenta a cache. É um argumento honesto a favor da alternativa que se segue.

## O gémeo .md

A opção mais simples é um segundo URL. `/about` serve HTML e `/about.md` serve o mesmo conteúdo em Markdown. Sem negociação, sem `Vary`, sem nada que possa correr mal numa cache. É um URL vulgar, portanto pode ser ligado, guardado nos favoritos, posto no sitemap e descarregado por qualquer cliente, incluindo um que não envie nenhum cabeçalho `Accept` aproveitável.

Depois diz que existe. No HTML:

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

E nos cabeçalhos da resposta, para o que faz um `HEAD` e nunca analisa o corpo:

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

Fazer as duas coisas custa uma linha cada e cobre os clientes que só olham para um sítio.

## Verifica o teu

```bash
# 1. O mesmo URL responde de forma diferente?
curl -s -H "Accept: text/markdown" https://exemplo.com/about | head -20

# 2. A resposta HTML admite que o gémeo existe?
curl -sI https://exemplo.com/about | grep -i "vary\|link"

# 3. O URL .md funciona por si só?
curl -sI https://exemplo.com/about.md | grep -i "content-type\|vary"
```

O segundo comando é o que apanha a falha habitual. Um site pode ter um gémeo `.md` impecável que ninguém vai encontrar, porque nenhum cabeçalho e nenhuma etiqueta apontam para ele.

## O que fazemos por cá

Todas as páginas deste site têm um gémeo em Markdown, e `packages/web/src/lib/content-negotiation.js` é tudo isso: cerca de noventa linhas.

Um mapa fixo lista os caminhos estáticos e os seus gémeos: `/` → `/index.md`, `/about` → `/about.md`, cada página de ferramenta e por aí fora. Os caminhos que levam um identificador ou um slug (os relatórios em `/r/<uuid>`, os guias, os artigos de blogue como este) são reconhecidos por padrão e recebem `<caminho>.md`.

A verificação do pedido é grosseira de propósito: se o cabeçalho `Accept` contiver a cadeia `text/markdown`, envia-se Markdown. Sem ordenação por valores de `q`. Um navegador nunca envia essa cadeia, por isso na prática separa bem os dois casos, mas um cliente que liste `text/markdown` com prioridade baixa recebe Markdown à mesma.

Cada resposta em Markdown sai com isto:

```
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
```

O `Content-Signal` diz o que se pode fazer com o conteúdo, e não apenas se pode ser descarregado. O `X-Markdown-Tokens` é uma marca de tamanho: hoje leva a contagem de caracteres do corpo, não uma contagem real de tokens.

As respostas HTML de uma página com gémeo levam `Vary: Accept` e o cabeçalho `Link`, e o `<head>` recebe a etiqueta `rel="alternate"` tirada do mesmo mapa.

Este último pormenor mordeu-nos. O mapa alimentava o template, mas as rotas reconhecidas por padrão não estavam no mapa, por isso cada relatório de análise servia o seu gémeo em Markdown e anunciava-o no cabeçalho `Link`, enquanto o seu HTML nada dizia. O gémeo existia e era invisível para tudo o que lesse a marcação.

## É uma convenção, não uma norma

`Accept: text/markdown` é negociação de conteúdo HTTP do costume, e isso é uma norma. Usá-la para Markdown é uma convenção que nasceu da proposta do llms.txt, e nenhum rastreador é obrigado a pedir. A posição honesta é que o gémeo `.md` é a parte que funciona de certeza, porque é um URL como outro qualquer e qualquer coisa o descarrega, enquanto a negociação custa um cabeçalho e compensa com os clientes que perguntam. Nenhuma das duas te vai fazer mal, e para saber qual está a ser usada lêem-se os registos, não os anúncios.

[Testa a tua negociação de Markdown](/pt/tools/markdown-tester) · [Gera o teu llms.txt](/pt/tools/llms-txt-generator)
