Sei mosse concrete per servire lettori umani e agenti AI dallo stesso sito, con checklist pronta da copiare
Negli ultimi quattro giorni io e Claude Code abbiamo trasformato smarts.md da sito di documentazione di smart contract pensato per esseri umani in un sito pensato per agenti AI.
Sembrano la stessa cosa. Non lo sono. Un sito per umani ottimizza leggibilità, ricerca e velocità di caricamento. Un sito per agenti AI deve rispondere a domande diverse:
robots.txt di default li chiude fuori?Ecco le sei cose che ho fatto costruire a Claude. Ognuna è utile da sola e puoi portarla nel tuo sito separatamente.
robots.txtLa maggior parte dei siti eredita un robots.txt da qualche vecchio template che implicitamente blocca qualunque User-Agent non riconosca. Ma dopo il 2025, molti crawler AI sono User-Agent nuovi — GPTBot, ClaudeBot, PerplexityBot, Applebot-Extended, Google-Extended, CCBot, meta-externalagent e altri. Se li vuoi dentro, devi autorizzarli esplicitamente.
Il robots.txt di smarts si apre con una nota di policy e poi elenca User-agent + Allow: / per 12 crawler che coprono OpenAI, Anthropic, Perplexity, Google Gemini, Apple, Common Crawl, Meta e Cohere. La posizione è netta: questo sito esiste per essere letto da AI.
llms.txt — un menù per gli LLMllms.txt è una convenzione proposta da llmstxt.org: metti un Markdown sintetico nella radice del sito che dice all'LLM cos'è questo sito, come si usa, dove sono i punti di ingresso chiave. È l'elevator pitch del tuo sito.
Il llms.txt di smarts fa circa 60 righe:
/{chain}/{address} vs slug corto)L'intuizione: gli LLM pagano in token per leggere la tua documentazione, quindi non fanno crawl dell'intero sito. Consegna loro un indice distillato e il tasso di successo schizza.
.well-known/mcp.json — scommettere in anticipoIl protocollo MCP non ha ancora una convenzione di discovery standardizzata tipo /.well-known/openid-configuration. Oggi nessun client pubblico fa crawl di un percorso well-known fisso.
Ma pubblicare il manifest costa 30 righe:
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
Nel momento in cui emerge una convenzione di discovery, non cambio una riga. E intanto è auto-documentazione per gli sviluppatori — chiunque curioso del mio MCP fa semplicemente curl smarts.md/.well-known/mcp.json.
Il trucco: l'array tools è derivato dalla costante MCP_TOOLS, single source of truth. Un test strutturale esistente forza ogni app/tools/*_tool.rb a comparire in quella costante, quindi il manifest eredita gratis la garanzia di "nessun tool nuovo dimenticato".
.md: distillazione WebFetch-friendly per ogni paginaLa mia preferita. Il tool WebFetch di Claude Code deve ripulire ed estrarre contenuto da HTML arbitrario — costoso in token e inaffidabile. E se gli servi direttamente .md?
Il respond_to di Rails lo supporta nativamente:
# config/routes.rb
get ":slug(.:format)", to: "contracts#show",
constraints: { slug: ContractSlugs::ROUTE_PATTERN, format: /html|md/ }
https://smarts.md/usdc-eth restituisce HTML; https://smarts.md/usdc-eth.md restituisce 40 righe di Markdown — indirizzo, chain, classificazione, endpoint MCP, come interrogare via agente AI, link sorgente.
# 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"
Un fetch, tutto il contenuto strutturato che un agente AI vuole, nessun parser DOM. Claude ha spedito questa parte in fretta — un controller, due template .md.erb, (.:format) nelle routes, fatto.
Scoperta in direzione opposta: una parte dei miei visitatori usa già Claude Code / Cursor / Windsurf. Arrivano su una pagina contratto e la mossa successiva è di solito "faccio dare un'occhiata alla mia AI".
Quindi ogni pagina contratto renderizza una card con:
usdc-eth) oppure chain/address, con pulsante Copiamcp.smarts.md (setup in una riga)Un click di attrito tra "sto guardando questo contratto" e "sto chiedendo alla mia AI". La card usa una card DaisyUI e un controller Stimulus copy generico — 50 righe di erb. Un test di regressione blocca gli attributi data-copy-text-value affinché un refactor futuro non incolli silenziosamente la stringa sbagliata negli appunti degli utenti.
OpenGraph, Twitter Card, JSON-LD — lo strato tradizionale di ricerca e social card. Vale la pena, perché anche i crawler AI leggono qui.
La scelta interessante è come JSON-LD debba descrivere uno smart contract. Claude ha optato per un WebPage che incapsula un SoftwareApplication:
{
"@type": "WebPage",
"about": {
"@type": "SoftwareApplication",
"name": "USD Coin",
"applicationCategory": "SmartContract",
"operatingSystem": "Ethereum",
"identifier": "0xa0b8..."
}
}
operatingSystem prende il nome della chain, identifier l'indirizzo, additionalType la classificazione (es. «Uniswap V3 Pool»). schema.org non ha un tipo dedicato SmartContract, ma SoftwareApplication con questi campi è sufficiente per far capire a un LLM "questo è un contratto su Ethereum con un indirizzo preciso".
L'immagine OG è un summary_large_image 1200×630; Twitter Card, breadcrumb, softwareVersion e license completano il quadro.
I sei punti sopra sono usciti da sette PR in quattro giorni:
| PR | File | Dimensione |
|---|---|---|
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 |
— | — |
Ognuno è un PR indipendente con test e commit message propri. Questa cadenza di taglio fine è la cosa più preziosa nel lavorare con Claude — ogni PR è abbastanza piccolo da recensirne il diff in un'occhiata, ma impilati insieme il sito è cresciuto in una superficie AI completa.
Se hai un sito di contenuti e vuoi renderlo AI-friendly, procedi in quest'ordine:
robots.txt/llms.txt (un menù distillato).md alle tue pagine di contenuto principali/.well-known/mcp.jsonI primi cinque non te li dice la maggior parte dei SEO engineer — non sono nel playbook classico. Ma con quattro giorni di dati dalla mia parte, la curva del traffico AI e quella del traffico umano sono due serie completamente indipendenti. Bisogna servire entrambe.