Seis ações práticas para servir leitores humanos e agentes de IA no mesmo site, com checklist para copiar
Nos últimos quatro dias, eu e o Claude Code transformamos o smarts.md de um site de documentação de contratos inteligentes feito para humanos em um feito para agentes de IA.
Soa como a mesma coisa. Não é. Um site para humanos otimiza legibilidade, busca e tempo de carregamento. Um site para agentes de IA tem que responder a perguntas diferentes:
robots.txt padrão está trancando a porta?Aqui estão as seis coisas que pedi ao Claude para construir. Cada uma é útil por si só e dá para levar para o seu próprio site separadamente.
robots.txtA maioria dos sites herda um robots.txt de algum template antigo que implicitamente bloqueia qualquer User-Agent desconhecido. Mas depois de 2025, muitos crawlers de IA são User-Agents novos — GPTBot, ClaudeBot, PerplexityBot, Applebot-Extended, Google-Extended, CCBot, meta-externalagent e outros. Para deixá-los entrar, precisa liberar explicitamente.
O robots.txt do smarts abre com uma nota de política e depois lista User-agent + Allow: / para 12 crawlers, cobrindo OpenAI, Anthropic, Perplexity, Google Gemini, Apple, Common Crawl, Meta e Cohere. A postura é direta: esse site existe para ser lido por IA.
llms.txt — um cardápio para LLMsllms.txt é uma convenção proposta pelo llmstxt.org: você coloca um Markdown conciso na raiz do site que diz ao LLM o que é esse site, como usá-lo e onde estão os pontos de entrada chave. É o pitch de elevador do seu site.
O llms.txt do smarts tem cerca de 60 linhas:
/{chain}/{address} vs slug curto)A ideia central: LLMs pagam em tokens pra ler sua documentação, então não vão crawlear o site inteiro. Entrega um índice destilado e a taxa de acerto sobe bastante.
.well-known/mcp.json — aposta antecipadaO protocolo MCP ainda não padronizou uma convenção de descoberta tipo /.well-known/openid-configuration. Hoje nenhum cliente público faz crawl de um caminho well-known fixo.
Mas publicar o manifesto custa 30 linhas:
def well_known_mcp
response.set_header("Cache-Control", "public, max-age=3600")
response.set_header("Access-Control-Allow-Origin", "*")
render json: {
name: "smarts",
version: "0.1.0",
description: "...",
protocol_version: "2024-11-05",
transports: [{ type: "sse", endpoint: "https://smarts.md/mcp/sse" }],
capabilities: { tools: true, resources: false, prompts: false },
tools: MCP_TOOLS.map { |t| { name: t[:name], description: t[:blurb] } }
}
end
No momento em que aparecer uma convenção de descoberta, eu não mudo uma linha. E é autodocumentação para desenvolvedores — quem quiser entender meu MCP pode só curl smarts.md/.well-known/mcp.json.
O pulo do gato: o array tools é derivado da constante MCP_TOOLS, fonte única de verdade. Um teste estrutural existente obriga que cada app/tools/*_tool.rb apareça nessa constante, então o manifesto herda a garantia de "nenhuma ferramenta nova é esquecida" de graça.
.md: destilação WebFetch-friendly para cada páginaEssa é minha favorita. A ferramenta WebFetch do Claude Code precisa limpar e extrair conteúdo de HTML arbitrário — isso custa token e é instável. E se você entregar .md direto?
O respond_to do Rails suporta isso nativamente:
# config/routes.rb
get ":slug(.:format)", to: "contracts#show",
constraints: { slug: ContractSlugs::ROUTE_PATTERN, format: /html|md/ }
https://smarts.md/usdc-eth devolve HTML; https://smarts.md/usdc-eth.md devolve 40 linhas de Markdown — endereço, cadeia, classificação, endpoint MCP, como consultar via agente de IA, links fonte.
# USD Coin on Ethereum
- **Address:** `0xa0b8...`
- **Chain:** Ethereum
- **Classification:** ERC-20 Token
## Query via AI agent
- **MCP endpoint:** `https://smarts.md/mcp/sse`
- **Reference:** `usdc-eth`
- **Sample prompt:** "Tell me the current state of usdc-eth"
Um fetch, todo o conteúdo estruturado que um agente de IA quer, sem parser de DOM. O Claude resolveu isso rápido — um controller, dois templates .md.erb, (.:format) nas rotas, pronto.
Essa é a descoberta inversa: parte dos meus visitantes já usa Claude Code / Cursor / Windsurf. Eles chegam numa página de contrato e o próximo pensamento costuma ser "deixa minha IA dar uma olhada nisso".
Então cada página de contrato renderiza um card com:
usdc-eth) ou chain/address, com botão de copiarmcp.smarts.md com o setup de uma linhaUm clique de atrito entre "estou olhando esse contrato" e "estou perguntando pra minha IA". O card usa um card do DaisyUI e um controller Stimulus copy genérico — 50 linhas de erb. Um teste de regressão trava os atributos data-copy-text-value para que um refactor futuro não cole silenciosamente a string errada na área de transferência dos usuários.
OpenGraph, Twitter Card, JSON-LD — a camada tradicional de busca e social card. Vale a pena, porque crawlers de IA também leem.
A escolha interessante é como o JSON-LD deveria descrever um contrato inteligente. O Claude optou por um WebPage envelopando uma SoftwareApplication:
{
"@type": "WebPage",
"about": {
"@type": "SoftwareApplication",
"name": "USD Coin",
"applicationCategory": "SmartContract",
"operatingSystem": "Ethereum",
"identifier": "0xa0b8..."
}
}
operatingSystem recebe o nome da cadeia, identifier recebe o endereço, additionalType recebe a classificação (por exemplo "Uniswap V3 Pool"). O schema.org não tem um tipo dedicado SmartContract, mas SoftwareApplication com esses campos é o suficiente pra um LLM entender "isso é um contrato na Ethereum com um endereço específico".
A imagem OG é um summary_large_image 1200×630; Twitter Card, breadcrumbs, softwareVersion e license completam o conjunto.
Os seis itens acima saíram de sete PRs em quatro dias:
| PR | Arquivos | Tamanho |
|---|---|---|
feat/ai-crawler-discovery |
2 | ~126 loc |
feat/well-known-mcp-manifest |
4 | ~129 loc |
feat/markdown-contract-pages |
6 | ~298 loc |
feat/contract-mcp-card |
3 | ~126 loc |
feat/seo-meta-tags |
8 | ~292 loc |
feat/seo-enrichments |
8 | ~189 loc |
feat/og-card |
— | — |
Cada um é um PR independente, com testes próprios e mensagem de commit própria. Essa cadência é a coisa mais valiosa em trabalhar com o Claude — cada PR é pequeno o bastante pra revisar o diff num relance, mas empilhados juntos o site cresceu uma superfície completa pra IA.
Se você tem um site tipo conteúdo e quer deixá-lo AI-friendly, faça nessa ordem:
robots.txt/llms.txt (um cardápio destilado).md às suas páginas de conteúdo principais/.well-known/mcp.jsonA maioria dos engenheiros de SEO não vai te contar os cinco primeiros — não estão no playbook tradicional. Mas olhando quatro dias de dados do meu lado, a curva de tráfego de IA e a curva de tráfego humano são duas séries completamente independentes. Você tem que servir as duas.