Idea en 30 segundos
Rate limiting es un control de runtime que limita la frecuencia de llamadas externas del agente para evitar picos y tormentas de retries en producción.
Cuándo se necesita: cuando un agente llama con frecuencia a model/tool API, tiene lógica de retries y opera bajo carga pico.
Problema
Sin rate limiting, un servicio inestable acelera rápido una cadena: retry → llamada → otro retry.
En demo casi no se nota. En producción, este comportamiento crea olas de 429/5xx, colas y latencia.
Lo peor es que el incidente se amplifica solo:
- un usuario demasiado activo consume cuotas
- un tenant "asfixia" a otros
- un pico global rompe dependencias para todos a la vez
Y cada minuto sin control de frecuencia agrega más retries, colas y retrasos, hasta que el sistema termina haciéndose DDoS a sí mismo.
Analogía: es como una rampa de acceso regulada a la autopista. Si no dosificas el flujo, incluso una buena vía se convierte en atasco en minutos.
Solución
La solución es añadir una capa policy de rate limit centralizada en runtime y en tool gateway.
Cada llamada externa del agente se verifica contra límites per_user, per_tenant, global y burst_tokens.
La policy devuelve una decisión técnica: allow o stop con razón explícita:
rate_limited_userrate_limited_tenantrate_limited_globalburst_limited
Cuando devuelve stop, runtime responde al cliente con retry_after_ms y no ejecuta la llamada.
Es una capa separada del sistema, no parte del prompt ni de la lógica del modelo.
Rate limiting ≠ step limits
Son niveles de control distintos:
- Rate limiting limita la frecuencia de llamadas externas.
- Step limits limita la longitud y el comportamiento del runtime loop.
Uno sin el otro no alcanza:
- sin rate limiting, las API externas caen por picos y tormentas de retries
- sin step limits, un run puede seguir girando demasiado incluso con frecuencia moderada
Ejemplo:
- rate limiting: no más de
per_user=6llamadas por 10 segundos - step limits:
max_steps=18,max_repeat_action=3
Componentes del control rate limiting
Estos componentes trabajan juntos en cada llamada externa del agente.
| Componente | Qué controla | Mecánicas clave | Para qué |
|---|---|---|---|
| Per-user limit | Comportamiento de un usuario | per_user quotasliding window | Evita que un usuario consuma toda la capacidad |
| Per-tenant limit | Carga de un tenant | per_tenant quotatenant-scoped keys | Aísla picos entre clientes |
| Global limit | Carga total del sistema | global capshared limiter | Protege dependencias externas frente a picos masivos |
| Burst control | Picos cortos de tráfico | token bucket refill rate | Amortigua saltos inmediatos sin detener todo el sistema |
| Rate-limit observability | Visibilidad de decisiones policy | audit logs alerts sobre stop spikes | No limita llamadas de forma directa, pero ayuda a ubicar rápido la fuente del pico |
Ejemplo de alerta:
Slack: 🛑 Support-Agent hit rate_limited_tenant. retry_after=1200ms, tenant=t_42.
Cómo se ve en la arquitectura
La capa policy de rate limit se ubica entre runtime y model/tool API externos.
Cada decisión (allow o stop) se registra en audit log.
Cada llamada externa del agente pasa por este flow antes de ejecutarse: runtime no ejecuta llamadas directamente, primero pide una decisión al policy layer.
Resumen del flow:
- Runtime forma una llamada externa del agente
- Policy verifica
per_user,per_tenant,globalyburst_tokens allow→ se ejecuta la llamadastop→ se devuelveretry_after_msy respuesta parcial- ambas decisiones se escriben en audit log
Ejemplo
Un agente de soporte procesa muchas solicitudes en paralelo y reintenta crm.search varias veces.
Con rate limiting:
per_user = 6 / 10sper_tenant = 120 / minglobal = 50 / sburst_tokens = 5
→ el pico se detiene a nivel policy antes de que fallen dependencias y colas.
Rate limiting detiene el incidente justo antes de la llamada externa, no después de una ola de 429.
En código se ve así
El esquema simplificado de arriba muestra el flujo principal.
Punto crítico: el rate-limit check debe ser O(1) y atómico (normalmente via Redis/Lua o equivalente), si no, se convierte en cuello de botella bajo pico.
Después de stop(...), runtime suele devolver respuesta parcial al cliente con razón explícita y retry_after_ms.
Ejemplo de configuración de rate limit:
rate_limits:
per_user_10s: 6
per_tenant_min: 120
global_rps: 50
burst_tokens: 5
refill_per_second: 2
action = planner.next(state)
action_key = make_action_key(action.name, action.args)
if not action.is_external_call():
# execute_local — helper condicional para acciones locales sin API externa.
# Decision.allow — helper condicional para mantener un modelo único outcome/reason.
local_result = execute_local(action)
local_decision = Decision.allow(reason=None)
audit.log(
run_id,
decision=local_decision.outcome,
reason=local_decision.reason,
scope="local",
action=action.name,
action_key=action_key,
result=local_result.status,
)
return local_result
decision = rate_limit.check(
user_id=state.user_id,
tenant_id=state.tenant_id,
action=action.name,
now_ms=clock.now_ms(),
)
if decision.outcome == "stop":
audit.log(
run_id,
decision=decision.outcome,
reason=decision.reason,
scope=decision.scope,
retry_after_ms=decision.retry_after_ms,
action=action.name,
action_key=action_key,
)
alerts.notify_if_needed(run_id, decision.reason, scope=decision.scope)
return stop(decision.reason, retry_after_ms=decision.retry_after_ms)
result = executor.execute(action)
audit.log(
run_id,
decision=decision.outcome,
reason=decision.reason,
scope=decision.scope,
action=action.name,
action_key=action_key,
result=result.status,
)
return result
Cómo se ve durante la ejecución
Escenario 1: parada por límite de tenant
- Runtime forma llamada externa
crm.search. - Policy detecta cuota
per_tenantexcedida. - Decisión:
stop (reason=rate_limited_tenant). - Runtime devuelve
retry_after_ms. - La llamada no se ejecuta y el evento se guarda en audit log.
Escenario 2: pico burst
- Varios runs crean un pico corto de llamadas al mismo tiempo.
- Policy agota
burst_tokens. - Decisión:
stop (reason=burst_limited). - Parte de llamadas se rechaza con
retry_after_ms. - El sistema se mantiene estable sin cascade-failure.
Escenario 3: ejecución normal
- Runtime forma llamada externa.
- Policy verifica límites: todo dentro de rango.
- Decisión:
allow. - La llamada se ejecuta.
- Decisión y resultado se registran en audit log.
Errores típicos
- poner solo límite global sin aislamiento
per_user/per_tenant - no devolver
retry_afteral hacerstop - hacer retry sin backoff ni jitter
- verificar rate limit en una sola capa (solo runtime o solo gateway)
- no loguear decisiones stop (
reason,scope,retry_after_ms) - no tener alerting en picos
rate_limited_*
Resultado: el sistema parece controlado, pero se degrada rápido ante picos reales.
Autoevaluación
Chequeo rápido de rate limiting antes de lanzar a producción:
Progreso: 0/8
⚠ Faltan controles base de governance
Antes de production necesitas como mínimo control de acceso, límites, audit logs y parada de emergencia.
FAQ
P: ¿Con qué límites conviene empezar?
R: Como mínimo: per_user, per_tenant, global + un control pequeño de burst. Después ajusta según eventos stop reales.
P: Si la API externa ya devuelve 429, ¿igual necesitamos rate limiting propio?
R: Sí. El rate limiting interno protege runtime antes del 429 externo y da stop reasons, retry_after y audit controlados.
P: Ante límite alcanzado, ¿mejor stop o cola?
R: Para runs sync suele ser mejor stop + retry_after. En pipelines async puedes agregar cola, pero siempre con límites explícitos y timeout.
P: ¿Rate limiting reemplaza budget controls?
R: No. Rate limiting controla frecuencia de llamadas, budget controls controla el gasto total del run.
P: ¿Dónde guardar contadores?
R: En almacenamiento compartido de baja latencia con operaciones atómicas (a menudo Redis). Sin esto, los límites serán inconsistentes entre instancias.
Dónde encaja Rate Limiting en el sistema
Rate limiting es una de las capas de Agent Governance. Junto con RBAC, budgets, step limits, approval y audit, forma un sistema unificado de control de ejecución.
Páginas relacionadas
Siguiente sobre este tema:
- Resumen de Agent Governance — modelo general de control de agentes en producción.
- Budget Controls — cómo limitar el gasto total de un run.
- Step limits — cómo detener loops en runtime.
- Kill switch — cómo detener acciones de emergencia sin release.
- Audit logs para agentes — cómo analizar stop reasons y picos de carga.