Los agentes de IA ya leen los errores de tu API
En marzo, Mintlify sumó un mes de tráfico a los sitios de documentación que aloja. Salieron unos 790 millones de peticiones, y el 45,3 % las hicieron agentes de programación con IA. Los navegadores hicieron el 45,8 %. Claude Code por sí solo envió una cuarta parte de todo (las cifras de Mintlify).
Es tráfico a documentación, no a APIs. Pero los agentes que leen la documentación son los mismos que luego escriben la petición, la ejecutan y leen lo que vuelva. En la encuesta State of the API 2025 de Postman, el 24 % de los desarrolladores dijo que ya diseña APIs pensando en agentes. Cuando salió parecía prematuro. Ya no.
Casi todo lo que construimos aquí trata de fallos: endpoints que devuelven 500, que se cuelgan o que se paran a mitad de una respuesta. Así que la pregunta que nos hacíamos era muy concreta. Cuando un agente recibe un error de tu API, ¿tiene lo suficiente para hacer lo correcto a continuación?
Un agente se toma tu mensaje de error al pie de la letra
Un desarrollador que recibe {"error":"E4021"} busca el código, no encuentra nada y le pregunta a un compañero. Un agente no puede preguntar a nadie. Trabaja con el cuerpo que enviaste, y si el cuerpo no dice nada útil, adivina: reintenta la misma petición o cambia un campo que estaba bien.
Esto dice nuestro endpoint de productos cuando el ID no existe:
$ curl -i https://api.testingapis.com/api/Products/99999
HTTP/1.1 404 Not Found
content-type: application/json; charset=utf-8
{"status":404,"error":"Not Found","message":"Product with ID 99999 does not exist."}Es una frase sosa, y está bien. Nombra el recurso y el ID, así que quien la lea, persona o programa, sabe que el problema es el ID y que volver a enviarlo no servirá de nada.
Si quieres una forma estándar para los errores, la RFC 9457 (Problem Details for HTTP APIs) define type, title, status, detail e instance, servidos como application/problem+json. Sustituyó a la RFC 7807 en 2023. No creemos que el formato exacto importe mucho. Lo que importa es que haya una frase clara en algún sitio.
Di cuánto hay que esperar
Los agentes reintentan. Si tu 429 o tu 503 no dice cuánto esperar, el cliente tiene que elegir un número, y un agente que trabaja en bucle en una tarea seguirá eligiendo. Retry-After forma parte de HTTP desde hace décadas y lo arregla con una cabecera:
$ curl -i https://api.testingapis.com/api/status/429
HTTP/1.1 429 Too Many Requests
content-type: application/json; charset=utf-8
retry-after: 5
{"status":429,"statusText":"Too Many Requests","category":"client-error","message":"This is a 429 response. Use /api/status/{code} to request any status."}/api/status/429La IETF también trabaja en las cabeceras RateLimit y RateLimit-Policy, que permiten a un cliente ver su cuota antes de agotarla en lugar de después. El borrador 11 salió en mayo. La sintaxis es así:
RateLimit-Policy: "default";q=100;w=60
RateLimit: "default";r=50;t=30Eso se lee como "100 peticiones cada 60 segundos, quedan 50, la ventana se reinicia en 30". Sigue siendo un borrador, así que no quitaríamos las cabeceras X-RateLimit-* que ya leen tus clientes. Enviar las dos cuesta muy poco.
Los reintentos crean duplicados
Reintentar un GET no hace daño. Reintentar un POST sí, si el primer intento llegó al servidor y solo se perdió la respuesta. Acabas con dos pedidos. Una persona suele notar el cobro doble. Un agente ve que su segundo intento funcionó y sigue adelante.
La solución habitual es una clave de idempotencia. El cliente envía una cabecera Idempotency-Key única con la escritura y, si la misma clave llega otra vez, el servidor devuelve el primer resultado en lugar de hacer el trabajo dos veces. Stripe funciona así desde hace años, y hay un borrador de la IETF para la cabecera, aunque todavía no es una RFC. Si tu API cobra pagos o crea algo engorroso de limpiar, merece la pena añadirla antes de que los agentes empiecen a llamarla.
Los servidores MCP se están convirtiendo en APIs HTTP corrientes
Muchos agentes no llamarán directamente a tu API REST. Pasarán por un servidor MCP que la envuelve. La especificación de MCP publicada el 28 de julio eliminó el handshake de sesión y la cabecera Mcp-Session-Id. Cada petición lleva ahora su propia versión del protocolo y los datos del cliente, y los nombres del método y de la herramienta viajan en cabeceras HTTP, así que un gateway puede enrutar y limitar peticiones sin analizar el cuerpo.
El resultado es que un servidor MCP se comporta ahora como cualquier otro servicio HTTP sin estado. Puede estar detrás de un balanceador de carga normal, y todo lo anterior se le aplica tal cual. Cuando falla una llamada a una herramienta, el agente necesita de tu servidor MCP un motivo y un tiempo de espera, igual que de tu API.
Una comprobación rápida
Este es el script que ejecutamos mientras escribíamos esto. Envía cuatro peticiones que fallan y comprueba dos cosas en cada una: ¿hay un motivo que un programa pueda leer, y hay un Retry-After?
// For each failure: is there a reason a program can read, and a time to wait?
const BASE = "https://api.testingapis.com";
const cases = [
["missing product", "/api/Products/99999"],
["rate limited", "/api/status/429"],
["server down", "/api/Products/1?error=503"],
["bad request", "/api/status/400"],
];
for (const [name, path] of cases) {
const res = await fetch(BASE + path);
const body = await res.json().catch(() => ({}));
const reason = body.message ?? body.detail ?? body.title;
const wait = res.headers.get("retry-after");
console.log(
name.padEnd(16),
res.status,
reason ? "reason: yes" : "reason: NO ",
wait ? `retry-after: ${wait}s` : "retry-after: -",
);
}missing product 404 reason: yes retry-after: -
rate limited 429 reason: yes retry-after: 5s
server down 503 reason: yes retry-after: -
bad request 400 reason: yes retry-after: -Todas las respuestas tienen un motivo, y eso está bien. Pero fíjate en la tercera línea. /api/status/503 envía Retry-After: 5, y ?error=503 en un endpoint real no envía nada. Un cliente probado contra él nunca aprendería cuándo volver a intentarlo. Ese lo tenemos en la lista.
Apunta el mismo script a los caminos de fallo de tu propia API. Si no puedes hacer que tu API falle cuando quieras, la guía de respuestas de error muestra cómo obtener de la nuestra un 500, un 429, un timeout o un cuerpo truncado.
Nada de esto es un consejo nuevo. Los mensajes de error claros y Retry-After eran buenas ideas mucho antes de que nadie construyera un agente. Lo que ha cambiado es que una persona confundida acaba escribiéndote un correo, y un agente simplemente vuelve a intentarlo.