← Voltar ao Blog

Auditei 30 llms.txt em 2026: 5 anti-padrões

Cinco meses atrás auditei 30 arquivos llms.txt de infra clássica — Anthropic, Stripe, Vercel, Cloudflare — e concluí que a maioria estava quebrada. Tudo bem, pensei. Aquele grupo era gente grande, com Confluence e comitê. Ninguém estaria vigiando o llms.txt.

Aí abri o terminal em 30 startups de IA que apareceram nas últimas batches: Firecrawl, Trigger.dev, Cursor, Modal, Baseten, Braintrust, Warp, Cactus, Cedar, Wisprflow, e por aí. Startups que vendem produto para desenvolvedores de LLM. Se alguém deveria acertar llms.txt, seria essa gente.

Não acertaram.

Rodei curl em cada domínio na segunda de manhã. Anotei o HTTP status, o Content-Type, o tamanho, e depois li o conteúdo. 19 arquivos abriram como text/plain. 11 abriram como outra coisa. Cinco anti-padrões saltam da lista bruta. Todos eles descrevem comportamento observável no curl -o daquele dia, sem espaço para opinião.

Distribuição dos 30 llms.txt auditados em 2026

Como auditei

Escolhi 30 domínios com peso em ecossistema de IA em 2026 (mix de YC recentes e nomes estabelecidos como Cursor e Sourcegraph). Rodei:

curl -sL -A "Mozilla/5.0 (audit)" --max-time 12 \
  -o "$domain.txt" \
  -w "HTTP=%{http_code}|CT=%{content_type}|SIZE=%{size_download}" \
  "https://$domain/llms.txt"

O -L segue redirect. O -w grava o status e o Content-Type real. Isso muda tudo: eu não precisei confiar em nenhuma declaração da empresa sobre “o llms.txt que a gente publicou”. Confiei no que o servidor devolveu.

Resultado bruto de segunda-feira, sem interpretação:

  • 19 arquivos vieram como text/plain (variando de 448 bytes a 138.722 bytes)
  • 5 domínios devolveram HTML no path /llms.txt (200 OK, mas Content-Type: text/html)
  • 5 domínios devolveram 404
  • 1 domínio devolveu 403 com XML de “Access Denied”

Só uma manhã com o terminal aberto, sem pretensão de método. Mesmo assim, os padrões repetem tão rápido que parei nos 30.

Anti-padrão 1: HTML no lugar de text/plain

Cinco dos 30 sites devolveram uma página HTML no endereço /llms.txt. O servidor respondeu 200 OK, com o site inteiro renderizado.

DomínioContent-Type retornadoTamanho
basehub.comtext/html321.780 bytes
poe.comtext/html87.920 bytes
windsurf.comtext/html67.028 bytes
layercode.comtext/html (redirect)473.148 bytes
codeium.comtext/html (redirect)67.028 bytes

O caso mais estranho é o layercode.com: o /llms.txt redireciona para toyo.ai, um domínio de outra empresa. Presumo que a Layercode foi comprada ou renomeada. O codeium.com faz uma manobra parecida: redireciona para windsurf.com, que é o nome novo do produto. Os dois entregam a página inicial do site em vez de qualquer arquivo estruturado.

O comportamento do crawler nesse caso varia. O da OpenAI espera texto plano. Quando recebe HTML, alguns parsers extraem <title> e desistem; outros tentam entender o Next.js embaralhado. Nenhum lê aquilo como um llms.txt. É o 404 sem admitir que é 404.

Se você configurou uma URL /llms.txt no Next.js e ela cai no catch-all do App Router, o comportamento padrão é responder HTML. Verifique com curl -I o Content-Type real: o browser mascara isso porque renderiza qualquer coisa.

Anti-padrão 2: 404 silencioso (e um 403 educado)

Cinco domínios responderam 404 explícito:

  • continue.dev — 404 em HTML da própria home
  • julius.ai — 404 servindo 58KB da SPA
  • sourcegraph.com — 404 em 10KB de HTML
  • reworkd.ai — 404 no www.reworkd.ai/llms.txt depois do redirect
  • grit.io — redireciona para docs.grit.io/llms.txt e 404 lá

E um sexto que merece nota separada: cedarcopilot.com devolveu 403 com um XML curtíssimo da AWS S3: <Error><Code>AccessDenied</Code>.... Ou seja, existe uma configuração de bucket que bloqueia leituras não autenticadas do /llms.txt. É a única coisa pior do que 404: 404 sinaliza “não temos”; 403 sinaliza “temos, mas é privado”. Nenhum dos dois casos é o que o crawler procura.

Seis domínios em 30 = 20% de “não temos, e nem sabemos que não temos”. Suspeito que a maioria já teve um llms.txt em algum momento (o SEO mensal recomendou), o arquivo migrou de pasta, e ninguém redirecionou. É o comportamento clássico do link quebrado dentro do próprio site.

A verificação leva quatro segundos:

curl -sI https://seusite.com/llms.txt | head -1
# HTTP/2 200  ← ok
# HTTP/2 404  ← problema

Coloque isso em cron uma vez por semana e você fica sabendo antes do crawler.

Anti-padrão 3: O despejo de 138KB

A spec original do Jeremy Howard recomenda arquivos pequenos que caibam no context window de um LLM sem consumir orçamento do prompt. A palavra “small” aparece na introdução da proposta.

cactuscompute.com respondeu 138.722 bytes. O arquivo traz a documentação inteira do produto Needle inline, com preços, instruções para agentes, especificações da API, tudo dentro do mesmo arquivo. Não há nenhum link - [Nome](url) no formato canônico: só cabeçalhos e prosa.

A escolha faz sentido dependendo do que você quer que o LLM faça. Se a intenção é “dar todo o contexto de uma vez”, 138KB entra em qualquer janela moderna. Mas o llms.txt foi desenhado como índice, e um despejo desse tamanho muda essa premissa. Você paga com tokens toda vez que o crawler abre o arquivo, mesmo quando a pergunta do usuário toca só um pedacinho.

Outros gigantes do meu recorte:

  • basehub.com (HTML) — 321KB
  • poe.com (HTML) — 87KB
  • windsurf.com (HTML) — 67KB
  • modal.com — 26KB
  • baseten.co — 24KB
  • cursor.com — 22KB

Os três primeiros são HTML e caem no anti-padrão 1. Os últimos três estão em texto plano e são grandes, mas usam a estrutura de índice com links .md, o que deixa o LLM baixar só o que precisa. O padrão da Cloudflare (mencionado na minha auditoria anterior) funciona aqui: um llms.txt raiz enxuto que aponta para llms.txt por produto.

Anti-padrão 4: URL concatenada com bug

Este só aparece com o arquivo aberto. Estava lendo o cursor.com/llms.txt (22KB, 367 referências .md, no geral bem organizado) quando bati na linha 22:

- https://cursor.comhttps://cursor.com/changelog.md

Sem espaço. Dois https://cursor.com colados. É um bug de template: o gerador do arquivo concatenou base_url + full_url em vez de base_url + path. Quem tentar seguir esse link cai em nada (o domínio cursor.comhttps não resolve).

Um único link quebrado num arquivo grande não deveria ser fatal, mas revela algo pior: ninguém executou parser algum sobre esse arquivo antes de publicar. Existe validador oficial (llms-txt-parser no NPM); existe curl | grep -oE 'https?://[^ ]+' | xargs -I{} curl -sI -o /dev/null -w "%{http_code} {}\n" {} para bater todos os links em 30 segundos.

Se você monta o llms.txt num CI, coloque essa checagem no mesmo job que gera o site. Custa 30 segundos e evita alucinações induzidas: o LLM vai ver a URL malformada e inventar uma correção que soa plausível, talvez https://cursor.com/changelog.md, talvez outra coisa. Nenhuma é confiável.

Anti-padrão 5: Zero gêmeo .md

A proposta original inclui uma convenção esperta: qualquer URL com .md adicionado deve retornar uma versão Markdown limpa da página, sem nav, sem ads, sem bundle de JavaScript. É o padrão que faz llms.txt funcionar de verdade: o LLM abre o .md e vê só conteúdo.

Contei as ocorrências da string .md em cada um dos 19 arquivos válidos:

GrupoDomíniosRef. .md
Zero (8)trigger.dev, wisprflow.ai, cactuscompute.com, supermemory.ai, onlook.com, val.town, morphik.ai, warp.dev0
1 a 6 (5)firecrawl.dev (1), motherduck.com (1), modelscope.cn (2), browserbase.com (2), baseten.co (6)1–6
10 ou mais (6)openrouter.ai (13), e2b.dev (17), greptile.com (54), braintrust.dev (65), modal.com (317), cursor.com (367)13–367

Oito arquivos válidos apontam para zero URL .md. Servem links HTML e esperam que o crawler execute JavaScript para renderizar. O crawler da OpenAI, em 2026, ainda não executa JavaScript direito na maioria dos casos.

O paper GEO de Aggarwal et al. (arXiv 2311.09735), publicado no SIGKDD 2024, mostrou que técnicas de otimização podem levar a até +115,1% de citação nas respostas geradas, mas só quando o modelo consegue extrair o conteúdo. Se o parser bate em HTML embaralhado e desiste, o efeito vai para zero. A convenção .md existe justamente para desbloquear esse ponto.

O padrão maior por trás dos cinco

Uma coisa que aprendi mexendo com llms.txt desde 2024 (e apanhando em produção): quase todo mundo publica o arquivo uma vez, cola no Slack “olha, fizemos LLMO”, e nunca mais volta. É o que a auditoria mostra. Dos 30 domínios de startups vendendo para desenvolvedores de LLM, um terço não passou no teste mais básico do curl -I.

Se você mantém um llms.txt, coloque no seu monitor:

  1. curl -I semanal no /llms.txt — status 200 e Content-Type: text/plain
  2. Parser em CI — quebra o build se algum link for malformado
  3. Contagem de links .md — se está em zero, você está entregando HTML pro crawler
  4. Tamanho abaixo de 10KB no raiz — se passar, divida em llms.txt por produto
  5. Alerta se .md versionado sumir — o .md some quando o build muda de path

O guia com esses critérios completos está em llmoframework.com, na seção Reference Templates. Uso a checklist mensal desde março e reduziu meus falsos-positivos de LLMO a um número que consigo contar nos dedos.

Vou refazer essa auditoria no primeiro trimestre de 2027. Aposto uma cerveja que o número de HTML servido em /llms.txt aumenta em vez de cair. Adoção está ganhando a corrida; qualidade continua perdendo.

ken imoto · WebRTC & Voice AI engineer · kenimoto.dev · TabNews

LLMO Quickstart Livro relacionado LLMO Quickstart tutorial LLMO | Otimização para Busca por IA em 30 minutos · llms.txt · JSON-LD caminho mais curto Ver a página do livro →