AI Agents: El 99% de los Tests Unitarios No Detecta el Fallo Real — Cómo Construir un Evaluation Harness que Mida lo que Importa
Los AI Agents fallan de forma silenciosa: decisiones incorrectas con alta confianza que ningún test unitario detecta. Construye un evaluation harness de 4 buckets para medir precisión, confianza y coste real.
Tu AI Agent No Está Fallando Cuando Lancea una Excepción. Está Fallando Cuando Escribe una Respuesta Perfecta que Es Completamente Incorrecta.
Y ningún test unitario del mundo va a detectarlo.
La industria asume que los AI Agents se evalúan como software tradicional: más tests = más calidad. Escribís tests unitarios. Probáis funciones helper. Validáis que el JSON parsea bien. Y cuando todo pasa, asumís que el agent funciona.
*Pero un AI Agent que pasa todos los tests unitarios puede estar tomando decisiones catastróficas con un 95% de confianza. *
El problema no es que fallen. Es que fallan bien. Con buena gramática. Con paso seguro. Sin lanzar ninguna excepción que un try-catch pueda atrapar.
Bienvenidos al verdadero problema de evaluar AI Agents en 2026.
---
Por Qué el Try-Catch Es un Error Categorial
El try-catch fue diseñado para errores de runtime. Null pointers. Timeouts. Conexiones fallidas. Excepciones que rompen el flujo de ejecución.
Pero un AI Agent que decide incorrectamente no lanza una excepción. Ejecuta código perfectamente válido que lleva a una decisión equivocada.
Piénsalo así: un conductor con GPS toma la salida equivocada en una autopista. El coche funciona perfectamente. El GPS da indicaciones claras. No hay ningún error en el sistema. Pero el destino es otro.
El software tradicional confunde "funcionar sin errores" con "funcionar correctamente". Para AI Agents, esas dos cosas no tienen correlación.
Veámoslo con código:
```python
❌ TEST UNITARIO TRADICIONAL — Este test lo pasa el agent
def test_get_user_email():
agent = CustomerSupportAgent()
result = agent.get_user_email("user_123")
assert result is not None # ✅ Pasa: devolvió un string
assert "@" in result # ✅ Pasa: tiene formato de email
✅ EVALUATION REAL — Esto es lo que el test unitario NO ve
def evaluate_agent_decision():
agent = CustomerSupportAgent()
El agent devuelve un email que NO existe en la base de datos
pero con formato perfectamente válido
result = agent.get_user_email("user_123")
result = "soporte@noexiste.com" — formato perfecto, dato incorrecto
real_email = query_database("SELECT email FROM users WHERE id = 'user_123'")
real_email = "maria@empresa.com"
assert result == real_email # ❌ FALLA: el dato es incorrecto
Pero ningún test unitario comprueba esto
```
El primer test pasa. El segundo test es el que realmente importa. Y el 99% de los equipos solo escribe el primero.
---
El Peligro de la Alta Confianza en Decisiones Incorrectas
Los modelos de lenguaje generan tokens con probabilidades asociadas (logprobs). Cuando un modelo produce una respuesta con alta probabilidad en cada token, internamente "cree" que está en lo correcto.
Esto es análogo a un empleado que nunca duda de sí mismo pero se equivoca sistemáticamente. En evaluación de agents, el peor escenario no es el agent que duda (fallo visible, fácil de atrapar). Es el que ejecuta con convicción una acción dañina.
| Nivel de Confianza | Decisión Correcta | Decisión Incorrecta |
|-------------------|-------------------|-------------------|
| Confianza Alta | El agente funciona. Todo bien. | ⚠️ PELIGRO: Modo de fallo invisible. El agent actúa sin dudar. |
| Duda/Baja | El agente funciona pero es ineficiente. Pide clarificación constante. | El agente duda. El fallo es detectable. Se puede intervenir. |
El bucket crítico es "incorrecto + confianza alta". Fallos invisibles que el agente ejecutará sin dudar. No hay log. No hay error. No hay excepción. Solo una decisión equivocada ejecutada con total convicción.
---
El Sistema de 4 Buckets: Tu Evaluation Harness para AI Agents
Construí esto después de ver cómo agents en producción tomaban decisiones dañinas sin que nadie pudiera detectarlo a tiempo. No es teoría. Es el harness que uso hoy en producción.
El sistema clasifica cada acción del agent en una matriz 2x2 y te permite ver exactamente dónde está fallando tu sistema.
Bucket 1 — Taxonomía de Fallos Específica de tu Dominio
No todos los fallos son iguales. Tienes que definir los tuyos:
Errores de hecho: información incorrecta (el agent dijo que la empresa está en Madrid cuando está en Barcelona)
Errores de procedimiento: paso incorrecto en un workflow (cerró un ticket sin asignarlo)
Errores de alucinación: información inventada (creó un cliente que no existe)
Errores de omisión: no hacer algo que debía hacerse (no envió el email de confirmación)
```python
Taxonomy of failures — domain-specific
class FailureTaxonomy:
FACTUAL = "factual_error" # Wrong information
PROCEDURAL = "procedural_error" # Wrong step in workflow
HALLUCINATION = "hallucination" # Invented information
OMISSION = "omission_error" # Didn't do what was needed
NONE = "no_error" # Correct execution
```
Bucket 2 — Medir Confianza vs Precisión
Extrae los logprobs del modelo en cada respuesta y crúzalos con la corrección factual de la acción:
```python
import openai
import numpy as np
class ConfidenceAccuracyTracker:
def __init__(self):
self.results = [] # (confidence, accuracy, decision_id)
def evaluate_decision(self, prompt, expected_action, agent_response):
Extraer logprobs de la respuesta del modelo
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
logprobs=True,
top_logprobs=5
)
Calcular confianza media de los tokens
token_logprobs = []
for token_data in response.choices[0].logprobs.content:
token_logprobs.append(token_data.logprob)
avg_confidence = np.exp(np.mean(token_logprobs)) # Convertir logprob a probabilidad
Evaluar precisión de la decisión
is_correct = self._check_accuracy(agent_response, expected_action)
self.results.append({
"confidence": avg_confidence,
"accuracy": 1.0 if is_correct else 0.0,
"bucket": self._classify_bucket(avg_confidence, is_correct),
"decision_id": str(uuid.uuid4())[:8]
})
return self.results[-1]
def _classify_bucket(self, confidence, is_correct):
if is_correct and confidence > 0.85:
return "correcta-confianza" # ✅ El mejor caso
elif is_correct and confidence <= 0.85:
return "correcta-duda" # ⚡ Funciona pero ineficiente
elif not is_correct and confidence > 0.85:
return "incorrecta-confianza" # 🚨 PELIGRO: Fallo invisible
else:
return "incorrecta-duda" # ⚠️ Detectable, intervenible
```
Bucket 3 — Logging Estructural de Decisiones
No loguees solo errores. Loguea cada decisión con su contexto completo:
```python
class StructuralDecisionLogger:
def log_decision(self, agent_id, decision_data):
log_entry = {
"timestamp": datetime.utcnow().isoformat(),
"agent_id": agent_id,
"decision": decision_data["action"],
"confidence": decision_data["confidence"],
"tokens_consumed": decision_data["tokens"],
"latency_ms": decision_data["latency_ms"],
"human_in_the_loop": decision_data.get("required_human", False),
"bucket": decision_data["bucket"],
"expected_vs_actual": {
"expected": decision_data["expected"],
"actual": decision_data["actual"]
}
}
Enviar a tu sistema de logging (Datadog, Grafana, etc.)
self._send_to_logging_pipeline(log_entry)
Alarma automática si el agent está en bucket peligroso
if decision_data["bucket"] == "incorrecta-confianza":
self._trigger_alert(log_entry)
```
Bucket 4 — Dashboard de 4 Cuadrantes
Creas un dashboard que clasifica cada ejecución en tiempo real y te permite ver patrones:
```
CONFIANZA ALTA | CONFIANZA BAJA
─────────────────────────────────────┼───────────────────────────────────
✅ CORRECTO | Ejecuciones óptimas | ⚡ CORRECTO | Ejecuciones válidas
| (mejorar tiempo/coste) | | pero dudosas (ineficiencia)
| | |
| Objetivo: mantener aquí | | Objetivo: aumentar confianza
─────────────────────────────────────┼───────────────────────────────────
❌ INCORRECTO | 🚨 PELIGRO | ❌ INCORRECTO | Fallos detectables
| Fallos invisibles | | El agent duda
| El agent NO duda | | Fácil de intervenir
| | |
| Objetivo: CERO tolerancia | | Objetivo: minimizar
```
Si ves ejecuciones en el cuadrante "incorrecto + confianza alta", tienes un problema de arquitectura, no de modelo. El agent está aprendiendo patrones incorrectos con total seguridad.
---
Cómo Implementarlo en Producción (Sin Morir en el Intento)
Vale, sé lo que estás pensando: "Extraer logprobs y medir confianza es demasiado complejo para producción".
Es cierto que añade complejidad. Pero es la única manera de detectar el modo de fallo más peligroso. Empieza con un submuestreo del 10% de las ejecuciones. No necesitas medir todas.
Usa herramientas que ya soportan esto:
LangSmith: tiene tracing nativo con logprobs y evaluación de decisiones
Weights & Biases: soporta logging de confianza para modelos de lenguaje
MLflow: tracking de experimentos con métricas personalizadas
```python
Production-ready: sample 10% of executions for evaluation
class ProductionEvaluationHarness:
def __init__(self, sample_rate=0.1):
self.sample_rate = sample_rate
self.tracker = ConfidenceAccuracyTracker()
self.logger = StructuralDecisionLogger()
def evaluate(self, agent_decision, expected, agent_id):
Solo evaluamos una muestra para no ralentizar producción
if random.random() > self.sample_rate:
return
result = self.tracker.evaluate_decision(
prompt=agent_decision["prompt"],
expected_action=expected,
agent_response=agent_decision["response"]
)
self.logger.log_decision(agent_id, {
**agent_decision,
"confidence": result["confidence"],
"bucket": result["bucket"],
"expected": expected
})
return result
```
---
Lo que la Gente se Equivoca al Decir (Y la Verdad)
"Pero si mi agent pasa los tests de integración y no lanza errores, está funcionando correctamente."
❌ Falso. Confundes funcionamiento técnico con corrección semántica. Un agent puede ejecutar código perfectamente (sin errores de runtime) mientras toma decisiones lógicamente incorrectas. El código puede ser impecable y la decisión catastrófica.
"Los logs tradicionales ya capturan los errores — solo necesito mejor logging."
❌ Falso. Los logs tradicionales capturan excepciones y errores de sistema. No capturan decisiones incorrectas con alta confianza porque desde la perspectiva del sistema, todo funcionó correctamente. No hay nada que loguear. Necesitas logging semántico que evalúe la corrección de la decisión, no solo la ejecución del código.
"Extraer logprobs y medir confianza es demasiado complejo para producción."
✅ Parcialmente cierto, pero manejable. Añade complejidad, pero es la única defensa contra el modo de fallo más peligroso. Empieza con un submuestreo del 10%. Usa herramientas como LangSmith que ya lo soportan. La alternativa es descubrir el fallo cuando el cliente te lo dice.
---
La Línea de Meta
El 2026 nos ha enseñado algo claro: los AI Agents no son software tradicional. No puedes evaluarlos con las mismas herramientas. Los tests unitarios miden si el código funciona. No miden si la decisión es correcta.
El Sistema de 4 Buckets no es opcional. Es la diferencia entre un agent que parece funcionar y uno que realmente funciona.
Empieza hoy. Define tu taxonomía de fallos. Extrae logprobs. Mide confianza vs precisión. Y pon un dashboard que te muestre dónde están tus agents fallando en silencio.
Porque el AI Agent perfectamente escrito que toma decisiones incorrectas con un 95% de confianza no es un bug. Es una bomba de relojería.
Lee el artículo completo en brianmenagomez.com
Más sobre mis servicios en brianmenagomez.com
Herramientas: Conversor IAE CNAE · Gestorias cerca de ti · Calculadora IRPF

