Problema
La solicitud parece simple: verificar el estado de un incidente y dar un resumen corto.
En los traces se ve otra cosa: en 8 minutos, un run consumió más de 38k tokens, cuando tareas similares antes se mantenían en ~4-6k. La mitad del budget no se fue en la respuesta, sino en contexto: history, logs crudos y tool outputs grandes.
Para este tipo de tarea, puede ser ~$2.80 en lugar de los ~$0.20 habituales. Y la calidad de la respuesta casi no subió.
El sistema no se cae.
Simplemente infla poco a poco el prompt, la latencia y el costo.
Analogía: imagina una maleta donde antes de cada viaje agregas "una cosa importante más", pero nunca sacas nada. Al inicio casi no se nota. Después gastas más tiempo, dinero y esfuerzo solo por cargar exceso. El uso excesivo de tokens en agentes funciona igual.
Por qué pasa
El uso excesivo de tokens normalmente no viene del modelo en sí, sino de control débil del budget de contexto en runtime.
En producción suele pasar así:
- en el contexto de cada paso nuevo se mete todo: history, retrieval, tool output;
- payload crudo (logs, HTML, JSON) entra al prompt sin compresión;
- sin per-source caps ni summarization, el contexto crece cada turn;
- los tokens se gastan en "arrastrar exceso", no en progreso útil;
- reasoning loops largos sin chequeo de no-progress inflan aún más el history.
En trace, esto suele verse como crecimiento estable de prompt_tokens,
donde cada turn nuevo sale más caro que el anterior,
aunque la tarea no se vuelva más compleja.
Sin control, este crecimiento empieza a dañar latencia, costo y calidad.
Fallos más frecuentes
En producción se ven sobre todo cuatro patrones repetidos de uso excesivo de tokens.
Prompt bloat
En la solicitud al modelo entra demasiado contexto "por si acaso".
Causa típica: no hay max_prompt_tokens ni priorización de chunks.
Token bombs en tool output
Las herramientas devuelven payloads grandes (HTML, logs, stack traces), que van al prompt casi sin procesar.
Causa típica: no hay caps, y el payload no pasa por extraction o summarization antes de entrar al prompt.
Memory/history inflation
El agente acumula history turn tras turn, pero no comprime secciones antiguas. Como resultado, cada paso nuevo se vuelve más caro. Si además el run gira mucho tiempo sin progreso, esta inflación crece todavía más rápido.
Causa típica: memory se usa como "archivo", no como budgeted context.
Degradación silenciosa por truncation
Cuando el contexto supera la ventana real, partes importantes del prompt se recortan. Muchas veces desaparecen primero policy constraints o instrucciones críticas.
Causa típica: no hay control explícito de qué descartar y en qué orden.
Cómo detectar estos problemas
El uso excesivo de tokens se ve bien con la combinación de métricas de costo, latencia y contexto.
| Métrica | Señal de uso excesivo de tokens | Qué hacer |
|---|---|---|
prompt_tokens_per_run | crecimiento sostenido de tokens por run | introducir max_prompt_tokens y budgeted context builder |
tool_output_tokens | payloads crudos grandes en prompt | caps + extraction/summarization antes del modelo |
tokens_per_success | misma calidad, pero costo en alza | revisar unit economics y limitar contexto innecesario |
context_truncation_rate | recortes frecuentes de prompt | priorizar policy y hechos recientes, comprimir lo antiguo |
latency_p95 | la latencia sube junto con tokens | reducir contexto y limitar fan-out en retrieval o tool output |
Cómo distinguir sobreconsumo de una tarea realmente compleja
No todo prompt grande es malo. La pregunta clave: ¿los tokens extra aportan mejora real de calidad?
Normal si:
- la solicitud compleja de verdad requiere más fuentes y verificaciones;
tokens_per_successcrece junto con la precisión;- el contexto adicional aporta hechos nuevos y no repite lo ya conocido.
Peligroso si:
- los tokens crecen más rápido que la success rate;
- mucho contexto duplica turns viejos o dumps técnicos crudos;
- latencia y costo suben, pero las respuestas casi no cambian.
Cómo detener estos fallos
En la práctica se ve así:
- defines límites duros:
max_prompt_tokens+ caps para history/tool/retrieval; - agregas context builder con prioridades (policy y hechos nuevos por encima de logs viejos);
- comprimes fragmentos viejos o grandes en un summarization tier;
- al exceder el budget, devuelves stop reason o partial en lugar de enviar un prompt "desbordado".
Guard mínimo para token budget:
from dataclasses import dataclass
@dataclass(frozen=True)
class TokenLimits:
max_prompt_tokens: int = 7000
max_history_tokens: int = 1800
max_tool_tokens: int = 2500
max_retrieval_tokens: int = 2200
class TokenBudgetGuard:
def __init__(self, limits: TokenLimits = TokenLimits()):
self.limits = limits
self.total_prompt_tokens = 0
self.by_source = {
"history": 0,
"tool": 0,
"retrieval": 0,
}
def _cap_for(self, source: str) -> int:
if source == "history":
return self.limits.max_history_tokens
if source == "tool":
return self.limits.max_tool_tokens
if source == "retrieval":
return self.limits.max_retrieval_tokens
return self.limits.max_prompt_tokens
def add_chunk(self, source: str, tokens: int) -> str | None:
if self.by_source.get(source, 0) + tokens > self._cap_for(source):
return f"token_overuse:{source}_cap"
if self.total_prompt_tokens + tokens > self.limits.max_prompt_tokens:
return "token_overuse:prompt_budget_exceeded"
self.by_source[source] = self.by_source.get(source, 0) + tokens
self.total_prompt_tokens += tokens
return None
Este es un guard base.
En producción se suele ampliar con token counting preciso del proveedor,
un summarization tier para chunks antiguos,
y stop reasons separados para truncation.
add_chunk(...) se llama antes de meter el fragmento en prompt,
para que el budget actúe como gate y no como verificación post-facto.
Dónde se implementa en la arquitectura
En producción, el control del uso excesivo de tokens casi siempre se reparte entre tres capas del sistema.
Memory Layer gestiona qué guardar a largo plazo y qué pasar al prompt actual. Si memory significa "mostrar todo", los costos subirán sí o sí.
Tool Execution Layer se encarga de normalizar y comprimir payloads grandes antes de entrar al contexto del modelo. Aquí se aplican output caps, se extraen hechos necesarios de payloads grandes y se comprimen antes de llegar al prompt.
Agent Runtime mantiene execution budgets:
max_prompt_tokens, stop reasons, cierre controlado y fallback cuando se superan límites.
Aquí el token budget se vuelve una regla de producción, no una recomendación.
Autoevaluación
Verificación rápida antes del release. Marca los puntos y mira el estado abajo.
Este es un sanity-check corto, no una auditoría formal.
Progreso: 0/8
⚠ Hay señales de riesgo
Faltan controles básicos. Cierra los puntos clave del checklist antes del release.
FAQ
Q: ¿No podemos simplemente pasar a un modelo con mayor context window?
A: Se puede, pero normalmente cuesta más y es más lento.
Sin control de budget, el problema no desaparece, solo se mueve a un límite mayor.
Q: ¿Qué conviene al inicio: contar tokens o caracteres?
A: Lo mejor es token counting del proveedor. Si no está disponible, empieza con char caps conservadores y pasa luego a tokens.
Q: ¿Qué conviene comprimir primero al superar budget?
A: Normalmente turns antiguos y tool outputs crudos grandes. Policy y hechos más recientes deben quedarse.
Q: ¿Qué mostrar al usuario cuando se agota prompt budget?
A: Motivo de parada, qué ya se procesó y siguiente paso seguro: partial result, reducir solicitud o relanzar con menos contexto.
El uso excesivo de tokens casi nunca parece una caída ruidosa. Es una degradación lenta que infla latencia y costo sin un crash explícito del servicio. Por eso los agentes de producción necesitan no solo mejores modelos, sino control estricto del budget de contexto.
Páginas relacionadas
Si este problema aparece en producción, también conviene revisar:
- Por qué fallan los agentes de IA - mapa general de fallos en producción.
- Budget explosion - cómo el sobreconsumo de tokens se vuelve un incidente financiero.
- Tool spam - cómo llamadas innecesarias inflan contexto y costo.
- Context poisoning - cómo contexto de baja calidad degrada decisiones del agente.
- Memory Layer - dónde separar memoria de largo plazo del contexto de prompt.
- Agent Runtime - dónde definir límites de tokens, stop reasons y fallback.