Cambiar tema

Monitorización, alertas y recuperación de fallos en AI Agent: diseño práctico del registro de logs a la máquina de estados

Easton editorial illustration: large Agent state recorder, coral failure beacon, checkpoint rewind handle, recovery status strip

Un informe de Gartner de 2024 señala que el 87 % de los proyectos empresariales de AI Agent superan una tasa de fallo del 25 % en los tres primeros meses tras el despliegue. La causa suele estar enterrada en capas de llamadas a herramientas, con logs dispersos imposibles de rastrear.

La raíz no está en la cantidad de alertas, sino en que la arquitectura de monitorización del Agent es incorrecta desde el principio. Un Agent no es un servicio backend convencional: su carácter no determinista hace que la monitorización tradicional no alcance — la ruta de ejecución se genera dinámicamente y la misma tarea puede seguir caminos distintos. Este artículo te ofrece un diseño completo: de logs a métricas y trazas, hasta la arquitectura de máquina de estados, para convertir el Agent de «caja negra incontrolable» en un sistema transparente donde cada fallo es trazable y recuperable.

Capítulo 1: ¿Por qué la monitorización tradicional falla con los Agent?

¿Te ha pasado? Un Agent falla, revisas los logs y solo encuentras fragmentos de salida del LLM sin poder reconstruir la trayectoria completa. Al final vuelves a ejecutarlo y esperas que esta vez funcione.

La lógica de monitorización de un backend tradicional es clara: entra una petición, pasa por los microservicios A, B y C, cada nodo registra estado y timestamp, y si algo falla sigues la cadena. Un Agent no funciona así.

La ruta de ejecución se genera de forma dinámica. En la misma tarea, la primera vez puede llamar a la herramienta A, la segunda a la B y la tercera saltarse las herramientas por completo. Un informe de OpenAI de 2024 indica que la tasa media de finalización de tareas de Agent es solo del 61,8 % — en gran parte porque el Agent toma decisiones durante el razonamiento y esas decisiones son inherentemente inciertas.

Peor aún está el God Prompt: meter toda la lógica del Agent en un prompt gigante. El blog técnico de ArizenAI lo llama «el asesino número uno en producción». ¿Por qué? Tres problemas: no es testeable, no es depurable y no es predecible.

No puedes hacer unit tests de un prompt de 5 000 palabras. No puedes localizar con precisión qué paso del razonamiento falló. Tampoco puedes predecir si cambiar un parámetro provocará un colapso en cadena. En un proyecto vi un God Prompt donde, tras cambiar un ejemplo, la tasa de éxito cayó del 70 % al 30 %. Tardamos una semana en descubrir que el nuevo ejemplo enseñó al Agent a «priorizar la herramienta A», que en ese escenario no debía invocarse.

OpenAI también destaca un dato: el 82 % de los fallos de Agent son errores reparables. No es falta de capacidad del Agent, sino de robustez del diseño. La monitorización no debe limitarse a «detectar problemas»: debe ser el bucle de retroalimentación que mejora el Agent. Necesitas la tasa de éxito por estado, la latencia de cada llamada a herramienta y la frecuencia de cada tipo de error — esos datos te dicen dónde hay que ajustar.

La mentalidad tradicional es «cuando falle, investigamos». Con Agent, la idea es «cada paso deja rastro; el fallo en sí es una oportunidad de aprendizaje». Ese cambio de perspectiva es el punto de partida de todo el sistema.

Capítulo 2: Arquitectura de observabilidad en tres capas para AI Agent

Monitorizar un Agent no depende de una sola técnica, sino de tres capas superpuestas: logs, métricas y trazas. Cada una resuelve una dimensión distinta.

Primera capa: de logs caóticos a registros estructurados

¿Has visto los logs en bruto de un Agent? Fragmentos de texto generados por el LLM mezclados con stack traces, timestamps dispersos. Sirven para «arqueología» a posteriori, no para monitorización en tiempo real.

La clave de los logs estructurados es etiquetar cada entrada: Agent ID, task ID, estado actual, resumen de entrada y salida. Con esos campos puedes agregar por tarea, filtrar por estado y ordenar por tiempo.

# Ejemplo de logs estructurados
import structlog

logger = structlog.get_logger()

def log_agent_step(agent_id: str, task_id: str, state: str, input: dict, output: dict):
    logger.info(
        "agent_step",
        agent_id=agent_id,
        task_id=task_id,
        state=state,
        input_summary=str(input)[:100],  # Truncar para evitar inflación de logs
        output_summary=str(output)[:100],
        timestamp=time.time()
    )

Parece sencillo, pero muchos equipos no lo hacen: vuelcan la salida cruda del LLM al log y esperan que grep saque algo útil. No funciona.

Segunda capa: métricas específicas del Agent

Las métricas responden al análisis de tendencias. Un log te dice que una tarea falló; una métrica te dice que la tasa de fallo está subiendo.

Un Agent necesita cuatro tipos de métricas clave:

Tipo de métricaMétricas concretasUmbral de alerta sugerido
Consumo de tokensTotal, por tarea, por llamada a herramientaPor tarea > 10 000 tokens
LatenciaP50, P99, tiempo de llamada a herramientaP99 > 30 s
Tasa de errorFallos de tarea, fallos de herramienta, éxito de reintentosTasa de fallo > 20 %
CostoCosto por tarea, costo diario totalAumento diario del 50 %

El Dashboard de LangSmith es un buen ejemplo: muestra estas métricas agrupadas por Agent y permite bajar al detalle de cada tarea. Los umbrales deben basarse en datos históricos, no en suposiciones. Ejecuta una semana, calcula el rango normal y fija umbrales en torno al 1,5× del límite superior.

Tercera capa: estándar de trazas OpenTelemetry

Las trazas resuelven la reconstrucción de la cadena. Una Trace empieza en la petición del usuario, pasa por reconocimiento de intención, selección de herramienta, ejecución y validación, hasta la salida final. Cada etapa es un Span con timestamp, estado e entrada/salida.

OpenTelemetry se consolida como estándar de la industria. El blog de PredictionGuard señala que unifica el formato de trazas entre frameworks y herramientas. Los principales frameworks de Agent ya lo soportan: Pydantic AI, smolagents, Strands Agents y LangGraph.

# Ejemplo de trazas OpenTelemetry
from opentelemetry import trace
from opentelemetry.sdk.trace.export import ConsoleSpanExporter

tracer = trace.get_tracer("agent_tracer")

async def run_agent_with_trace(task: str):
    with tracer.start_as_current_span("agent_task") as span:
        span.set_attribute("task_input", task)
        
        # Reconocimiento de intención
        with tracer.start_as_current_span("intent_detection") as intent_span:
            intent = await detect_intent(task)
            intent_span.set_attribute("intent_result", intent)
        
        # Llamada a herramienta
        with tracer.start_as_current_span("tool_call") as tool_span:
            result = await call_tool(intent)
            tool_span.set_attribute("tool_result", str(result)[:200])
        
        span.set_attribute("final_output", result)
        return result

Langfuse y LangSmith soportan importación OpenTelemetry. Puedes recoger trazas con una solución open source e importarlas a una plataforma comercial para visualización y análisis, evitando depender de un solo proveedor.

La ventaja de las tres capas: logs para el detalle, métricas para la tendencia, trazas para la visión global. No pierdes ninguna dimensión.

Capítulo 3: Diseño de máquina de estados — el patrón que hace observable el fallo

El problema del God Prompt es, en esencia, «todo en una olla». Toda la lógica mezclada: cuando algo falla, no sabes qué tramo se rompió. La máquina de estados divide esa olla grande en una cadena de ollas pequeñas.

El blog de ArizenAI cifra la reducción de costo de inferencia en un 80 % con máquina de estados. ¿Cómo? Cada estado hace una sola cosa; el LLM no tiene que razonar desde cero en cada paso.

Máquina de estados vs God Prompt: diferencias de fondo

DimensiónGod PromptMáquina de estados
TesteabilidadImposible unit testCada estado se prueba por separado
DepurabilidadLocalización vaga del falloLímites de estado claros
Control de costoRazona todo el prompt cada vezSolo la parte necesaria del estado actual
Manejo de erroresOculto en el promptTyped transitions con rutas explícitas

Estructura típica de máquina de estados para Agent:

[Inicialización] → [Reconocimiento de intención] → [Selección de herramienta] → [Ejecución] → [Validación] → [Completado]
         ↘            ↗
           [Manejo de errores]

ArizenAI recomienda entre 5 y 12 estados. Menos, y vuelves al God Prompt; más, y las transiciones se complican demasiado. Cada estado debe tener tipos de entrada y salida bien definidos — eso son las Typed transitions.

# Ejemplo de definición de estados (pseudocódigo)
from typing import TypedDict, Literal

class IntentState(TypedDict):
    task_input: str
    intent_type: Literal["query", "action", "clarify"]

class ToolState(TypedDict):
    intent: IntentState
    selected_tool: str
    tool_params: dict

class ErrorState(TypedDict):
    failed_state: str
    error_type: str
    retry_count: int

# Transición de estado: ruta de error explícita
def transition_from_intent(intent: IntentState) -> ToolState | ErrorState:
    try:
        tool = select_tool(intent)
        return {"intent": intent, "selected_tool": tool, "tool_params": {}}
    except IntentError as e:
        return {"failed_state": "intent", "error_type": "ambiguous", "retry_count": 0}

Puntos de monitorización por estado

La máquina de estados convierte cada estado en una unidad natural de monitorización. No hace falta bucear en logs caóticos: miras las métricas por estado.

  • Estado de inicialización: hora de inicio de tarea, resultado de comprobación de integridad de entrada
  • Estado de reconocimiento de intención: distribución de tipos de intención, tiempo de reconocimiento, tasa de ambigüedad
  • Estado de selección de herramienta: frecuencia de llamadas, tiempo de selección, tasa sin herramienta coincidente
  • Estado de ejecución: tiempo de ejecución, tasa de éxito, distribución de tipos de fallo
  • Estado de validación: tasa de aprobación, intentos de corrección
  • Estado de manejo de errores: distribución de tipos de error, éxito de reintentos, activaciones de degradación

Con estas métricas ves de un vistazo qué tramo falla. ¿El reconocimiento de intención pasa de 2 s a 10 s? Puede que el prompt sea demasiado largo. ¿La tasa de fallo de herramientas sube del 5 % al 30 %? Quizá un API externo esté caído.

La máquina de estados afina la granularidad de la monitorización: de «toda la tarea» a «cada paso». Eso es más efectivo que cualquier regla de alerta, porque localizar el problema forma parte de la monitorización.

Capítulo 4: Práctica de ingeniería para recuperación de fallos

La monitorización detecta; la recuperación resuelve. Pero recuperar no es solo «reintentar»: un reintento ciego puede empeorar las cosas.

Clasificación de errores: no todos los fallos son iguales

En los proyectos que he visto, los errores se reparten en tres categorías:

TipoProporciónCaracterísticasTratamiento
Transitorios~60 %Timeout de API, inestabilidad del servicio, rate limitReintento con backoff exponencial (máx. 5 veces)
Lógicos~30 %Formato de parámetros incorrecto, herramienta inexistente, intención ambiguaAutorreflexión + ajuste de estrategia
En cascada~10 %Caída de servicio core, error de configuraciónBloqueo + degradación

Datos de Alibaba Cloud indican que un mecanismo de reintento bien diseñado puede subir la tasa de éxito de API del 85 % al 99,5 %. Pero tiene que ser «bien diseñado».

Trampa del reintento: Context Contamination

Un artículo de Arxiv de mayo de 2026 describe un fenómeno contraintuitivo: reintentar a ciegas suele bajar la tasa de éxito.

¿Por qué? La información del fallo «contamina» el razonamiento posterior.

Imagina: el Agent llama a la herramienta A y falla; el error se añade al historial. El Agent ve el error e infiere «la herramienta A falla, pruebo la B». La B también falla. Con dos fallos en el historial, puede concluir «la tarea es demasiado compleja, la abandono».

Eso es Context Contamination: el fallo altera la ruta de razonamiento y empuja intentos posteriores hacia abandonar o elegir estrategias erróneas.

La solución es el aislamiento de estado. Cada reintento no debe heredar todo el historial de fallos, sino reiniciar desde un «estado limpio». O bien comprimir el fallo en un resumen estructurado antes del reintento, en lugar del stack trace crudo.

# Ejemplo de reintento con aislamiento de estado
async def retry_with_clean_state(task: str, error: AgentError, max_retries: int = 3):
    for attempt in range(max_retries):
        # No pasar el historial completo de fallos, solo un resumen estructurado
        error_summary = {
            "type": error.type,
            "failed_step": error.step,
            "hint": get_recovery_hint(error)
        }
        
        result = await run_agent_state(
            start_state="error_recovery",
            context={"original_task": task, "error_summary": error_summary}
        )
        
        if result.success:
            return result
    
    return {"status": "failed", "reason": "max_retries_exceeded"}

Degradación: admitir el fallo y salir con elegancia

Algunos errores no se recuperan solos. Tras 3-5 fallos consecutivos, toca degradar.

Estrategias según el escenario:

  • Simplificar la tarea: dividir en una versión más simple y devolver resultado parcial
  • Solicitar intervención humana: pausar la tarea y avisar a operaciones o al usuario
  • Respuesta de respaldo: devolver una respuesta genérica predefinida para no cortar la experiencia

NIST SP 800-61 Rev. 3 (actualización de 2025) define seis funciones de respuesta a incidentes: Govern (gobernanza), Identify (identificación), Protect (protección), Detect (detección), Respond (respuesta) y Recover (recuperación). Nació como marco de ciberseguridad, pero encaja en la operación de sistemas Agent.

Mapeo al Agent:

  • Govern: umbrales de fallo, estrategias de degradación, responsabilidades
  • Identify: clasificar tipos de error, rastrear cadenas de fallo
  • Protect: estrategias de degradación predefinidas, circuit breaker
  • Detect: monitorización en tiempo real, detección de anomalías
  • Respond: activar reintento o degradación, registrar el incidente
  • Recover: restaurar servicio normal, retrospectiva y mejora

La ventaja del marco: trata la recuperación como un flujo completo, no como un parche de última hora.

Capítulo 5: Casos prácticos y herramientas recomendadas

La teoría está clara; lo difícil es llevarlo a producción. Aquí van integraciones concretas.

Monitorización LangGraph + Langfuse

LangGraph soporta OpenTelemetry de forma nativa; conectar Langfuse requiere pocas líneas:

from langfuse import Langfuse
from langfuse.callback import CallbackHandler

langfuse_handler = CallbackHandler(
    public_key="pk-xxx",
    secret_key="sk-xxx",
    host="https://cloud.langfuse.com"
)

# Inyectar callback al compilar LangGraph
agent = graph.compile()
result = agent.invoke(
    {"input": task},
    config={"callbacks": [langfuse_handler]}
)

Langfuse recoge automáticamente trazas de cada nodo: entrada, salida, latencia y consumo de tokens. En el Dashboard puedes ver la cadena completa por task ID.

Endpoint de health check en CrewAI

CrewAI no trae monitorización integrada; conviene diseñar un endpoint de health check:

from fastapi import FastAPI
from crewai import Crew

app = FastAPI()

@app.get("/health")
async def health_check():
    # Comprobar tasa de éxito de las últimas 100 tareas
    recent_tasks = get_recent_tasks(limit=100)
    success_rate = sum(1 for t in recent_tasks if t.status == "success") / len(recent_tasks)
    
    return {
        "status": "healthy" if success_rate > 0.8 else "degraded",
        "success_rate": success_rate,
        "last_error": recent_tasks[-1].error_summary if recent_tasks[-1].status == "failed" else None
    }

Este endpoint puede integrarse con los health checks de Kubernetes o alimentar el sistema de alertas.

Matriz de herramientas recomendadas

EscenarioHerramientaCaracterísticasEquipo ideal
TrazasLangfuseOpenTelemetry nativo, open source, self-host opcionalEquipos que necesitan despliegue personalizado
MonitorizaciónLangSmithOficial de LangChain, alertas madurasEquipos en LangChain/LangGraph
LogsLoki + GrafanaBajo costo, amigable con K8s, infra existenteDespliegues grandes, presupuesto ajustado
Detección de anomalíasLuna-2 (modelo pequeño)Patrones de fallo específicos de Agent, buen filtrado de ruidoEquipos ahogados en alertas ruidosas

El blog de PredictionGuard señala que modelos pequeños como Luna-2 entienden patrones de fallo propios de Agent mejor que umbrales fijos. Si tu panel dispara decenas de alertas al día y el 90 % es ruido, merece la pena probarlos.

Conclusión

¿Cuánto cambia un sistema completo de monitorización para Agent?

DimensiónSin monitorizaciónCon monitorización
LocalizaciónRevisar logs, mucho tiempoPor estado, respuesta en segundos
RecuperaciónReintento ciego, baja tasa de éxitoTratamiento por categoría, recuperación dirigida
Calidad de alertasRuido masivo, causa raíz enterradaAgregación con filtrado, señal clara
Mejora del AgentAjustar parámetros a ojoOptimización basada en datos

Del God Prompt a la máquina de estados, de logs caóticos a trazas OpenTelemetry, del reintento ciego al aislamiento de estado — este cambio no es un «extra», es el camino obligatorio para llevar un Agent a producción.

Si aún sostienes todo el Agent con un prompt gigante, empieza hoy a dividir estados: 5-12 discretos, una responsabilidad cada uno, rutas de fallo explícitas.

Si aún no tienes OpenTelemetry, el momento es ahora. Los frameworks principales ya lo soportan; Langfuse y LangSmith importan trazas directamente.

Reintentar no es la panacea. Context Contamination hunde más a quien solo reintenta. Diseña aislamiento de estado: esa es la vía correcta.

La industrialización del Agent nunca fue «escribir un buen prompt y listo». Monitorización y recuperación son el paso que lo hace realmente controlable.

Construir un sistema de observabilidad para AI Agent

Montaje completo del sistema de monitorización, del registro de logs a la máquina de estados

⏱️ Estimated time: 45 min

  1. 1

    Step 1: Diseñar un formato de logs estructurados

    Etiqueta cada log con Agent ID, task ID, estado actual y resumen de entrada/salida. Usa bibliotecas como structlog para unificar el formato y trunca textos largos para evitar la inflación de logs.
  2. 2

    Step 2: Configurar las métricas clave del Agent

    Monitoriza consumo de tokens (umbral por tarea: 10 000), latencia (P99: 30 s), tasa de error (umbral de fallos: 20 %) y costo (aumento diario del 50 %).
  3. 3

    Step 3: Integrar trazas OpenTelemetry

    Define un Span en cada etapa, desde la petición del usuario hasta la salida final. Frameworks como LangGraph y Pydantic AI ya lo soportan de forma nativa; importa los datos a Langfuse o LangSmith para visualizarlos.
  4. 4

    Step 4: Dividir la arquitectura en máquina de estados

    Divide el God Prompt en 5-12 estados discretos, cada uno con una sola responsabilidad, y define rutas de error explícitas con Typed transitions.
  5. 5

    Step 5: Implementar clasificación y recuperación de errores

    Errores transitorios: reintento con backoff exponencial (máx. 5 veces). Errores lógicos: autorreflexión. Errores en cascada: bloqueo y degradación. Cada reintento usa aislamiento de estado para evitar Context Contamination.

FAQ

¿Por qué la monitorización tradicional falla con los Agent?
La ruta de ejecución de un Agent se genera de forma dinámica: la misma tarea puede seguir caminos distintos en cada intento. La monitorización tradicional depende de cadenas fijas y no puede rastrear decisiones no deterministas. Además, el God Prompt concentra toda la lógica en un solo prompt, así que cuando falla no puedes localizar el paso concreto.
¿Cómo reduce el patrón de máquina de estados el costo de inferencia?
Cada estado hace una sola cosa; el LLM no tiene que razonar toda la lógica desde cero en cada paso. Según datos de ArizenAI, la máquina de estados puede reducir hasta un 80 % el costo de inferencia. Además, cada estado se prueba de forma independiente y los fallos se localizan con precisión.
¿Qué es Context Contamination?
La información del fallo contamina el razonamiento posterior. Si una llamada a herramienta falla, el error se añade al historial de conversación y el Agent puede inferir una estrategia incorrecta o abandonar la tarea. La solución es reintentar con aislamiento de estado, sin heredar todo el historial de fallos.
¿Cómo diseñar umbrales de alerta para Agent?
Ejecuta una semana para recopilar datos base, calcula el rango normal y fija umbrales en torno al 1,5× del límite superior habitual. Evita fijarlos a ojo: umbrales demasiado bajos generan ruido; demasiado altos, se pierden problemas reales.
¿OpenTelemetry o LangSmith?
Si necesitas despliegue personalizado, elige Langfuse (open source). Si usas el ecosistema LangChain/LangGraph, LangSmith (integración de alertas más madura). Ambos soportan importación y exportación OpenTelemetry y evitan el vendor lock-in.
¿Qué hacer cuando el reintento también falla?
Tras 3-5 fallos consecutivos, activa la degradación: simplifica la tarea y devuelve un resultado parcial, solicita intervención humana o responde con un mensaje de respaldo para no romper la experiencia. El marco NIST SP 800-61 recomienda tratar la recuperación como un flujo completo, no como un parche temporal.

13 min de lectura · Publicado el: 27 may 2026 · Actualizado el: 21 ago 2026

Comentarios

Inicia sesión con GitHub para dejar un comentario

Easton BlogEaston Blog