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.

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, masContent-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ínio | Content-Type retornado | Tamanho |
|---|---|---|
| basehub.com | text/html | 321.780 bytes |
| poe.com | text/html | 87.920 bytes |
| windsurf.com | text/html | 67.028 bytes |
| layercode.com | text/html (redirect) | 473.148 bytes |
| codeium.com | text/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 homejulius.ai— 404 servindo 58KB da SPAsourcegraph.com— 404 em 10KB de HTMLreworkd.ai— 404 nowww.reworkd.ai/llms.txtdepois do redirectgrit.io— redireciona paradocs.grit.io/llms.txte 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) — 321KBpoe.com(HTML) — 87KBwindsurf.com(HTML) — 67KBmodal.com— 26KBbaseten.co— 24KBcursor.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:
| Grupo | Domínios | Ref. .md |
|---|---|---|
| Zero (8) | trigger.dev, wisprflow.ai, cactuscompute.com, supermemory.ai, onlook.com, val.town, morphik.ai, warp.dev | 0 |
| 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:
curl -Isemanal no/llms.txt— status 200 eContent-Type: text/plain- Parser em CI — quebra o build se algum link for malformado
- Contagem de links
.md— se está em zero, você está entregando HTML pro crawler - Tamanho abaixo de 10KB no raiz — se passar, divida em
llms.txtpor produto - Alerta se
.mdversionado sumir — o.mdsome 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
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 → Este artigo foi útil?