¿Por qué los agentes de IA necesitan una ruta distinta por tu app?
Una parte creciente de las solicitudes a tu aplicación proviene de agentes de IA: asistentes que recuperan documentación para un usuario, herramientas de investigación que leen páginas de producto, flujos autónomos que llaman a tu API. La mayoría trabaja sobre interfaces diseñadas para personas. Descargan páginas HTML completas, analizan maquetaciones, siguen una navegación pensada para el ratón y reintentan cuando una página con mucho script no se renderiza como esperan.
Eso es ineficiente para todos. Los agentes reciben contenido ruidoso y cometen errores. Tus servidores gastan recursos renderizando páginas que nadie mira. Y el tráfico es difícil de interpretar, porque parece un navegador que se comporta de forma extraña. Si todavía no tienes claro cuánto de tu tráfico es esto, empieza con cómo saber si el tráfico del sitio web proviene de agentes de IA.
Un enfoque mejor es dar a los agentes una ruta estructurada: contenido y acciones en formatos pensados para programas, detectables en lugares estándar, con límites que premian a los clientes que se identifican correctamente. Esta guía muestra cómo hacerlo sin construir una segunda aplicación.
Paso 1: Decide qué deberían poder hacer los agentes
Empieza por la intención, no por la tecnología. Mira las rutas donde ya ves tráfico de agentes y agrúpalas:
- Leer contenido: documentación, información de producto, páginas de precios, artículos de ayuda, perfiles públicos.
- Consultar datos: búsqueda, consultas de catálogo, disponibilidad, estado.
- Realizar acciones: crear, actualizar o eliminar algo en nombre de un usuario.
Leer y consultar son buenos candidatos para una ruta estructurada abierta a cualquier cliente que se comporte bien. Las acciones necesitan autenticación y autorización independientemente de cómo se identifique el cliente, y se tratan en la guía sobre cómo proteger acciones sensibles.
Paso 2: Ofrece formatos aptos para máquinas
Para rutas de contenido, ofrece la misma información sin el chrome de la página. Dos formatos cubren la mayoría de las necesidades:
- Markdown para contenido narrativo como documentación y artículos, servido con el tipo de medio
text/markdownregistrado en RFC 7763. Conserva encabezados, listas, enlaces y bloques de código, y es compacto. - JSON para registros estructurados como productos, planes o estado.
Usa negociación de contenido para que la URL siga siendo la misma y el cliente pida el formato que quiere:
import express from "express";
const app = express();
app.get("/docs/:slug", async (req, res) => {
const doc = await loadDoc(req.params.slug);
if (!doc) return res.status(404).end();
res.vary("Accept");
const preferred = req.accepts(["text/html", "text/markdown", "application/json"]);
if (preferred === "text/markdown") {
return res.type("text/markdown; charset=utf-8").send(doc.markdown);
}
if (preferred === "application/json") {
return res.json({ title: doc.title, updatedAt: doc.updatedAt, body: doc.markdown });
}
return res.render("doc", { doc });
});Envía un encabezado Vary: Accept (RFC 9110 sobre Vary) para que las cachés almacenen cada representación por separado. Muchos equipos también exponen una URL alternativa explícita, como añadir .md a una ruta de documentación, porque para algunos clientes eso resulta más fácil que la negociación. Enlázalo desde la página HTML con <link rel="alternate" type="text/markdown" href="..."> para que pueda descubrirse. Los enlaces tipados como este siguen el modelo de Web Linking.
Paso 3: ¿Cómo descubren los agentes tu ruta estructurada?
Los agentes no pueden usar lo que no encuentran. Publica puntos de entrada en los lugares donde ya miran los clientes automatizados:
/llms.txten la raíz del sitio: un breve resumen en Markdown de lo que ofrece tu sitio con enlaces a las páginas más útiles y a sus versiones estructuradas, siguiendo la propuesta llms.txt.- Una descripción de API como un documento OpenAPI, enlazado desde tu documentación para desarrolladores y desde
/llms.txt. - Enlaces alternativos en páginas HTML que apunten a versiones en Markdown o JSON.
- Un sitemap que enumere las URLs canónicas de tu contenido, en el formato definido por el protocolo Sitemaps.
Un llms.txt mínimo:
# Example App
> Example App helps teams plan projects. This file lists the best entry points for automated clients.
## Docs
- [Getting started](https://example.com/docs/getting-started.md): setup in five steps
- [API reference](https://example.com/openapi.json): OpenAPI description of the public API
## Policies
- [Automated access](https://example.com/docs/automated-access.md): limits and how to sign requestsMantén una página que explique tus reglas para clientes automatizados: qué rutas están abiertas, qué límites aplican y cómo puede identificarse un cliente con solicitudes firmadas para recibir un trato mejor. Las reglas claras convierten la improvisación en cooperación.
Paso 4: Enruta por clase de actor, no por la cadena del user agent
Una vez que tengas respuestas estructuradas, decide quién las recibe por defecto. Usa la clase de actor y su base en lugar de analizar cadenas de user agent de forma ad hoc. Los operadores de IA sí publican sus user agents, como hacen OpenAI y Anthropic para sus crawlers y fetchers, pero una coincidencia de cadena sigue siendo solo una declaración.
type ActorClass = "human" | "human_ai" | "agent" | "unknown";
type Basis = "verified" | "declared" | "inferred" | "unknown";
function preferStructured(actor: ActorClass, basis: Basis, accept: string): boolean {
if (accept.includes("text/markdown") || accept.includes("application/json")) return true;
return actor === "agent" && (basis === "verified" || basis === "declared");
}Dos principios mantienen esto bajo control:
- Las solicitudes explícitas siempre ganan. Si un cliente pide Markdown o JSON, entrégalo, sea cual sea la clase.
- Los valores por defecto nunca quitan nada. Un visitante Human o Unknown siempre recibe la página completa. Elegir un valor por defecto estructurado para los agentes cambia el formato, no lo que se les permite ver.
Paso 5: ¿Qué límites de velocidad deberían tener los agentes de IA?
Los límites de velocidad son donde el contexto del actor aporta más valor de forma visible. En lugar de un límite para todos, da a cada combinación de clase y base un presupuesto razonable:
| Actor y base | Rutas de lectura | Notas |
|---|---|---|
| Agent, Verified | Límite más alto | El operador es identificable y responsable |
| Agent, Declared o Inferred | Límite estándar | Las afirmaciones no se pueden comprobar |
| Unknown | Límite estándar | Nunca punitivo por defecto |
| Human o Human + AI | Límite estándar | El uso interactivo rara vez se acerca a los límites |
Vincula el límite al identificador más estable disponible. Para agentes verificados, ese es el origen del operador y el identificador de clave. Para los demás, usa la credencial o una clave a nivel de red.
function limitKey(actor: { actor: ActorClass; basis: Basis; operator?: string }, ip: string, apiKey?: string) {
if (actor.actor === "agent" && actor.basis === "verified" && actor.operator) return `op:${actor.operator}`;
if (apiKey) return `key:${apiKey}`;
return `ip:${ip}`;
}
function limitFor(actor: { actor: ActorClass; basis: Basis }): number {
if (actor.actor === "agent" && actor.basis === "verified") return 600;
return 120;
}Los números son marcadores de posición. Define los tuyos a partir de la línea base que observaste. Cuando un cliente supera un límite, devuelve 429 Too Many Requests con un encabezado Retry-After y un enlace a tu página de acceso automatizado. Los agentes bien diseñados reducen el ritmo y lo leen.
Paso 6: Mantén las acciones detrás de la autorización
Una ruta estructurada para lectura no es una ruta para sortear tu modelo de seguridad. Cualquier acción que cambie datos sigue requiriendo:
- autenticación con una credencial emitida por tu aplicación,
- autorización para esa acción específica, y
- las comprobaciones adicionales que exija el nivel de riesgo de la ruta.
Una firma verificada te dice qué cliente está llamando. No te dice que el cliente pueda actuar en nombre de un usuario concreto. Mantén esas preguntas separadas. Nuestra publicación sobre qué prueban las solicitudes firmadas de agentes de IA explica la diferencia.
Paso 7: Mide el efecto
Ejecuta la ruta estructurada primero en modo de observación y luego compara:
- la proporción de solicitudes de agentes que usan formatos estructurados,
- el coste y la latencia del servidor para el tráfico de agentes antes y después,
- las tasas de error y reintento de los clientes agentes,
- cuántos clientes automatizados pasan de declared a verified una vez que publicas tus directrices de firma.
Estos números muestran si la ruta estructurada cumple su función y dónde ampliarla después.
Paso 8: Versiona y documenta la ruta estructurada
Trata la ruta estructurada como una interfaz pública, porque los agentes construirán sobre ella. Unos pocos hábitos la mantienen fiable:
- Mantén estables las URLs. Si un agente aprendió que
/docs/getting-started.mdexiste, debería seguir funcionando. Cuando el contenido se mueva, devuelve una301a la nueva ubicación en lugar de una404. - Incluye horas de actualización. Coloca un campo
updatedAten las respuestas JSON y un encabezadoLast-Modifieden Markdown, para que los agentes puedan cachear con sentido y actualizar solo cuando algo cambie. - Soporta solicitudes condicionales. Responde a
If-None-MatchyIf-Modified-Sincecon304 Not Modified. Los agentes que consultan periódicamente tu contenido cuestan mucho menos cuando pueden revalidar en lugar de descargarlo todo otra vez. - Versiona los cambios incompatibles. Si una forma JSON debe cambiar, añade una nueva ruta de versión o un nuevo tipo de medio y conserva la anterior durante un periodo publicado.
- Publica un changelog para la página de acceso automatizado. Los operadores de agentes bien comportados lo leen, y te da un lugar para anunciar nuevas rutas estructuradas.
app.get("/api/plans", async (req, res) => {
const plans = await loadPlans();
const etag = `"${plans.version}"`;
res.set("ETag", etag);
res.set("Cache-Control", "public, max-age=300");
if (req.get("if-none-match") === etag) return res.status(304).end();
return res.json({ updatedAt: plans.updatedAt, plans: plans.items });
});Estas prácticas también benefician a tu propio frontend y a las integraciones con partners. Una ruta estructurada que sea estable, cacheable y documentada se convierte rápidamente en la forma más sencilla para que cualquier programa trabaje con tu aplicación.
Errores comunes
- Servir hechos distintos a agentes y personas. La versión estructurada debe contener la misma información que la página. El contenido divergente confunde a los usuarios que preguntan a un asistente sobre tu producto.
- Ocultar la ruta estructurada. Si no está enlazada desde
/llms.txt, tus docs de API o las propias páginas, los agentes seguirán raspando HTML. - Premiar las declaraciones. Los límites más altos pertenecen a clientes verificados. Una cadena de user agent copiada no debería obtener un presupuesto mayor.
- Olvidar las cachés. Sin
Vary: Accept, una caché puede servir Markdown a un navegador.
Dónde encaja Proof of Actor
Proof of Actor te da la clase de actor y la base que necesitas para enrutar agentes a contenido estructurado y fijar límites justos. Detecta agentes firmados, declarados e inferidos, te ayuda a entender cómo usan tus rutas y deja la decisión de enrutamiento en tu código.
Para diseñar una ruta estructurada para tu propia aplicación con nuestro equipo, solicita acceso anticipado. Para escenarios de API y MCP específicamente, consulta APIs y MCP Servers, y lee quién está llamando a tu MCP server? para ver cómo se aplica el contexto del actor a llamadas de herramientas de Model Context Protocol.
Fuentes
- RFC 9110: HTTP Semantics: negociación de contenido (Sección 12),
Vary(Sección 12.5.5), solicitudes condicionales (Sección 13) yRetry-After(Sección 10.2.3) - RFC 7763: The text/markdown Media Type: servir representaciones Markdown
- RFC 8288: Web Linking: enlaces
alternatetipados - RFC 6585: Additional HTTP Status Codes, Section 4:
429 Too Many Requests - propuesta llms.txt: el formato de archivo
/llms.txt - OpenAPI Specification: descripciones de API legibles por máquinas
- Sitemaps protocol: formato de archivo sitemap
- OpenAI: Overview of OpenAI Crawlers: user agents y rangos de IP publicados por OpenAI
- Anthropic: crawler and fetcher documentation: ClaudeBot, Claude-User y Claude-SearchBot
- Model Context Protocol specification (2026-07-28): la revisión actual de MCP a noviembre de 2026