Cuando mis agentes empezaron a fallar en producción, hice lo que todos hacen primero: salí a cazar alucinaciones. Mejores prompts, esquemas de salida más estrictos, más guardrails. Nada movió la aguja, porque estaba depurando la capa equivocada. El razonamiento del agente estaba bien. Era la plomería la que seguía colapsando — y el culpable más grande era lo más aburrido que puedas imaginar: los límites de tasa (rate limits).

Esto no es solo mi problema. Es el modo de fallo dominante en producción para aplicaciones LLM hoy, y casi nadie habla de ello porque no queda bien en una demo.

En resumen — En producción, lo que tumba a tu agente no suele ser mal razonamiento — es capacidad. Los rate limits de los proveedores son ahora una de las mayores fuentes de errores en llamadas LLM en trazas reales. Una demo hace una solicitud a la vez; un agente en producción se expande en docenas de llamadas encadenadas, concurrentes, con reintentos, y choca contra límites que la demo nunca tocó. La solución no es un modelo más inteligente, es ingeniería de capacidad: presupuesto, contrapresión, reintentos con jitter, modelos de respaldo y caché.

Lo que nadie pone en el pitch deck

Aquí está el número que reformuló mi forma de pensar sobre la confiabilidad de los agentes. En el análisis de Datadog sobre trazas reales de observabilidad LLM, los errores por rate limit eran una porción enorme de todas las fallas de llamadas LLM — en marzo de 2026, aproximadamente un tercio de todos los errores de span LLM eran rate limits, del orden de millones de errores individuales. Su conclusión fue directa: cuando el modo de fallo dominante de tu aplicación LLM es la capacidad, necesitas redoblar tu ingeniería de capacidad, no tu ingeniería de prompts.

Piénsalo. El modo de fallo no es que el modelo sea tonto. Es que el proveedor del modelo dice “demasiadas solicitudes” — y tu agente no tiene plan para esa respuesta.

Coincide perfectamente con la historia más amplia de “los agentes fallan en producción” que todos están escribiendo. La razón por la que las demos mienten no es malicia; es estructural. Una demo ejecuta una solicitud limpia, un usuario, un camino feliz. La producción es concurrencia, reintentos, expansión y carga — las condiciones exactas que fabrican errores de rate limit. La brecha entre “funciona en un notebook” y “funciona a las 3am bajo carga” es, más a menudo de lo que la gente admite, una brecha de capacidad disfrazada de confiabilidad.

Por qué los agentes chocan contra este muro más que los chatbots

Un chatbot simple hace una llamada API por turno de usuario. Un agente es una bestia diferente. Una sola “tarea” se expande en:

  • Una llamada de planificación
  • N llamadas de selección de herramientas mientras itera
  • Una llamada por resultado de herramienta para decidir el siguiente paso
  • Reintentos en cada una de esas cuando algo es inestable
  • A menudo uno o dos subagentes, cada uno con su propio bucle

Así que una acción de usuario se convierte en 10–40 llamadas al modelo, frecuentemente concurrentes, frecuentemente con reintentos. El multiplicador es el objetivo de los agentes — y también es exactamente lo que te lleva directo a un rate limit. Peor aún, la respuesta ingenua al fallo lo hace catastrófico: una llamada recibe un 429, el framework reintenta inmediatamente, ese reintento también recibe un 429, y ahora has convertido un error de rate limit en una tormenta de reintentos que tumba toda la tarea.

“Trata tu cuota de LLM como un recurso compartido, finito y que no escala — como un pool de conexiones de base de datos, no como CPU.”

La aritmética es implacable. Si tu proveedor te da 500 solicitudes/minuto y cada tarea de agente se expande a ~20 llamadas al modelo, entonces solo 25 tareas concurrentes saturan toda tu cuota — y eso antes de un solo reintento. Agrega reintentos inmediatos a los 429 resultantes y no degradas gracefulmente, sino que atraviesas el techo.

Esto es también donde serverless te muerde específicamente. En Cloud Run, un pico de tráfico levanta nuevas instancias felizmente — el cómputo escala bien. Pero tu cuota de LLM no escala con el número de contenedores. Así que el autoscaling hace lo peor posible: permite que más agentes concurrentes se lancen, cada uno disparando su expansión de llamadas, todos extrayendo de la misma cuota fija, todos chocando contra el techo a la vez.

El kit de herramientas de ingeniería de capacidad

Ninguna de las soluciones es exótica. Son los mismos patrones que los sistemas distribuidos han usado por décadas — simplemente no han migrado a la mayoría de las bases de código de agentes todavía. Esto es lo que realmente movió mis números de confiabilidad.

1. Presupuesto y contrapresión, no solo reintentar

El instinto es reintentar más fuerte. La solución es enviar menos. Pon un limitador de concurrencia (un semáforo o token bucket) delante de todas las llamadas salientes al modelo para que tu app nunca exceda tu cuota conocida. Cuando el presupuesto está lleno, pon en cola — no dispares y reintentes.

import asyncio

# Limita las llamadas concurrentes por debajo del límite real del proveedor.
# Deja margen — NO eres el único llamante contra esta cuota.
sem = asyncio.Semaphore(8)

async def call_model(client, **kwargs):
    async with sem:
        return await client.messages.create(**kwargs)

2. Reintentar con backoff exponencial y jitter

Cuando reintentes, nunca lo hagas inmediatamente y nunca en sincronía. Los reintentos sincronizados de muchos workers crean una manada atronadora que reactiva el límite. El backoff exponencial con jitter aleatorio los dispersa.

import asyncio, random

async def with_backoff(fn, max_retries=5, base=0.5):
    for attempt in range(max_retries):
        try:
            return await fn()
        except RateLimitError:
            if attempt == max_retries - 1:
                raise
            delay = random.uniform(0, base * (2 ** attempt))
            await asyncio.sleep(delay)

Respeta el header Retry-After si el proveedor lo envía — te está diciendo exactamente cuánto esperar.

3. Modelo de respaldo, no solo fallo

No necesitas tu modelo frontier para cada llamada. Enruta a un modelo más barato/secundario (otro proveedor, o un modelo más pequeño en una cuota separada) cuando el principal está rate-limited. Una respuesta degradada es mejor que una tarea muerta, y has distribuido la carga entre dos pools de cuota.

4. Caché agresiva

Una fracción sorprendente de las llamadas de agentes son casi duplicadas: las mismas descripciones de herramientas, el mismo contexto del sistema, las mismas subconsultas entre ejecuciones. El caché de prompt/respuesta reduce el volumen de llamadas que llegan al limitador. El error de rate limit más barato es la solicitud que nunca enviaste.

5. Haz la capacidad observable

No puedes hacer ingeniería de lo que no ves. Los rate limit sorprenden a los equipos porque aparecen como errores genéricos de “agente falló”, no como un problema etiquetado de capacidad. Registra la clase de error (429 vs timeout vs error de herramienta), monitorea tu concurrencia en vuelo y tu tasa de 429 como métricas de primera clase, y alerta sobre ellas.

El cambio de modelo mental

Lo que le diría a mi yo del pasado: trata tu cuota de LLM como un recurso compartido, finito y que no escala — como un pool de conexiones de base de datos, no como CPU. El cómputo escala elásticamente. Tus cuotas de tokens por minuto y solicitudes por minuto no. Una vez que internalizas eso, la confiabilidad de los agentes deja de verse como un problema de IA y empieza a verse como un problema clásico de capacidad en sistemas distribuidos — lo cual es una gran noticia, porque ya sabemos cómo resolverlos.

Los modelos más inteligentes no te salvarán aquí. Un GPT-6 que razona perfectamente sigue devolviendo 429 cuando excedes tu cuota. La frontera de confiabilidad para agentes en 2026 no es la inteligencia — es la ingeniería de capacidad.


Fuentes: