En 2005, cuando administraba el cyber café a los 14 años, aprendí algo que no venía en ningún manual: las métricas mienten cuando medís lo que es fácil de medir, no lo que importa. El dueño me pedía un reporte semanal de "máquinas usadas por hora". El número era perfecto todos los viernes. Y cada dos meses igual se caía la red completa porque nadie estaba midiendo la calidad de las conexiones, solo la cantidad. Hoy que leo cómo reventaron los benchmarks top de agentes de IA, me acuerdo de esos reportes hermosos y completamente inútiles.
El paper que no podía ignorar sobre AI agent benchmarks
Score 379 en Hacker News. Eso no pasa con cualquier cosa. El paper en cuestión documenta cómo investigadores lograron que agentes que dominaban benchmarks de referencia — SWE-bench, WebArena, y otros que el ecosistema usa como vara — colapsaran con modificaciones mínimas al entorno de evaluación.
No hablamos de jailbreaks elaborados ni de prompt injection sofisticada. Hablamos de cosas como:
- Cambiar el nombre de variables en el repositorio de prueba
- Agregar archivos README con información levemente contradictoria
- Modificar el orden de los tests sin cambiar la lógica
- Introducir dependencias nuevas que no afectan el resultado esperado
El benchmark se rompe. El score se desploma. El agente que "resolvía" el 45% de los issues de SWE-bench de repente resuelve el 12%.
Y acá está la parte que me cayó como un balde de agua fría: eso no es un bug del benchmark. Es el benchmark funcionando correctamente por primera vez.
Lo que los benchmarks originales medían no era capacidad de resolución de problemas. Medían memorización del entorno de evaluación disfrazada de razonamiento.
Dónde me hubieran roto mis propios agentes
Hace unas semanas escribí sobre Research-Driven Agents — la idea de que un agente que lee antes de codear produce resultados más confiables. Lo sigo sosteniendo. Pero leer el paper me obligó a hacer un ejercicio incómodo: ¿qué pasa si aplico las mismas roturas a mi propio setup?
Mi arquitectura actual para agentes de investigación y generación de código tiene más o menos esta forma:
// Estructura simplificada del pipeline de Research-Driven Agent
interface ResearchAgentConfig {
// El agente primero lee contexto, después actúa
researchPhase: {
maxTokensContext: number; // cuánto contexto puede procesar
sourceValidation: boolean; // ¿verifica las fuentes que usa?
contradictionDetection: boolean; // ¿detecta info contradictoria?
};
actionPhase: {
groundingRequired: boolean; // ¿cada acción necesita justificación en el contexto?
rollbackCapability: boolean; // ¿puede deshacer si detecta error?
};
}
// Lo que YO tenía configurado (con honestidad brutal)
const miConfigActual: ResearchAgentConfig = {
researchPhase: {
maxTokensContext: 8000,
sourceValidation: false, // acá me rompían
contradictionDetection: false, // acá también
},
actionPhase: {
groundingRequired: true, // esto estaba bien
rollbackCapability: false, // esto era un problema
},
};
Los dos false en researchPhase son exactamente el vector de ataque que describe el paper. Si le metés al agente contexto contradictorio — un README que dice una cosa y los tests que esperan otra — no tiene mecanismo para detectar la contradicción. Elige una fuente arbitrariamente (casi siempre la más reciente en el contexto) y avanza con confianza.
Eso en un benchmark se manifiesta como score bajo. En producción se manifiesta como un PR que parece razonable pero está construido sobre un supuesto incorrecto. Y como aprendí cuando revisé esos PRs vibe-coded — el problema no es que la IA se equivoque. El problema es que yo los aprobaba.
Los tres patrones de rotura que ahora busco activamente
1. Overfitting al entorno de evaluación
El más documentado en el paper. El agente aprende los patrones específicos del benchmark — nombres de archivos, estructura de repositorios, formato de tests — y optimiza para esos patrones en vez de para el problema subyacente.
En mis agentes esto aparece como dependencia al scaffolding. Si el agente siempre trabaja con repos estructurados de la misma manera (cosa que pasa cuando usás los mismos templates), empieza a asumir esa estructura en vez de inferirla.
// Trampa común: el agente asume estructura en vez de explorarla
async function analizarRepositorio(path: string) {
// MAL: asumir que siempre existe este archivo
const config = await readFile(`${path}/src/config/index.ts`);
// BIEN: explorar la estructura real antes de actuar
const estructura = await explorarArbol(path, { profundidad: 3 });
const archivoConfig = encontrarConfigProbable(estructura);
if (!archivoConfig) {
// manejar la ausencia explícitamente
return { error: 'estructura_no_reconocida', estructura };
}
return await readFile(archivoConfig);
}
2. Métricas de proceso vs. métricas de resultado
Este me dolió más porque es el error del cyber café, treinta años después.
Los benchmarks de agentes miden frecuentemente si el agente ejecutó los pasos correctos — llamó a la herramienta adecuada, generó el formato esperado, completó la secuencia en orden. No miden si el resultado es correcto en un sentido robusto.
Mis propios dashboards tenían el mismo problema. Estaba midiendo "tasa de completitud de tareas" (¿el agente terminó sin errores?) en vez de "tasa de corrección de outputs" (¿el resultado es válido bajo perturbaciones mínimas?).
Esto conecta directamente con algo que mencioné en el contexto de contribuir al kernel de Linux con IA: el kernel tiene reviewers humanos que hacen exactamente esto — intentan romper el código con casos edge antes de aceptarlo. Los agentes de IA todavía no tienen ese adversario incorporado.
3. Context poisoning sin detección
El más peligroso en producción. Si el agente procesa fuentes externas — documentación, issues, PRs anteriores — y alguna de esas fuentes tiene información incorrecta o desactualizada, el agente la incorpora sin marcarla.
// Sistema básico de detección de contradicciones en contexto
interface ContextoFuente {
contenido: string;
timestamp: Date;
confianza: 'alta' | 'media' | 'baja';
origen: 'documentacion_oficial' | 'issue' | 'pr' | 'readme' | 'test';
}
async function detectarContradicciones(
fuentes: ContextoFuente[]
): Promise<ContradiccionDetectada[]> {
const contradicciones: ContradiccionDetectada[] = [];
// Jerarquía de confianza: tests > código > docs > issues
// Si una fuente de menor jerarquía contradice una de mayor jerarquía, flag
const jerarquia = {
'test': 4,
'documentacion_oficial': 3,
'readme': 2,
'pr': 1,
'issue': 0
};
for (let i = 0; i < fuentes.length; i++) {
for (let j = i + 1; j < fuentes.length; j++) {
const similitud = await compararSemantico(fuentes[i].contenido, fuentes[j].contenido);
if (similitud.contradiccion && similitud.confianza > 0.8) {
contradicciones.push({
fuente_a: fuentes[i],
fuente_b: fuentes[j],
descripcion: similitud.descripcion,
// la fuente de mayor jerarquía gana, pero registramos el conflicto
recomendacion: jerarquia[fuentes[i].origen] > jerarquia[fuentes[j].origen]
? 'usar_fuente_a'
: 'usar_fuente_b'
});
}
}
}
return contradicciones;
}
Esto no es ciencia de cohetes, pero requiere pensar activamente en el agente como un sistema que puede ser envenenado — no solo como un sistema que puede equivocarse.
Los errores que veo en stacks de agentes típicos
Evaluar en el mismo entorno donde entrenás el prompt. Si afinás el prompt del agente sobre los mismos ejemplos que después usás para medir, estás recreando exactamente el overfitting del paper. El benchmark y el agente se entrenan juntos sin que nadie lo note.
Medir latencia y costo pero no robustez. El dashboard tiene p95 de respuesta, costo por token, tasa de error de API. No tiene "¿qué pasa si el input tiene un campo vacío inesperado?". Eso no es un problema de monitoreo — es un problema de qué decisiones tomás con las métricas que sí tenés.
Asumir que más contexto es siempre mejor. El paper documenta casos donde darle al agente más información del repositorio empeoró el performance porque introdujo ruido contradictorio. Más contexto sin filtrado es context poisoning en slow motion.
Esto también aplica a infraestructura más amplia — cuando Francia migra a Linux o cuando pensamos en el futuro de Git con agentes, el problema de fondo es el mismo: ¿qué garantías tenemos de que el sistema se comporta bajo condiciones que no anticipamos?
FAQ: AI agent benchmarks y lo que realmente miden
¿Qué son exactamente los AI agent benchmarks más usados?
SWE-bench es el más citado — mide si un agente puede resolver issues reales de GitHub en repositorios de Python conocidos. WebArena mide navegación web y completitud de tareas. HumanEval mide generación de código contra tests unitarios. El problema común: todos miden performance en entornos fijos y conocidos, no robustez ante variación.
¿Por qué un agente con 45% en SWE-bench puede bajar al 12% con cambios mínimos?
Porque el agente aprendió patrones del entorno de evaluación específico — estructura de repositorios, nombres de archivos, formato de tests — no el problema general de "resolver un bug". Cuando cambiás esos patrones sin cambiar el problema, el agente pierde el ancla que usaba para navegar.
¿Esto invalida los benchmarks como herramienta?
No los invalida, los recontextualiza. Un benchmark sigue siendo útil para comparar modelos bajo condiciones controladas idénticas. El error es interpretarlo como proxy de capacidad real en producción. Son termómetros calibrados para un rango específico — no para toda la fiebre.
¿Cómo evalúo la robustez de mis propios agentes sin un laboratorio de investigación?
Tres técnicas accesibles: perturbación de input (cambiar nombres de variables, orden de campos, formato de respuestas esperadas), inyección de contradicción (agregar información levemente incorrecta al contexto y medir si el agente la detecta o la incorpora sin cuestionar), y evaluación adversarial simple (pedirle a alguien que no construyó el agente que intente romperlo con inputs razonables pero inusuales).
¿Los modelos más nuevos son inmunes a este problema?
No. El paper incluye modelos de frontera — GPT-4o, Claude 3.5, Gemini 1.5 — y todos muestran degradación ante perturbaciones. La diferencia es de magnitud, no de presencia del problema. Modelos más grandes degradan menos bruscamente pero degradan igual.
¿Qué cambio concreto debería hacer primero en mi stack?
Separar el entorno de desarrollo de prompts del entorno de evaluación. Si estás afinando un agente sobre los mismos ejemplos que después medís, empezá por ahí. Segundo: agregar al menos un test de perturbación mínima en tu pipeline de CI — un input que sea levemente distinto al caso happy path pero igualmente válido. Si el agente falla ahí, el problema es más profundo que el prompt.
La conclusión incómoda
El problema no son los benchmarks rotos. El problema es que los usábamos como excusa para no pensar en robustez.
Cuando un agente tiene 67% en SWE-bench, eso se convierte en el argumento de venta, el criterio de adopción, la razón para construir encima. Nadie pregunta "¿67% bajo qué condiciones?". Nadie pregunta qué pasa cuando las condiciones cambian aunque sea un poco.
Yo lo hice. Elegí herramientas y diseñé pipelines parcialmente basado en scores de benchmarks que ahora sé que eran frágiles. No fue negligencia — fue falta de información y, seré honesto, un poco de pereza epistémica. Es más cómodo confiar en el número que diseñar tus propios tests de rotura.
Lo que cambié en mi stack desde que leí el paper: agregué un paso de contradicción detection en el contexto de los agentes de investigación, separé los ejemplos de desarrollo de los de evaluación, y empecé a medir "robustez ante perturbación mínima" junto con las métricas de completitud que ya tenía.
No es una solución completa. Es un comienzo honesto.
¿Vos ya tenés algún test de robustez en tus agentes, o también estás midiendo solo lo que es fácil de medir? Escribime — me interesa saber si alguien encontró una manera sistemática de hacer esto que no requiera un equipo de investigación.
Este artículo fue publicado originalmente en juanchi.dev
Top comments (0)