Cambiar tema

Control de costos en agentes de IA: routing de modelos, presupuestos de herramientas, caché y retries

Easton editorial illustration: agent rollout and rollback rail
7
Capas de presupuesto
user, tenant, workflow, task, tool, retry, cache.
4
Acciones de control
route, degrade, pause, abort.
3
Tipos de caché
prompt prefix cache, business result cache, tool response cache.
数据来源: Esta checklist de ingeniería se basa en la investigación de documentos oficiales de la fase 1; precios, descuentos y disponibilidad de modelos deben verificarse contra páginas oficiales antes de publicar.

"OpenAI API Pricing"

A las 3 de la mañana, un report Agent en segundo plano devuelve una respuesta vacía. El estado HTTP es 200, pero el body viene vacío. La lógica de retry solo revisa el código de estado, así que sigue intentando. Cada request envía 500 tokens de entrada. Después de 1.500 retries, se quemaron 750.000 tokens. La factura del día siguiente hace evidente el problema.

La causa raíz no es “elegimos un modelo caro”. Faltaban tres piezas: circuit breaker, verificación de presupuesto y clasificación de errores. El costo de un Agent suele descontrolarse de tres maneras:

Retries sin límite. No hay clasificación de fallos, así que una respuesta vacía se trata como error recuperable. Falta el circuit breaker, por lo que 1.500 fallos seguidos tampoco detienen la ejecución. Cada retry vuelve a enviar todo el contexto y multiplica el costo 2-5 veces.

Contexto inflado. Una tarea larga corre 6 horas y el historial de conversación crece hasta 80K tokens. Sin checkpoint, un fallo reinicia todo desde cero y cada paso se paga otra vez.

Uso excesivo del modelo. Todas las tareas usan un frontier model porque no hay estrategia de routing. Incluso una clasificación simple pasa por el camino más caro y desperdicia el 70% de los tokens.

El control de costos de un Agent no es una optimización aislada. Es un diseño por capas: objetos de presupuesto, estrategia de routing, cache hits, circuit breakers de retry, logs de costo y umbrales de alerta. Conviene convertir esos seis objetos de ingeniería en tablas de decisión o checks ejecutables.

Diseño del objeto de presupuesto: qué registrar, dónde guardarlo y cuándo cortar

El control de costos empieza con un objeto de presupuesto, no con un total único. Sin capas, un pico de factura no te dice qué usuario, tarea o herramienta quemó el presupuesto.

Siete capas de presupuesto

Los objetos de presupuesto se separan de lo más grueso a lo más fino:

Capa de presupuestoObjeto de presupuestoLímite sugeridoDisparador de alerta
Layer 1userLímite diario/mensual por usuarioAlerta si queda < 20%
Layer 2tenantPool de presupuesto por tenantAlerta si queda < 30%
Layer 3workflowPresupuesto por tipo de workflowAlerta si queda < 40%
Layer 4taskPresupuesto por tipo de tareaAlerta si queda < 50%
Layer 5toolPresupuesto por llamada de herramientaSaltar herramienta si supera el límite
Layer 6retryLímite de retries + circuit breakerDesactivar herramienta tras N fallos consecutivos
Layer 7cacheMonitoreo del cache hit rateAlerta si el hit rate cae bajo lo esperado

Cada límite depende del modelo de negocio y es configuración mutable. La estructura de capas es más estable. El campo de presupuesto restante debe entrar en los logs de costo para alimentar alertas y circuit breakers.

Campos que debe registrar cada capa

Cada capa de presupuesto debe registrar estos campos:

CampoUsoTipoPor qué registrarlo
modelIdentificar el modelostringEvaluar si el routing de modelos tiene sentido
inputTokensTokens de entradaintegerCalcular costo de entrada
outputTokensTokens de salidaintegerEl costo de salida debe seguirse por separado
cachedTokensTokens servidos por cachéintegerMedir ahorro por caché
costEstimateEstimación de costo de esta llamadafloatAcumular costo en tiempo real
budgetRemainingPresupuesto restantefloatBase para decisiones de circuit breaker

El punto del objeto de presupuesto es contabilizar por dimensión, no “guardar total_cost”. En multi-tenant, el costo se reparte por tenantId. En sistemas con muchas herramientas, toolName abre la caja negra.

Lógica de circuit breaker

Cuando el presupuesto restante cae bajo un umbral, activa el circuit breaker:

def check_budget_before_retry(budget_remaining, retry_cost_estimate):
    if budget_remaining < retry_cost_estimate:
        return "skip_retry"  # Saltar el retry porque excedería el presupuesto
    if budget_remaining < threshold:  # threshold por ejemplo 20%
        return "wait_approval"  # Presupuesto bajo, esperar aprobación
    return "continue"

El circuit breaker revisa el presupuesto antes del retry, no después. Estima el costo antes de cada retry y detente si la próxima prueba excede el presupuesto. Así evitas la respuesta vacía reintentada 1.500 veces.

El artículo de context engineering de esta serie cubrirá qué contexto va en un prefix estable y qué contenido debe quedarse como variable de ejecución.

Estrategia de routing de modelos: no todas las tareas necesitan el modelo más caro

Un ticket triage Agent suele tener esta distribución: 70% de tareas son clasificación simple, 20% necesitan redactar una respuesta y solo 10% deberían subir a un frontier model antes de enviar un correo al cliente. Una estrategia de routing puede ahorrar 40-85% del costo.

Routing a nivel de modelo

El routing por modelo se basa en complejidad:

Nivel de tareaTareas típicasNivel de modelo recomendadoProporciónPerfil de costo
70% - nivel SClasificación, extracción, filtrado, Q&A simplenano/flash (más barato)70%Salida corta, pocos turnos, pocas llamadas de herramientas
20% - nivel MRedacción, resumen, generación de código, razonamiento mediomid-tier (precio medio)20%Salida media, posible uso de herramientas
10% - nivel LRevisión, arquitectura, razonamiento complejo, coordinación multi-herramientafrontier (más caro)10%Salida larga, muchos turnos, herramientas frecuentes

La estrategia tiene tres pasos:

Paso 1: clasificar la tarea. Define criterios S/M/L para cada workflow: longitud de salida, número de llamadas a herramientas, profundidad de razonamiento y nivel de riesgo.

Paso 2: usar S como valor por defecto. Solo sube a M o L cuando aparezcan señales de complejidad.

Paso 3: routing en cascada. Si S falla, sube a M. Si M falla, sube a L. Si L falla, entra intervención humana. Antes de cada subida, revisa presupuesto restante; si no alcanza, salta la subida.

Routing a nivel de servicio

El mismo modelo también puede dividirse por latency priority. Descuentos y ventanas de entrega cambian, así que verifica precios oficiales antes de publicar.

Nivel de servicioDescuento de costoTiempo de finalizaciónCaso adecuado
Realtime APISin descuentoRespuesta inmediataChat interactivo con Agent, tareas prioritarias
Batch API50% cost discount (verificar antes de publicar)24-hour turnaround (verificar antes de publicar)evals batch, clasificación, embeddings, procesamiento de repositorios de contenido
Flex ProcessingMenor costo (verificar antes de publicar)Respuesta más lenta, indisponibilidad ocasionalTareas asíncronas de baja prioridad, model evaluations, data enrichment

Checklist para routing offline:

  • ¿Necesita respuesta inmediata? Sí -> Realtime API, con routing de modelo.
  • ¿Puede aceptar 24 horas de espera? Sí -> Batch API.
  • ¿Es de baja prioridad y tolera fallos ocasionales? Sí -> Flex Processing.
  • ¿Es trabajo batch como eval, clasificación o embedding? Sí -> Batch API.

Clasificación por riesgo

También hay que clasificar por riesgo:

Nivel de riesgoOperación típicaEstrategia de routingRama de presupuesto
Bajo riesgoClasificación, extracción, resumen internoModelo S + camino automáticoSin aprobación, límite amplio
Riesgo medioBorrador de respuesta a cliente, sugerencia de cambio de códigoModelo M + aprobación opcionalSi excede presupuesto, pedir aprobación
Alto riesgoEnviar correo a cliente, cobrar, cambiar arquitecturaModelo L + aprobación obligatoriaEspera, rechazo y timeout son ramas de presupuesto

El artículo Human-in-the-Loop de la misma serie explica cómo espera, rechazo y timeout afectan esas ramas de presupuesto.

Restricciones clave

El routing necesita restricciones claras:

  • No hardcodear precios: los precios cambian. Guarda model + pricingVersion en lugar de fijar una fórmula de costo en la lógica de negocio.
  • Revisar presupuesto restante: antes de subir de nivel, revisa budgetRemaining. Si no alcanza, salta la subida o pide aprobación.
  • Clasificar errores: separa fallos recuperables por capacidad del modelo de errores no recuperables como parámetros inválidos o permisos denegados.

Presupuesto de llamadas a herramientas: per-tool budget, timeout y límite de retries

Una llamada de herramienta tiene costo de schema y de API. Cada llamada envía schema, argumentos y contexto de parsing de respuesta; además la API externa puede rate-limitar o expirar. Son costos separados de la llamada al modelo.

Control del presupuesto de herramientas

Cada herramienta necesita controles propios:

ControlConfiguración sugeridaCampo de monitoreoAcción
Per-tool budgetLímite por llamadatool_cost_estimateSaltar herramienta o degradar
Tool timeoutTimeout de la API externatool_durationMarcar timeout como error recuperable
Retry limit per toolLímite de retries por herramientatool_retry_countAbandonar herramienta, no entrar en bucle

Las herramientas que llaman API externas, como búsqueda, base de datos o servicios de terceros, necesitan contabilidad propia. Si no, tool calling se vuelve una caja negra de costos.

Clasificación de fallos de herramientas

Los fallos de herramientas se dividen en recuperables y no recuperables:

Tipo de falloErrores típicosEstrategiaImpacto de costo
Fallo recuperableTimeout de red, 503 Service Unavailable, 429 Rate LimitRetry automático con exponential backoff y retry-afterCada retry envía todo el contexto
Fallo no recuperable403 Permission Denied, 400 Bad Request, herramienta inexistenteNo retry; inyectar el error para que el modelo decidaSin retry, sin gasto repetido

La regla es simple: reintenta solo fallos temporales causados por condiciones externas. No reintentes errores de configuración interna.

Circuit breaker

Después de N fallos consecutivos, desactiva la herramienta:

def circuit_breaker_tool(tool_name, consecutive_failures, threshold=5):
    if consecutive_failures >= threshold:
        return "disable_tool"  # Desactivar herramienta
    return "continue"

El estado del circuit breaker debe quedar en logs para explicar por qué se desactivó la herramienta. Tras activarse, espera intervención humana o un check de recuperación, en lugar de seguir llamando una herramienta inestable.

Las bases de tool calling están en Tool Calling. Aquí se amplía con per-tool budget, timeout y límites de retry.

Diseño de Prompt Caching: prefix estable, variables y umbral de 1024 tokens

Prompt Caching optimiza el costo de tokens de entrada para un prompt prefix estable. No es una caché de resultados de negocio. Rutea requests con el mismo prompt prefix a un servidor que procesó recientemente ese prefix, lo que puede reducir latencia y costo de entrada.

Prompt Caching no es caché de resultados

Prompt Caching guarda un prompt prefix estable, no un resultado de negocio. La diferencia importa:

  • Prompt Caching: guarda un prompt prefix estable, como system prompt o tool schema. Un hit ahorra tokens de entrada, pero la inferencia se ejecuta igual.
  • Caché de resultados de negocio: guarda una salida completa, como resultado de herramienta o consulta de base de datos. Un hit responde directo sin llamar al modelo.

Los objetivos son distintos. Prompt Caching reduce costo de tokens de entrada; la caché de negocio reduce el costo de la llamada completa. Pueden convivir: prefixes estables por Prompt Caching, resultados frecuentes de herramientas por caché de negocio.

Requisitos de estructura

La clave es separar prefix estable y variables de ejecución:

Tipo de contenidoPosiciónProbabilidad de cache hitEjemplos
Prefix estable (entra en caché)Inicio del promptAltaSystem prompt, Tool schema, documentos Policy, ejemplos Few-shot
Variables de ejecución (fuera de caché)Más adelante en el promptBajaUser input, File fragments, Runtime state (turno actual, variables temporales)

Pasos de diseño:

  1. Poner System prompt, Tool schema y Policy al inicio: son estables entre llamadas y tienen más probabilidad de hit.
  2. Poner User input, File fragments y Runtime state después: cambian en cada llamada y no deben formar parte del prefix estable.
  3. Monitorear Cache hit rate: registra cachedTokens y tokens de entrada totales, luego calcula el hit rate. Más de 40% es sano; menos de 20% requiere revisar la estructura.

Umbral y efecto

El umbral automático y el efecto de Prompt Caching son hechos variables; verifica documentación oficial antes de publicar:

  • Umbral: activación automática desde 1024 tokens (verificar antes de publicar).
  • Efecto: los hits pueden reducir costo y latencia (verificar ratios exactos).
  • Ver hits: campo usage.prompt_tokens_details.cached_tokens.

Modelos soportados, umbrales y descuentos de Prompt Caching pueden cambiar. Verifícalos contra la página oficial de pricing. El principio durable es estable: contenido estático adelante, contenido variable atrás.

Circuit breakers de retry: idempotencia, checkpoints y presupuesto restante

Los retries son una de las fuentes más grandes de costo descontrolado. Un report Agent atascado en una herramienta inestable puede reenviar todo el contexto en cada fallo; tras 1.500 retries, el costo se aleja mucho del camino normal.

Revisar presupuesto antes del retry

Revisa el presupuesto restante antes de reintentar, no después:

def should_retry(error_type, budget_remaining, retry_cost_estimate):
    # Clasificación de error
    if error_type in ["403", "400", "tool_not_exist"]:
        return False  # Error no recuperable, no retry

    # Verificación de presupuesto
    if budget_remaining < retry_cost_estimate:
        return False  # Fuera de presupuesto, no retry

    return True  # Retry permitido

La verificación de presupuesto debe ir antes de la lógica de retry. Así evitas gastar el presupuesto diario en una respuesta vacía reintentada 1.500 veces.

Idempotencia

Un retry no debe repetir efectos secundarios, como enviar correos o cobrar:

  • Usa un ID de idempotencia, como requestId, para llamadas de herramientas. Si la API externa recibe el mismo ID, debe devolver el resultado cacheado en vez de procesar otra vez.
  • Escribe el ID de idempotencia en los logs de costo para diagnosticar llamadas repetidas.

La idea de idempotencia es que la misma operación no consuma dos veces. Sin eso, los retries amplifican costo y efectos secundarios.

Guardado de estado (Checkpoint)

Las tareas largas deben recuperarse sin repetir todo el workflow:

  • Guarda un checkpoint en nodos importantes: pasos completados, estado actual y resumen de contexto.
  • Tras un fallo, continúa desde el checkpoint, no desde el inicio.
  • Persiste el checkpoint. No basta con dejarlo en memoria.

El diseño de checkpoint y thread state se cubre en Arquitectura de Agent con LangGraph.

Estrategia de retry

Cada tipo de error necesita una estrategia distinta:

Tipo de errorError típicoEstrategia de retryImpacto de costo
Timeout de redSin respuesta en 10 segundosExponential backoff + retry-after, máximo 3 retriesCada retry envía todo el contexto
503/429Service Unavailable, Rate LimitEsperar ventana de rate limit + retry-after, máximo 3 retriesLa espera no consume tokens, el retry sí
403/400Permission Denied, Bad RequestNo retry; inyectar error para que el modelo decidaSin retry, evita gasto inválido

La regla es: solo se reintentan errores recuperables. No mandes requests inválidos al modelo una y otra vez.

Circuit breaker

Después de N fallos consecutivos, detén retries y espera intervención:

def circuit_breaker(consecutive_failures, threshold=5):
    if consecutive_failures >= threshold:
        return "stop_retry"  # Detener retries
    return "continue"

La decisión del circuit breaker debe quedar en logs para explicar por qué se detuvieron los retries. Después, espera intervención humana o recuperación de presupuesto, en lugar de llamar otra vez un modelo o herramienta inestable.

Logs de costo y alertas: campos y umbrales

La observabilidad de costos es la condición previa para controlar costos. Si los campos de log están incompletos, no encontrarás el problema.

OpenTelemetry trace span attributes

Diseña logs de costo en tres niveles de span:

Agent run span (nivel superior):

CampoUsoTipoPor qué registrarlo
runIdIdentificar ejecución específicastringDistingue runs repetidos del mismo workflow
tenantIdIdentificar tenantstringReparte costos en sistemas multi-tenant
userIdIdentificar usuariostringSigue tendencias de costo por usuario
workflowNameIdentificar workflowstringSigue costos por tipo de workflow
totalCostCosto total estimadofloatAcumula costo en tiempo real
budgetRemainingPresupuesto restantefloatBase para circuit breaker
totalRetriesTotal de retriesintegerMuestra amplificación por retries

Model call span (span hijo):

CampoUsoTipoPor qué registrarlo
modelIdentificar modelostringVer si el routing tiene sentido
pricingVersionVersión de preciosstringEvita fórmulas de costo hardcodeadas
inputTokensTokens de entradaintegerCalcula costo de entrada
outputTokensTokens de salidaintegerSigue costo de salida por separado
cachedTokensTokens cacheadosintegerCalcula ahorro de caché
costEstimateEstimación de esta llamadafloatAcumula costo en tiempo real
latencyMsLatencia de llamadaintegerAyuda a decidir si Batch/Flex encaja

Tool call span (span hijo):

CampoUsoTipoPor qué registrarlo
toolNameIdentificar herramientastringUbica overhead de tool calls
toolBudgetLímite de presupuesto de herramientafloatBase para circuit breaker
toolTimeoutTimeout de herramientaintegerClasifica fallos de timeout
retryCountNúmero de retriesintegerMide amplificación por retries
errorTypeTipo de errorstringSepara recuperable de no recuperable

No registres solo total_cost. Divide por dimensión. Sin estos campos, un pico de factura solo dice “sobre presupuesto”; no dice qué usuario, herramienta o retry lo causó.

El diseño completo de logs, alertas y recuperación se cubre en Monitoreo y recuperación de Agents. Este artículo añade campos de costo y objetos de presupuesto.

Umbrales de alerta

Define umbrales por dimensión:

Dimensión de alertaUmbralCanalAcción
Consumo global de presupuesto70%, 90%, 100%Slack/email70% avisar, 90% degradar, 100% cortar
Consumo de un user/tenantMás de 3x el promedioSlack/emailRevisar llamadas anómalas
Tasa de fallo de un modelo> 5%DashboardRevisar routing o estado del servicio
Retries de una herramienta> umbralDashboardRevisar estabilidad de la herramienta
Cache hit rate< valor esperadoDashboardRevisar estructura del prompt

Los umbrales deben estar en la lógica de costo para disparar alertas y circuit breakers automáticamente.

Estrategia de degradación

Después de una alerta, la degradación puede seguir estos caminos:

Camino de degradaciónMétodoCaso adecuadoImpacto de costo
Degradación de modeloModelo grande -> modelo pequeñoUn modelo tiene alta tasa de fallosBaja costo, puede bajar calidad
Degradación de caminoRealtime API -> Batch API -> Flex ProcessingEl presupuesto global se consume demasiado rápidoSube latencia, baja costo
Degradación de funciónDesactivar herramientas no esencialesUna herramienta acumula demasiados retriesReduce overhead de herramientas
Degradación de usuarioRate limit, cola, mensaje “intenta más tarde”Consumo anómalo de un usuarioEvita que un usuario queme presupuesto

La degradación debe vivir en la lógica de presupuesto. Cuando se dispara una alerta, el sistema debe degradar automáticamente, no esperar intervención manual.

Siguientes pasos

El control de costos de Agents depende de monitoreo, tool calling y context engineering:

  • Publicado: Monitoreo y recuperación de Agents: campos de log, alertas y recuperación de fallos. Este artículo añade campos de costo y objetos de presupuesto.
  • Publicado: Arquitectura de Agent con LangGraph: checkpoints, thread state y recuperación para tareas largas.
  • Publicado: Tool Calling: bases de llamadas a herramientas. Este artículo añade per-tool budget, timeout y límites de retry.
  • Misma serie: context engineering: prefixes estables, cache hits y qué contexto va en el prefix estable frente a variables de ejecución.
  • Misma serie: Human-in-the-Loop: espera, rechazo, timeout de aprobación y cómo cambian costos y retries.

Empieza por la defensa a nivel de sesión: define un per-session cost limit y termina la sesión automáticamente cuando exceda el presupuesto. Es la protección inicial más rápida contra una tarea descontrolada que quema el presupuesto del día. Luego amplía el diseño a capas de presupuesto, routing de modelos, presupuestos de herramientas, Prompt Caching, circuit breakers de retry y logs de costo.

Diseñar un presupuesto de costos y circuit breaker para Agents

Usa objetos de presupuesto, routing de modelos, routing de servicio, caché, presupuestos de herramientas y circuit breakers de retry para mover el control de costos antes de ejecutar cada run.

⏱️ Estimated time: 45 min

  1. 1

    Step 1: Listar todos los caminos de costo

    Enumera llamadas a modelos, llamadas a herramientas, lecturas de archivos, API externas, procesos batch, cachés y rutas de retry del Agent.
  2. 2

    Step 2: Definir el objeto de presupuesto

    Registra presupuestos por tenant, user, run, workflow, model, tool, retry, cache y time window.
  3. 3

    Step 3: Configurar la estrategia de routing

    Define routing de modelos y routing de servicio para distintos tipos de tareas: online, batch, flex y queue.
  4. 4

    Step 4: Diseñar los cache hits

    Pon el contexto estable en el prompt prefix, deja el contenido variable después y separa prompt caching, caché de resultados de negocio y caché de respuestas de herramientas.
  5. 5

    Step 5: Limitar herramientas y retries

    Asigna a cada herramienta timeout, max retries, idempotency key, per-tool budget y fallback.
  6. 6

    Step 6: Registrar spans de costo

    En cada run/span registra token, cached token, tool, retry, latency, estimated cost, budget remaining y traceId.
  7. 7

    Step 7: Configurar degradación y circuit breaker

    Define umbrales de degradación, pausa, circuit breaker y alertas, y pruébalos con fallos reales.

FAQ

¿El costo de un Agent se debe medir por usuario, sesión, tarea o herramienta?
Mídelo por capas: user, tenant, workflow, task, tool, retry y cache. Cada capa necesita su propio presupuesto y circuit breaker. Si solo guardas total_cost, no podrás ubicar qué usuario, herramienta o ruta de retry provocó el pico.
¿El routing de modelos solo consiste en usar un modelo pequeño para tareas simples?
No. También necesitas routing de servicio, como Batch/Flex/tiempo real, y clasificación por riesgo. El mismo modelo puede dividirse por latency priority. El trabajo offline encaja con Batch API y las tareas de baja prioridad con Flex Processing.
¿Cuál es la diferencia entre Prompt Caching y una caché de negocio normal?
Prompt Caching guarda un prompt prefix estable, como system prompt, tool schema y policy. No guarda el resultado de negocio. Una caché de negocio guarda salidas completas o respuestas de herramientas. Resuelven problemas distintos y pueden convivir.
¿Cuántas veces conviene reintentar una llamada de herramienta fallida?
No uses solo un número fijo. Mira la clase de error, el presupuesto restante y el estado del circuit breaker. Reintenta pocas veces los errores recuperables; no reintentes 403, 400 ni herramientas inexistentes.
¿Qué hacer si una tarea larga de Agent se queda sin presupuesto a mitad de camino?
Lo más seguro es pausar, guardar un checkpoint y esperar recuperación de presupuesto o aprobación humana. Fallar de golpe pierde progreso; degradar a ciegas puede bajar la calidad.
¿Qué campos debe registrar un log de costo?
Como mínimo: runId, tenantId, workflow, model, input/output/cached tokens, toolName, retryCount, latency, costEstimate, budgetRemaining, decision y traceId.

16 min de lectura · Publicado el: 17 sep 2026

Comentarios

Inicia sesión con GitHub para dejar un comentario

Easton BlogEaston Blog