<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Langfuse on lo0 — Blog Técnico</title><link>https://blog.lo0.es/tags/langfuse/</link><description>Recent content in Langfuse on lo0 — Blog Técnico</description><generator>Hugo -- gohugo.io</generator><language>es</language><lastBuildDate>Wed, 20 May 2026 00:12:00 +0200</lastBuildDate><atom:link href="https://blog.lo0.es/tags/langfuse/index.xml" rel="self" type="application/rss+xml"/><item><title>Evals: la capa después del tracing que decide si tu LLM rinde o sólo parece rendir</title><link>https://blog.lo0.es/posts/evals-llm-la-capa-despues-de-tracing/</link><pubDate>Wed, 20 May 2026 00:12:00 +0200</pubDate><guid>https://blog.lo0.es/posts/evals-llm-la-capa-despues-de-tracing/</guid><description>&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>Tracing te dice &lt;strong>qué ha pasado&lt;/strong> dentro de tu aplicación LLM: qué prompts entraron, qué tokens salieron, qué tools se llamaron. Evals te dice &lt;strong>si eso está bien&lt;/strong>. Son dos capas distintas: no hay overlap, no hay sustitución, hay continuidad. En 2026 el campo se ha estabilizado alrededor de una &lt;strong>arquitectura de dos pisos&lt;/strong>: un framework ligero estilo &lt;code>pytest&lt;/code> (DeepEval, Promptfoo, Ragas) que corre en CI y bloquea el merge si la regresión es seria, y una plataforma de observabilidad (Langfuse, LangSmith, Arize Phoenix, Braintrust) que persiste evaluaciones a largo plazo, permite anotación humana, detecta drift, da dashboard a stakeholders. La técnica dominante es &lt;strong>LLM-as-a-judge&lt;/strong>: un modelo evaluador con una rúbrica determina si la respuesta es buena, &lt;strong>80-90% de acuerdo con humanos a 500-5000x menos coste&lt;/strong> y, calibrado correctamente, en producción. Para RAG hay las cuatro métricas canónicas de Ragas (faithfulness, answer relevancy, context precision, context recall). Para agentes, &lt;strong>trajectory matching&lt;/strong>, accuracy de selección de tools y &lt;strong>pass^k&lt;/strong> —la métrica recién popularizada por Tau-bench que reveló que muchos agentes con pass^1 alto tienen pass^4 hasta 25 puntos por debajo, es decir, son inconsistentes—. Este artículo recorre los seis ángulos: por qué evaluar LLMs es distinto, las cuatro patas de un sistema de evals, LLM-as-a-judge en serio (G-Eval, position bias, calibración), métricas para RAG y agentes, el panorama de herramientas 2026 con sus diferencias reales, y la receta operativa para tener evals que no sean teatro.&lt;/p>
&lt;blockquote>
&lt;p>Este artículo abre la &lt;strong>serie de capas post-tracing&lt;/strong>. Viene encadenado del cierre de la serie eBPF de ayer (&lt;a href="https://blog.lo0.es/posts/agentsight-tracing-llm/">AgentSight y el nuevo tracing de LLMs&lt;/a>), donde quedó apuntado que evals es &amp;ldquo;el mundo aparte que sigue al tracing&amp;rdquo;. Es ese mundo.&lt;/p>
&lt;/blockquote>
&lt;h2 id="la-analogía-el-test-suite-que-tu-pipeline-de-ml-siempre-quiso">La analogía: el test suite que tu pipeline de ML siempre quiso&lt;/h2>
&lt;p>Quien lleve años desarrollando software no encontrará nada raro en la idea de &lt;strong>tests automatizados&lt;/strong>: cada commit dispara una suite que se valida contra outputs esperados, y si algo se rompe, el merge falla. Es lo que separó programar en los 90 de programar en los 2010. Imposible imaginar producción sin esto.&lt;/p>
&lt;p>Cuando llegaron los modelos de Machine Learning clásicos, el patrón se preservó parcialmente: tests de entrada/salida determinista, plus métricas de modelo (accuracy, F1, AUC) sobre un dataset de validación. Imperfecto pero funcionaba; los modelos eran determinísticos y las predicciones tenían &lt;strong>etiquetas claras&lt;/strong>.&lt;/p>
&lt;p>Con los LLMs, el patrón se rompió. ¿Cómo testeas que la respuesta a &amp;ldquo;explícame qué es un transformer&amp;rdquo; es correcta? &lt;strong>No hay una sola respuesta correcta&lt;/strong>, hay una distribución de respuestas razonables. ¿Cómo testeas que un agente eligió la herramienta adecuada para resolver un problema multistep? La función de coste es &lt;strong>subjetiva, dependiente del contexto, y a menudo emerge solo cuando el dominio experto lo mira&lt;/strong>.&lt;/p>
&lt;p>Lo que ha pasado en los últimos tres años es la construcción colectiva del &lt;strong>equivalente al test suite para LLMs&lt;/strong>. Aún imperfecto, aún en evolución, pero ya operacionalmente viable. Las piezas existen: datasets curados, evaluadores que escalan (LLM-as-a-judge), frameworks que corren en CI, plataformas que persisten regresión. Lo que cambia respecto a tests tradicionales es que &lt;strong>el resultado del eval también es probabilístico&lt;/strong>: el judge se puede equivocar; medimos su acuerdo con humanos y aceptamos un umbral. Vivimos con la incertidumbre como parte del sistema.&lt;/p>
&lt;h2 id="por-qué-evaluar-llms-es-estructuralmente-distinto">Por qué evaluar LLMs es estructuralmente distinto&lt;/h2>
&lt;p>Cinco diferencias que cambian todo:&lt;/p>
&lt;p>&lt;strong>No-determinismo.&lt;/strong> Mismo input → distinto output según temperature, top_p, seed. Un test que pasaba ayer puede fallar hoy sin haber tocado nada. La solución no es eliminar el no-determinismo (a veces lo quieres); es &lt;strong>medir en distribución&lt;/strong>, no en una muestra única.&lt;/p>
&lt;p>&lt;strong>No hay golden answer única.&lt;/strong> Para &amp;ldquo;resume este artículo en 3 frases&amp;rdquo;, hay miles de resúmenes válidos. Comparar bit-a-bit con una &amp;ldquo;respuesta correcta&amp;rdquo; es absurdo. Evaluamos &lt;strong>propiedades&lt;/strong> de la respuesta (fidelidad, concisión, no contradicción), no igualdad textual.&lt;/p>
&lt;p>&lt;strong>Métricas clásicas son insuficientes.&lt;/strong> BLEU, ROUGE, BERTScore funcionaban en traducción automática y resumen extractivo. Para generación abierta correlan muy mal con juicio humano. Es famoso el contraejemplo: una respuesta semánticamente correcta puede tener BLEU bajo porque usa otras palabras; una respuesta incorrecta puede tener BLEU alto porque copia tokens del input. Hace falta otra cosa.&lt;/p>
&lt;p>&lt;strong>Coste cuadrático del juicio humano.&lt;/strong> La alternativa obvia —&amp;ldquo;que personas evalúen cada respuesta&amp;rdquo;— escala terriblemente. Una app con 100 conversaciones/día genera 3.000/mes; evaluar cada una requiere horas de un humano caro. Para apps con miles o millones de queries, inviable.&lt;/p>
&lt;p>&lt;strong>Drift en producción.&lt;/strong> El modelo no cambia; el mundo cambia. Cambia el vocabulario de los usuarios, cambia el contenido de los documentos del RAG, cambia el comportamiento de los modelos cuando vendor los actualiza silenciosamente. Sin eval continuo, la app degrada y nadie se entera hasta que un cliente se queja.&lt;/p>
&lt;p>Estos cinco puntos explican toda la arquitectura moderna de evals: necesitamos &lt;strong>automatizar el juicio&lt;/strong> (LLM-as-a-judge), &lt;strong>medir propiedades en distribución&lt;/strong> (no igualdad exacta), &lt;strong>persistir resultados a lo largo del tiempo&lt;/strong> (detección de drift) y &lt;strong>mantener un anclaje humano&lt;/strong> (golden datasets calibrados).&lt;/p>
&lt;h2 id="las-cuatro-patas-de-un-sistema-de-evals">Las cuatro patas de un sistema de evals&lt;/h2>
&lt;p>Cualquier framework moderno gira sobre cuatro componentes:&lt;/p>
&lt;h3 id="1-datasets">1. Datasets&lt;/h3>
&lt;p>Un dataset de evaluación tiene una forma mínima: &lt;strong>lista de entradas + cómo se juzga cada salida&lt;/strong>. Dos modelos:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Dataset con golden output&lt;/strong>: para cada entrada, tienes la respuesta correcta (o una lista de aceptables). El evaluador compara generación con golden. Caso típico: NER, clasificación, traducción.&lt;/li>
&lt;li>&lt;strong>Dataset con criteria&lt;/strong>: para cada entrada, tienes una rúbrica abstracta (&amp;ldquo;la respuesta debe ser factual respecto al contexto&amp;rdquo;, &amp;ldquo;el tono debe ser profesional&amp;rdquo;). No hay golden; el evaluador aplica la rúbrica.&lt;/li>
&lt;/ul>
&lt;p>Los datasets buenos en producción son &lt;strong>mantenidos activamente&lt;/strong>: empiezas con 20-50 ejemplos curados a mano, los etiquetas con resultados deseados, y vas creciendo el dataset con los casos reales que han causado problemas (regression dataset). Después de un año en producción, debería haber &lt;strong>cientos o miles&lt;/strong> de casos, cada uno respaldado por una incidencia o un patrón observado.&lt;/p>
&lt;h3 id="2-evaluators">2. Evaluators&lt;/h3>
&lt;p>Lo que toma generación + criterios y devuelve un score. Cuatro familias:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Determinísticos / heurísticos&lt;/strong>: regex, longitud, presencia de tokens, validación de JSON schema. Rápidos, baratos, pero solo aplicables a propiedades sintácticas.&lt;/li>
&lt;li>&lt;strong>Semánticos clásicos&lt;/strong>: BERTScore, embeddings cosine similarity. Mejor que BLEU para igualdad semántica, pero limitados a &amp;ldquo;comparar contra golden&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>LLM-as-a-judge&lt;/strong>: un modelo —típicamente GPT-4, Claude, o un open-source especializado como Prometheus— recibe generación + criterios y devuelve score. El caballo de batalla del campo en 2026.&lt;/li>
&lt;li>&lt;strong>Humanos&lt;/strong>: la verdad de referencia. Caro, lento, pero indispensable como anclaje (golden set).&lt;/li>
&lt;/ul>
&lt;p>En una pipeline madura, los cuatro coexisten: heurísticos como gate inicial (¿es JSON válido?), semánticos para checks rápidos, LLM-as-judge para la mayoría de evaluación, y humanos en muestreo periódico para calibrar.&lt;/p>
&lt;h3 id="3-runners">3. Runners&lt;/h3>
&lt;p>Ejecutan dataset × evaluators y producen el cuadro de resultados. Lo que en pytest serían &lt;code>pytest --collect-only&lt;/code> + &lt;code>pytest -v&lt;/code>. Las cosas que un runner serio tiene que hacer:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Paralelización&lt;/strong>: cientos de prompts no pueden ejecutarse en serie.&lt;/li>
&lt;li>&lt;strong>Caché&lt;/strong>: si re-ejecutas un eval con el mismo prompt y modelo, no pagar dos veces.&lt;/li>
&lt;li>&lt;strong>Retry y backoff&lt;/strong>: rate limits de las APIs son la norma.&lt;/li>
&lt;li>&lt;strong>Trazabilidad&lt;/strong>: cada run identificado con commit, version del prompt, version del dataset, version del evaluator.&lt;/li>
&lt;li>&lt;strong>Aggregation&lt;/strong>: medias, percentiles, breakdown por segmento.&lt;/li>
&lt;/ul>
&lt;h3 id="4-storage-y-analytics">4. Storage y analytics&lt;/h3>
&lt;p>Un eval que se ejecuta y se imprime en pantalla no sirve. Hay que &lt;strong>persistir resultados a lo largo del tiempo&lt;/strong> para detectar regresión y drift. Aquí entran las plataformas (Langfuse, LangSmith, Phoenix): cada eval-run se guarda con metadata, se puede comparar contra runs anteriores, se generan dashboards.&lt;/p>
&lt;h2 id="llm-as-a-judge-el-caballo-de-batalla">LLM-as-a-judge: el caballo de batalla&lt;/h2>
&lt;p>Esta es la técnica que ha hecho factible eval automático a escala. Vale la pena entender bien cómo funciona y qué problemas tiene.&lt;/p>
&lt;h3 id="el-modelo-básico">El modelo básico&lt;/h3>
&lt;p>Le das al judge un prompt estructurado:&lt;/p>
&lt;pre tabindex="0">&lt;code>You are evaluating the quality of a customer support agent&amp;#39;s response.
User question: &amp;#34;How do I cancel my subscription?&amp;#34;
Agent response: &amp;#34;To cancel, log into your account, go to Settings &amp;gt;
Billing, click Cancel. Note that you&amp;#39;ll retain access until the end
of your current billing period.&amp;#34;
Rubric:
- Accuracy (1-5): Does the response factually answer the question?
- Completeness (1-5): Does it cover all relevant steps?
- Tone (1-5): Is it professional and helpful?
Provide a JSON response with the three scores and a brief justification.
&lt;/code>&lt;/pre>&lt;p>El judge devuelve un JSON. Las tres notas, una justificación corta. Caso resuelto.&lt;/p>
&lt;h3 id="scoring-rubric-vs-pairwise-comparison">Scoring rubric vs pairwise comparison&lt;/h3>
&lt;p>Dos modelos principales:&lt;/p>
&lt;p>&lt;strong>Scoring rubric (absoluto)&lt;/strong>: el judge devuelve un número en una escala (típicamente 0-1, 1-5 o 1-10). Sencillo, ortogonal entre evaluaciones. Pero los modelos LLM &lt;strong>son malos en escalas absolutas&lt;/strong>: tienden a apilarse en valores medios (3-4 en escala 1-5) y a no usar los extremos. Las correlaciones con humanos en scoring absoluto suelen rondar el 0.6-0.7.&lt;/p>
&lt;p>&lt;strong>Pairwise comparison&lt;/strong>: el judge ve &lt;strong>dos respuestas&lt;/strong> (A y B) y elige cuál es mejor. Los modelos son &lt;strong>mucho mejores&lt;/strong> en pairwise que en absoluto; las correlaciones suben a 0.75-0.85. Razón: es la tarea natural de un modelo de lenguaje (modelar relación entre dos cosas), no asignar números abstractos.&lt;/p>
&lt;p>La práctica recomendada: &lt;strong>usar pairwise cuando puedas&lt;/strong>. Para regresión (&amp;quot;¿v4 del prompt mejora sobre v3?&amp;quot;), pairwise es ideal. Para producción (&amp;quot;¿esta respuesta es buena?&amp;quot;), donde no tienes otra contra qué comparar, scoring absoluto con cuidado.&lt;/p>
&lt;h3 id="g-eval-el-patrón-que-más-se-usa">G-Eval: el patrón que más se usa&lt;/h3>
&lt;p>&lt;a href="https://arxiv.org/abs/2303.16634">G-Eval&lt;/a> (Liu et al., NAACL 2023) es el patrón de prompting que más correlación con humanos consigue de los métodos públicos. Tiene tres ingredientes:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Auto-CoT&lt;/strong>: el prompt induce al judge a generar &lt;strong>su propia cadena de razonamiento&lt;/strong> sobre los pasos a evaluar antes de dar nota. No le dices la rúbrica; le pides que la deduzca y aplique.&lt;/li>
&lt;li>&lt;strong>Form-filling&lt;/strong>: en lugar de pedir números libres, el judge rellena un formulario estructurado con campos específicos (presencia de elementos, errores detectados).&lt;/li>
&lt;li>&lt;strong>Probability-weighted scores&lt;/strong>: en lugar de &amp;ldquo;qué nota das&amp;rdquo;, se pide la probabilidad de cada nota y se hace una expectativa ponderada. Mitiga la tendencia a apilarse en valores medios.&lt;/li>
&lt;/ol>
&lt;p>G-Eval implementado bien alcanza &lt;strong>0.89 de correlación de Spearman&lt;/strong> con humanos en datasets de summarization. Es lo que las plataformas serias usan por defecto bajo el capó. Para tu trabajo: no implementes G-Eval a mano; usa la versión de DeepEval o de Phoenix que ya lo trae.&lt;/p>
&lt;h3 id="calibración-contra-humanos-el-paso-no-negociable">Calibración contra humanos: el paso no negociable&lt;/h3>
&lt;p>Un judge sin calibrar es teatro. La práctica:&lt;/p>
&lt;ol>
&lt;li>Construye un &lt;strong>golden set anotado por humanos&lt;/strong> (50-200 ejemplos como mínimo).&lt;/li>
&lt;li>Corre el judge sobre ese golden set.&lt;/li>
&lt;li>Mide el &lt;strong>agreement&lt;/strong> con humanos (Cohen&amp;rsquo;s kappa, Spearman, o accuracy si la tarea es binaria).&lt;/li>
&lt;li>Si el agreement es &amp;lt;85%, el judge no es fiable para esa tarea; itera sobre el prompt o cambia de modelo judge.&lt;/li>
&lt;li>&lt;strong>Repite cada 60-90 días&lt;/strong>. Los judges drift en silencio: cambios de versión del modelo, cambios de comportamiento que el vendor hace sin avisar.&lt;/li>
&lt;/ol>
&lt;p>El número de referencia que cita la literatura 2026: &lt;strong>85-90% de agreement con humanos&lt;/strong> es el umbral para considerar el judge productivo. Por encima, automatizas con cobertura humana en muestreo. Por debajo, sigues siendo manual.&lt;/p>
&lt;h3 id="los-sesgos-del-judge-lo-que-pega-tiros-en-producción">Los sesgos del judge: lo que pega tiros en producción&lt;/h3>
&lt;p>Cinco sesgos identificados que cualquier judge tiene en algún grado:&lt;/p>
&lt;p>&lt;strong>Position bias&lt;/strong>: en pairwise, el judge favorece la respuesta que aparece primero (o última, según modelo). Mitigación obligatoria: &lt;strong>swap and average&lt;/strong> — corre cada par dos veces, una en orden A-B y otra en B-A, y promedia. Si los dos órdenes contradicen, ese par es ambiguo, lo marcas como tal.&lt;/p>
&lt;p>&lt;strong>Length bias&lt;/strong>: respuestas más largas tienden a recibir mejor nota porque &amp;ldquo;parecen más completas&amp;rdquo;. Mitigación: normaliza por longitud o penaliza explícitamente en la rúbrica. Las plataformas modernas detectan esto y lo reportan.&lt;/p>
&lt;p>&lt;strong>Verbosity bias&lt;/strong>: similar al length bias pero con jerga técnica: respuestas que suenan más sofisticadas se puntúan mejor, aunque sean menos correctas. Mitigación: usar judges que &lt;strong>citen evidencia concreta&lt;/strong> del input.&lt;/p>
&lt;p>&lt;strong>Self-preference&lt;/strong>: si el judge es del mismo proveedor que el modelo evaluado (GPT-4 evaluando GPT-4), tiende a favorecer respuestas del propio proveedor por estilo. Mitigación: &lt;strong>cross-judge&lt;/strong> — usa un judge de un proveedor distinto al modelo bajo prueba.&lt;/p>
&lt;p>&lt;strong>Shortcut bias&lt;/strong> (el &amp;ldquo;Silent Judge&amp;rdquo; del paper de 2025): los judges aprenden atajos no intencionados; por ejemplo, asociar respuestas que empiezan por &amp;ldquo;Certainly!&amp;rdquo; con mayor calidad porque sí. Mitigación: tener una rúbrica explícita y ejemplos calibrados; medir agreement contra golden set humano periódicamente.&lt;/p>
&lt;h3 id="coste-y-judges-open-source">Coste y judges open-source&lt;/h3>
&lt;p>GPT-4 como judge es excelente pero &lt;strong>caro&lt;/strong>. A 5 USD/millón input tokens y 15 USD/millón output, una pipeline que evalúa 50 000 respuestas/día puede costar &lt;strong>decenas de miles de USD/mes&lt;/strong> solo en evals.&lt;/p>
&lt;p>La respuesta del campo: &lt;strong>judges open-source especializados&lt;/strong>. &lt;a href="https://github.com/prometheus-eval/prometheus">Prometheus&lt;/a> (KAIST + LG AI) entrena un modelo open-source pequeño específicamente para juzgar con rúbrica, y alcanza &lt;strong>0.897 de correlación de Pearson&lt;/strong> con humanos en 45 rúbricas — comparable a GPT-4 (0.882) a una fracción del coste.&lt;/p>
&lt;p>Otros modelos en la misma línea: &lt;strong>JudgeLM&lt;/strong>, &lt;strong>PandaLM&lt;/strong>, modelos Auto-J. La práctica madura es &lt;strong>usar judges open-source para la mayoría del tráfico, GPT-4/Claude para casos críticos&lt;/strong> (regresión profunda, golden set re-evaluación).&lt;/p>
&lt;h2 id="métricas-específicas-para-rag">Métricas específicas para RAG&lt;/h2>
&lt;p>Si tu sistema es &lt;strong>Retrieval-Augmented Generation&lt;/strong>, hay cuatro métricas canónicas que &lt;a href="https://docs.ragas.io/">Ragas&lt;/a> popularizó y que el resto del ecosistema ha adoptado:&lt;/p>
&lt;h3 id="faithfulness-fidelidad">Faithfulness (fidelidad)&lt;/h3>
&lt;p>¿La respuesta se atiene a los documentos recuperados? Mide alucinación. Se calcula descomponiendo la respuesta en afirmaciones individuales y verificando cuántas están respaldadas por el contexto. Rango 0-1.&lt;/p>
&lt;p>Crítico para sistemas donde &lt;strong>la respuesta debe ser sourced&lt;/strong> (legal, médico, financiero). Una respuesta puede sonar bien y aún así inventar; faithfulness lo cazas.&lt;/p>
&lt;h3 id="answer-relevancy-relevancia-de-la-respuesta">Answer Relevancy (relevancia de la respuesta)&lt;/h3>
&lt;p>¿La respuesta responde a la pregunta? Independiente de si es factualmente correcta — solo mide on-topic. Se calcula generando varias preguntas inversas a partir de la respuesta y midiendo cuánto se parecen a la pregunta original.&lt;/p>
&lt;p>Importante para detectar &lt;strong>off-topic drift&lt;/strong>: respuestas que evaden la pregunta o se desvían.&lt;/p>
&lt;h3 id="context-precision-precisión-del-contexto">Context Precision (precisión del contexto)&lt;/h3>
&lt;p>De los documentos recuperados, ¿cuántos son realmente relevantes? Si tu retrieval devuelve 10 chunks y solo 3 son útiles, la precisión es 0.3. Métrica del retrieval, no del LLM.&lt;/p>
&lt;p>Diagnóstico clave: precisión baja indica &lt;strong>retrieval ruidoso&lt;/strong>, probablemente porque el embedding model no captura semántica fina o el chunking es demasiado grande.&lt;/p>
&lt;h3 id="context-recall-recall-del-contexto">Context Recall (recall del contexto)&lt;/h3>
&lt;p>De los documentos relevantes que existen, ¿cuántos se han recuperado? Requiere golden (saber qué documentos eran los correctos).&lt;/p>
&lt;p>Recall bajo indica &lt;strong>retrieval limitado&lt;/strong>: el sistema no encuentra documentos que existían y eran relevantes. Causas: k demasiado bajo, query embedding mal, chunking que rompe contexto necesario.&lt;/p>
&lt;h3 id="el-cuadrante-diagnóstico-de-rag">El cuadrante diagnóstico de RAG&lt;/h3>
&lt;p>Las cuatro métricas combinadas dan un &lt;strong>diagnóstico estructurado&lt;/strong>:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Faithfulness&lt;/th>
&lt;th>Relevancy&lt;/th>
&lt;th>Precision&lt;/th>
&lt;th>Recall&lt;/th>
&lt;th>Diagnóstico&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Alto&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>&lt;strong>Sistema sano&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Bajo&lt;/strong>&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>LLM alucina sobre buen contexto&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Alto&lt;/td>
&lt;td>&lt;strong>Bajo&lt;/strong>&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>LLM divaga sobre pregunta&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Alto&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>&lt;strong>Bajo&lt;/strong>&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>Retrieval ruidoso (k alto, embeddings malos)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Alto&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>Alto&lt;/td>
&lt;td>&lt;strong>Bajo&lt;/strong>&lt;/td>
&lt;td>Retrieval incompleto (k bajo, chunking malo)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Bajo&lt;/td>
&lt;td>Bajo&lt;/td>
&lt;td>Bajo&lt;/td>
&lt;td>Bajo&lt;/td>
&lt;td>Empieza por arreglar retrieval&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Ragas mantiene además otras métricas más sofisticadas: &lt;strong>noise sensitivity&lt;/strong> (cómo afecta inyección de ruido), &lt;strong>context entities recall&lt;/strong> (recuperación de entidades específicas), &lt;strong>multimodal faithfulness/relevance&lt;/strong> para RAG sobre imágenes y vídeo.&lt;/p>
&lt;h2 id="métricas-específicas-para-agentes">Métricas específicas para agentes&lt;/h2>
&lt;p>Los agentes con tool use multi-step rompen el modelo single-turn de RAG. Necesitan métricas que entiendan &lt;strong>trayectoria de acciones&lt;/strong>, no solo respuesta final.&lt;/p>
&lt;h3 id="tool-selection-accuracy">Tool selection accuracy&lt;/h3>
&lt;p>¿El agente eligió la herramienta correcta? Métrica clásica de classification. Para cada turno donde el agente tenía que decidir entre herramientas, comparas selección con la correcta.&lt;/p>
&lt;p>Variantes:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Exact match&lt;/strong>: la herramienta elegida es la golden.&lt;/li>
&lt;li>&lt;strong>Top-k&lt;/strong>: la golden está entre las top-k consideradas (medido por logprobs si están disponibles).&lt;/li>
&lt;/ul>
&lt;h3 id="trajectory-matching">Trajectory matching&lt;/h3>
&lt;p>Compara la &lt;strong>secuencia completa de acciones&lt;/strong> del agente con una trayectoria golden. Para tareas multistep, una respuesta final correcta puede haberse llegado por un camino tortuoso e ineficiente, o por un camino directo. Trajectory matching captura la diferencia.&lt;/p>
&lt;p>Variantes:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Exact trajectory&lt;/strong>: secuencia idéntica de tool calls (rara vez factible).&lt;/li>
&lt;li>&lt;strong>Soft trajectory&lt;/strong>: porcentaje de pasos correctos, permitiendo ramas alternativas válidas.&lt;/li>
&lt;li>&lt;strong>Trajectory similarity&lt;/strong>: embedding de la secuencia comparado con embedding de la golden.&lt;/li>
&lt;/ul>
&lt;h3 id="task-completion-rate">Task completion rate&lt;/h3>
&lt;p>¿El agente terminó la tarea exitosamente? Métrica binaria al final. Crítica para benchmarks como &lt;a href="https://arxiv.org/abs/2406.12045">Tau-bench&lt;/a> (Sierra), &lt;a href="https://huggingface.co/gaia-benchmark">GAIA&lt;/a> (Meta + HF), &lt;a href="https://www.swebench.com/">SWE-bench&lt;/a> (Princeton).&lt;/p>
&lt;h3 id="passk-la-métrica-que-cambió-las-leaderboards">pass^k: la métrica que cambió las leaderboards&lt;/h3>
&lt;p>Tradicionalmente los benchmarks reportaban &lt;strong>pass^1&lt;/strong>: ejecutas el agente una vez por tarea, mides cuántas resolvió. El problema de no-determinismo: una ejecución sola es ruido.&lt;/p>
&lt;p>&lt;strong>pass^k&lt;/strong> ejecuta cada tarea &lt;strong>k veces&lt;/strong> y mide si el agente la resuelve &lt;strong>en las k ejecuciones&lt;/strong>. Es decir: pass^4 = &amp;ldquo;el agente resuelve esto consistentemente las 4 veces&amp;rdquo;. Métrica de fiabilidad, no de capacidad puntual.&lt;/p>
&lt;p>El descubrimiento que ha agitado el campo 2026: &lt;strong>pass^4 suele estar 15-25 puntos por debajo de pass^1&lt;/strong>. Es decir, muchos agentes que parecen estado del arte en leaderboards single-run resuelven la tarea &lt;strong>solo a veces&lt;/strong>. Productivamente significa que esos agentes no se pueden poner en producción tal cual — necesitan reintentos, autoconsistencia o human-in-the-loop. Tau-bench fue el primero en formalizar este reporting y otros benchmarks lo están adoptando (Tau²-Bench, ATBench, TRAJECT-Bench).&lt;/p>
&lt;h3 id="benchmarks-2026-importantes">Benchmarks 2026 importantes&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="https://arxiv.org/abs/2406.12045">Tau-bench / Tau²-Bench&lt;/a>&lt;/strong> (Sierra): tool-agent-user interaction en dominios empresariales (retail, airline). Reporta pass^k.&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://huggingface.co/gaia-benchmark">GAIA&lt;/a>&lt;/strong>: tareas que requieren razonamiento + tool use + web browsing.&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://www.swebench.com/">SWE-bench&lt;/a>&lt;/strong>: arreglo de bugs en repos reales de GitHub. El benchmark más exigente para agentes de coding.&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://arxiv.org/abs/2604.02022">ATBench&lt;/a>&lt;/strong> (2026): foco en safety durante la trayectoria, no solo en respuesta final.&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://arxiv.org/abs/2510.04550">TRAJECT-Bench&lt;/a>&lt;/strong>: agentic tool use evaluado a nivel trayectoria con métricas estandarizadas.&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://inspect.ai-safety-institute.org.uk/">Inspect AI evals&lt;/a>&lt;/strong> (UK AI Safety Institute): foco en capability y safety, abierto.&lt;/li>
&lt;/ul>
&lt;h2 id="el-panorama-de-herramientas-2026">El panorama de herramientas 2026&lt;/h2>
&lt;p>El campo se ha estabilizado en dos categorías que rara vez compiten directamente:&lt;/p>
&lt;h3 id="categoría-a-testing-frameworks-gating-en-ci">Categoría A: testing frameworks (gating en CI)&lt;/h3>
&lt;p>Pensados para correr como tests, bloquear merges, dar feedback rápido al desarrollador.&lt;/p>
&lt;p>&lt;strong>&lt;a href="https://github.com/confident-ai/deepeval">DeepEval&lt;/a>&lt;/strong> (Apache 2.0). El más popular hoy. Estilo &lt;code>pytest&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">deepeval&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">assert_test&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">deepeval.test_case&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">LLMTestCase&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">deepeval.metrics&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">GEval&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">FaithfulnessMetric&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">test_rag_response&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">test_case&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">LLMTestCase&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">input&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;What&amp;#39;s the capital of France?&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">actual_output&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">my_rag_app&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;What&amp;#39;s the capital of France?&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">retrieval_context&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">docs&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">geval_metric&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">GEval&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Correctness&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">criteria&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Determine if the answer is factually correct.&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">evaluation_params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;actual_output&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">faithfulness&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">FaithfulnessMetric&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">threshold&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">0.7&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">assert_test&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">test_case&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">geval_metric&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">faithfulness&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Trae 30+ métricas pre-hechas, incluye G-Eval, integra con CI/CD trivial. La librería más completa en cobertura.&lt;/p>
&lt;p>&lt;strong>&lt;a href="https://www.promptfoo.dev/">Promptfoo&lt;/a>&lt;/strong> (MIT). CLI-first, configuración en YAML. Especializado en &lt;strong>red teaming&lt;/strong> y &lt;strong>comparación de modelos&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">providers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">openai:gpt-4o&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">anthropic:claude-3.5-sonnet&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">openrouter:meta-llama/llama-3.3-70b&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">prompts&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;Summarize: {{text}}&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">tests&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">vars&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">text&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;...&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">assert&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">llm-rubric&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Summary is accurate and concise&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">contains&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;...&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Corre la misma evaluación contra muchos providers simultáneamente. Fantástico para &amp;ldquo;qué modelo conviene a esta tarea&amp;rdquo;. Pioneer en &lt;strong>red teaming automatizado&lt;/strong>: genera ataques de prompt injection y mide robustez.&lt;/p>
&lt;p>&lt;strong>&lt;a href="https://docs.ragas.io/">Ragas&lt;/a>&lt;/strong> (Apache 2.0). Especializado en RAG. Implementa las 4 métricas canónicas más una docena más, lightweight, sin opinionado sobre tu stack:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">ragas&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">evaluate&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">ragas.metrics&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">faithfulness&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">answer_relevancy&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context_precision&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context_recall&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">evaluate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dataset&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">metrics&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">faithfulness&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">answer_relevancy&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context_precision&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">context_recall&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Si tu sistema es RAG y solo RAG, Ragas es la apuesta más directa.&lt;/p>
&lt;p>&lt;strong>Otros relevantes&lt;/strong>: &lt;a href="https://github.com/openai/evals">OpenAI Evals&lt;/a> (el clásico, OSS), &lt;a href="https://docs.smith.langchain.com/">LangSmith Evals SDK&lt;/a> (para usuarios LangChain), &lt;a href="https://inspect.ai-safety-institute.org.uk/">Inspect AI&lt;/a> (UK AISI, fuerte en safety/capability evals).&lt;/p>
&lt;h3 id="categoría-b-plataformas-storage--dashboard--regresión">Categoría B: plataformas (storage + dashboard + regresión)&lt;/h3>
&lt;p>Pensadas para persistencia a largo plazo, anotación humana, regresión, dashboards a stakeholders.&lt;/p>
&lt;p>&lt;strong>&lt;a href="https://langfuse.com/">Langfuse&lt;/a>&lt;/strong> (MIT, self-host disponible). Cubierta en profundidad ayer. Para evals: ejecuta evaluators en background sobre traces de producción, permite human labeling en UI, integra con datasets y prompt management. Es la opción más completa OSS.&lt;/p>
&lt;p>&lt;strong>&lt;a href="https://www.langchain.com/langsmith">LangSmith&lt;/a>&lt;/strong> (comercial). Si usas LangChain, integración cero-config. Datasets, evaluator SDK, runs comparables side-by-side. UI limpia para stakeholders.&lt;/p>
&lt;p>&lt;strong>&lt;a href="https://phoenix.arize.com/">Arize Phoenix&lt;/a>&lt;/strong> (ELv2, OSS). OTel-native, fuerte en RAG por su énfasis en retrieval. Evals built-in con LLM-as-judge configurable.&lt;/p>
&lt;p>&lt;strong>&lt;a href="https://www.braintrust.dev/">Braintrust&lt;/a>&lt;/strong> (comercial, OSS lite). El competidor más joven en plataformas; fuerte en datasets y comparativa side-by-side. Adoptado por equipos que vienen de hacer evals &amp;ldquo;en una hoja de cálculo&amp;rdquo; porque la UX está pulida.&lt;/p>
&lt;h3 id="tabla-comparativa-testing-frameworks-vs-platforms">Tabla comparativa: testing frameworks vs platforms&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Herramienta&lt;/th>
&lt;th>Tipo&lt;/th>
&lt;th>Licencia&lt;/th>
&lt;th>Self-host&lt;/th>
&lt;th>Especialidad&lt;/th>
&lt;th>Idóneo cuando&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>DeepEval&lt;/strong>&lt;/td>
&lt;td>Framework CI&lt;/td>
&lt;td>Apache 2.0&lt;/td>
&lt;td>N/A&lt;/td>
&lt;td>Maximalismo de métricas&lt;/td>
&lt;td>Quieres pytest para LLMs, 30+ métricas listas&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Promptfoo&lt;/strong>&lt;/td>
&lt;td>Framework CI&lt;/td>
&lt;td>MIT&lt;/td>
&lt;td>N/A&lt;/td>
&lt;td>Modelo comparison + red teaming&lt;/td>
&lt;td>Eliges modelo, atacas prompt&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Ragas&lt;/strong>&lt;/td>
&lt;td>Framework CI&lt;/td>
&lt;td>Apache 2.0&lt;/td>
&lt;td>N/A&lt;/td>
&lt;td>RAG end-to-end&lt;/td>
&lt;td>Tu sistema es exclusivamente RAG&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>OpenAI Evals&lt;/strong>&lt;/td>
&lt;td>Framework CI&lt;/td>
&lt;td>MIT&lt;/td>
&lt;td>N/A&lt;/td>
&lt;td>Clásico, simple&lt;/td>
&lt;td>Empezando, OpenAI nativo&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Inspect AI&lt;/strong>&lt;/td>
&lt;td>Framework CI&lt;/td>
&lt;td>MIT&lt;/td>
&lt;td>Sí&lt;/td>
&lt;td>Safety / capability evals&lt;/td>
&lt;td>Evaluación de modelos base, alignment&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Langfuse&lt;/strong>&lt;/td>
&lt;td>Platform&lt;/td>
&lt;td>MIT&lt;/td>
&lt;td>&lt;strong>Sí&lt;/strong>&lt;/td>
&lt;td>Suite completa (trace+eval+prompts)&lt;/td>
&lt;td>OSS, self-host, equipo iterativo&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>LangSmith&lt;/strong>&lt;/td>
&lt;td>Platform&lt;/td>
&lt;td>Comercial&lt;/td>
&lt;td>No&lt;/td>
&lt;td>LangChain ecosystem&lt;/td>
&lt;td>Tu stack es LangChain&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Arize Phoenix&lt;/strong>&lt;/td>
&lt;td>Platform&lt;/td>
&lt;td>ELv2 (OSS)&lt;/td>
&lt;td>&lt;strong>Sí&lt;/strong>&lt;/td>
&lt;td>OTel-native, RAG&lt;/td>
&lt;td>Estandarización OTel, RAG profundo&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Braintrust&lt;/strong>&lt;/td>
&lt;td>Platform&lt;/td>
&lt;td>Comercial + OSS&lt;/td>
&lt;td>Limitado&lt;/td>
&lt;td>UX pulida, datasets&lt;/td>
&lt;td>Stakeholders no-técnicos, side-by-side&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="la-receta-operativa-stack-de-dos-pisos">La receta operativa: stack de dos pisos&lt;/h2>
&lt;p>La estructura que más se ve en equipos productivos en 2026:&lt;/p>
&lt;h3 id="piso-1--framework-de-ci">Piso 1 — Framework de CI&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>DeepEval&lt;/strong> o &lt;strong>Promptfoo&lt;/strong> (o &lt;strong>Ragas&lt;/strong> si es RAG estricto) corriendo en cada PR.&lt;/li>
&lt;li>Dataset golden versionado en el repo (~100-500 ejemplos curados).&lt;/li>
&lt;li>Métricas con threshold: si baja G-Eval medio por debajo de 0.85, el merge falla.&lt;/li>
&lt;li>Tiempo objetivo: &amp;lt;2 minutos para no bloquear el flow del desarrollador.&lt;/li>
&lt;/ul>
&lt;h3 id="piso-2--plataforma-de-regresión--drift">Piso 2 — Plataforma de regresión + drift&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Langfuse&lt;/strong> / &lt;strong>LangSmith&lt;/strong> / &lt;strong>Phoenix&lt;/strong> / &lt;strong>Braintrust&lt;/strong> persistiendo todos los traces de producción.&lt;/li>
&lt;li>Evaluators corriendo sobre muestreo de tráfico real (eg 5-10% de las respuestas evaluadas con LLM-as-judge cada hora).&lt;/li>
&lt;li>Dashboard semanal con tendencias por segmento, version de prompt, modelo.&lt;/li>
&lt;li>Human labeling de los casos que el judge marca como dudosos.&lt;/li>
&lt;/ul>
&lt;h3 id="ciclo-del-cambio">Ciclo del cambio&lt;/h3>
&lt;p>Pipeline típico de cambiar un prompt:&lt;/p>
&lt;ol>
&lt;li>Developer modifica el prompt en local.&lt;/li>
&lt;li>CI corre eval framework contra dataset golden. Si pasa, merge.&lt;/li>
&lt;li>El cambio sube a staging; la plataforma persiste evaluaciones de tráfico real durante 24-48h.&lt;/li>
&lt;li>Si la regresión sale: rollback automático o flag.&lt;/li>
&lt;li>Si pasa la ventana de staging: promoción a producción.&lt;/li>
&lt;li>Eval continuo en producción detecta drift en días/semanas si ocurre.&lt;/li>
&lt;/ol>
&lt;p>Lo que cierra el bucle: &lt;strong>el dataset golden se enriquece con los casos donde el sistema falló en producción&lt;/strong>. Cada incidente genera 3-5 ejemplos nuevos en el dataset; el dataset crece como entidad viva durante el ciclo de vida de la app.&lt;/p>
&lt;h2 id="ejemplo-concreto-pipeline-rag-con-deepeval--langfuse">Ejemplo concreto: pipeline RAG con DeepEval + Langfuse&lt;/h2>
&lt;p>Receta minimalista:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># CI: deepeval test (corre en cada PR)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># tests/test_rag.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">pytest&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">deepeval&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">assert_test&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">deepeval.test_case&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">LLMTestCase&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">deepeval.metrics&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">FaithfulnessMetric&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">AnswerRelevancyMetric&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">deepeval.dataset&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">EvaluationDataset&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">app.rag&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">answer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">dataset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">EvaluationDataset&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">dataset&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_test_cases_from_json_file&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">file_path&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;tests/golden_dataset.json&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">input_key_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;question&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">actual_output_key_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ignore&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># se rellena en runtime&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">expected_output_key_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;expected_answer&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context_key_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;ignore&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@pytest.mark.parametrize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tc&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dataset&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">test_cases&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">test_rag_quality&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tc&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">docs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">answer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">input&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">actual_output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">retrieval_context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">content&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">d&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">docs&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">assert_test&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">FaithfulnessMetric&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">threshold&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">0.8&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">AnswerRelevancyMetric&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">threshold&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">0.75&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Producción: tracing + eval async con Langfuse&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># app/rag.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langfuse&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">observe&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">get_client&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langfuse.evaluators&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">faithfulness&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">answer_relevancy&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">langfuse&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_client&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@observe&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">as_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;generation&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">answer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">question&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">docs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">retrieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">question&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">resp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">generate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">build_prompt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">question&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">docs&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># eval async en background sobre una muestra&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">langfuse&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">evaluate_async&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;faithfulness&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">evaluator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">faithfulness&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">input&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">question&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">resp&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">context&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">docs&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sample_rate&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">0.1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 10% del tráfico&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">resp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">docs&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Y un dashboard Grafana o Langfuse UI muestra:&lt;/p>
&lt;ul>
&lt;li>Faithfulness p50/p95 por día.&lt;/li>
&lt;li>Distribución por namespace o tenant.&lt;/li>
&lt;li>Drift respecto al baseline.&lt;/li>
&lt;li>Casos peor evaluados para human review.&lt;/li>
&lt;/ul>
&lt;p>Cuatro horas de trabajo para tener esto montado en una app que ya tiene Langfuse desplegado. Cero excusas para no hacerlo.&lt;/p>
&lt;h2 id="la-frontera-2026-lo-que-el-campo-aún-no-ha-resuelto">La frontera 2026: lo que el campo aún no ha resuelto&lt;/h2>
&lt;p>Tres frentes abiertos donde la investigación va activa:&lt;/p>
&lt;h3 id="outcome-scoring-sigue-siendo-el-problema-duro">Outcome scoring sigue siendo el problema duro&lt;/h3>
&lt;p>Ya tenemos el &lt;strong>step-level tracing&lt;/strong>: tool-call accuracy, trajectory analysis, latency per step, input/output por nodo. Te dice cómo se ejecutó el agente.&lt;/p>
&lt;p>Lo que no está resuelto es &lt;strong>outcome scoring&lt;/strong>: ¿completó el agente el objetivo en una forma que un experto del dominio aprobaría? Replay del trace no responde esta pregunta. Necesitas a alguien que sepa qué significa &amp;ldquo;éxito&amp;rdquo; en el contexto específico — y eso es caro y no escala.&lt;/p>
&lt;p>Las propuestas actuales: usar judges fuertes (GPT-4 con CoT) sobre la respuesta final más contexto del trace, dataset de outcomes etiquetados por expertos como golden, ensembles de judges para alta varianza. Ninguna es magia.&lt;/p>
&lt;h3 id="trajectory-benchmarks-emergentes">Trajectory benchmarks emergentes&lt;/h3>
&lt;p>&lt;a href="https://arxiv.org/abs/2604.02022">&lt;strong>ATBench&lt;/strong>&lt;/a> y &lt;a href="https://arxiv.org/abs/2510.04550">&lt;strong>TRAJECT-Bench&lt;/strong>&lt;/a> representan la nueva ola de benchmarks que evalúan &lt;strong>toda la trayectoria&lt;/strong> del agente, no solo input/output. Detectan safety issues durante la ejecución (usar tools peligrosos, exfiltrar datos en pasos intermedios) que un benchmark de final-answer pierde.&lt;/p>
&lt;p>Si tu carga de producción tiene agentes haciendo varios tool calls, &lt;strong>moviéndose a benchmarks trajectory-level&lt;/strong> durante 2026 es la dirección que el campo señala.&lt;/p>
&lt;h3 id="pairwise-vs-absolute-revisited">Pairwise vs absolute revisited&lt;/h3>
&lt;p>Hay debate activo. El argumento contra pairwise: &lt;strong>no escala bien&lt;/strong>. Para evaluar N respuestas, pairwise requiere O(N²) comparaciones (todos contra todos) o N log N con torneo, ambos caros. Scoring absoluto es O(N).&lt;/p>
&lt;p>La síntesis emergente: &lt;strong>pairwise para gold-set y regresión&lt;/strong> (necesitas la mayor calidad), &lt;strong>absolute con G-Eval para producción&lt;/strong> (escala mejor, asumiendo calibración adecuada). La elección no es ideológica; depende de la fase del pipeline.&lt;/p>
&lt;h3 id="self-consistency-y-ensemble-de-judges">Self-consistency y ensemble de judges&lt;/h3>
&lt;p>Para casos críticos: ejecutar el judge &lt;strong>varias veces&lt;/strong> con temperature &amp;gt; 0 y agregar. Si los N judges coinciden, alta confianza; si discrepan, marca el caso para human review. Mejora robustez a costa de coste.&lt;/p>
&lt;p>Variante más avanzada: &lt;strong>jury of judges&lt;/strong> — tres judges distintos (GPT-4, Claude, un open-source) sobre la misma respuesta, agregación por mayoría. Estado del arte en agreement con humanos pero &lt;strong>3x más caro&lt;/strong>.&lt;/p>
&lt;h2 id="trampas-operativas">Trampas operativas&lt;/h2>
&lt;h3 id="golden-dataset-que-envejece">Golden dataset que envejece&lt;/h3>
&lt;p>Un golden set sin mantener empieza a divergir de la realidad: nuevos casos de uso aparecen, nuevos failure modes no están representados. &lt;strong>Revisa y enriquece el golden cada quincena o mes&lt;/strong>, idealmente añadiendo los casos donde producción falló.&lt;/p>
&lt;h3 id="judge-contaminado">Judge contaminado&lt;/h3>
&lt;p>El judge sabe demasiado sobre el dataset (apareció en su entrenamiento). Las notas son artificialmente buenas. Especialmente serio si usas datasets públicos como golden. Mitigación: &lt;strong>datasets privados curados internamente&lt;/strong>, rotación de modelos judge.&lt;/p>
&lt;h3 id="sample-size-insuficiente">Sample size insuficiente&lt;/h3>
&lt;p>Con 10 ejemplos en el dataset, una métrica que baja de 0.85 a 0.75 puede ser ruido puro. &lt;strong>Mínimo 50, ideal 200-500&lt;/strong> para que las diferencias sean significativas. Reporta intervalos de confianza, no solo medias.&lt;/p>
&lt;h3 id="costes-que-se-descontrolan">Costes que se descontrolan&lt;/h3>
&lt;p>Ejecutar G-Eval con GPT-4 sobre 5 000 respuestas/día son &lt;strong>decenas de miles de tokens/día solo de evaluación&lt;/strong> que se pagan extra. Para escalas medianas, considera &lt;strong>judge open-source&lt;/strong> (Prometheus) o &lt;strong>sampling&lt;/strong> (5-10% del tráfico evaluado, no todo).&lt;/p>
&lt;h3 id="olvidar-el-segmento">Olvidar el segmento&lt;/h3>
&lt;p>Una métrica media de 0.85 puede esconder que para el segmento &amp;ldquo;preguntas en alemán&amp;rdquo; es 0.55 y para &amp;ldquo;preguntas técnicas largas&amp;rdquo; es 0.65. Reporta &lt;strong>siempre por segmento&lt;/strong> (idioma, dominio, tenant, tipo de pregunta). El &amp;ldquo;todo está bien&amp;rdquo; es sospechoso.&lt;/p>
&lt;h3 id="no-actualizar-la-calibración">No actualizar la calibración&lt;/h3>
&lt;p>Los judges drift. Lo que medía 88% de agreement humano hace 3 meses puede haber bajado a 76% sin que nadie se entere. &lt;strong>Recalibra cada 60-90 días&lt;/strong> contra el golden set humano.&lt;/p>
&lt;h3 id="confiar-en-un-eval-para-reemplazar-humanos">Confiar en un eval para reemplazar humanos&lt;/h3>
&lt;p>Los evals automatizados son &lt;strong>complemento&lt;/strong> del juicio humano, no sustituto total. Para casos de alto stake (legal, médico, financiero) o nuevos releases mayores, &lt;strong>muestreo humano sigue siendo necesario&lt;/strong>. La proporción razonable: 95% automatizado, 5% humano en muestreo estratificado.&lt;/p>
&lt;h2 id="lo-que-no-hemos-cubierto-próximos-posts">Lo que no hemos cubierto (próximos posts)&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Guardrails y safety&lt;/strong>: el siguiente post de la serie. Cómo prevenir que prompts malos lleguen al modelo, en lugar de evaluar respuestas a posteriori.&lt;/li>
&lt;li>&lt;strong>MCP observability profunda&lt;/strong>: cómo OpenTelemetry GenAI se extiende a MCP servers para que las tools también sean trace-aware.&lt;/li>
&lt;li>&lt;strong>eBPF + on-device inference + drift detection&lt;/strong>: el cierre.&lt;/li>
&lt;/ul>
&lt;h2 id="referencias">Referencias&lt;/h2>
&lt;p>Frameworks y plataformas:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/confident-ai/deepeval">DeepEval&lt;/a> — Apache 2.0, pytest-style.&lt;/li>
&lt;li>&lt;a href="https://www.promptfoo.dev/">Promptfoo&lt;/a> — MIT, CLI + YAML, red teaming.&lt;/li>
&lt;li>&lt;a href="https://docs.ragas.io/">Ragas&lt;/a> — Apache 2.0, RAG-specific.&lt;/li>
&lt;li>&lt;a href="https://github.com/openai/evals">OpenAI Evals&lt;/a> — MIT, clásico.&lt;/li>
&lt;li>&lt;a href="https://inspect.ai-safety-institute.org.uk/">Inspect AI&lt;/a> — UK AI Safety Institute.&lt;/li>
&lt;li>&lt;a href="https://langfuse.com/">Langfuse&lt;/a> — MIT, self-host, suite completa.&lt;/li>
&lt;li>&lt;a href="https://www.langchain.com/langsmith">LangSmith&lt;/a> — LangChain team.&lt;/li>
&lt;li>&lt;a href="https://phoenix.arize.com/">Arize Phoenix&lt;/a> — ELv2, OTel-native.&lt;/li>
&lt;li>&lt;a href="https://www.braintrust.dev/">Braintrust&lt;/a> — comercial + OSS lite.&lt;/li>
&lt;/ul>
&lt;p>Métodos y papers:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://arxiv.org/abs/2303.16634">G-Eval (Liu et al., 2023)&lt;/a> — el patrón de prompting dominante.&lt;/li>
&lt;li>&lt;a href="https://github.com/prometheus-eval/prometheus">Prometheus (KAIST + LG AI)&lt;/a> — judge open-source con 0.897 correlación.&lt;/li>
&lt;li>&lt;a href="https://arxiv.org/abs/2406.12045">Tau-bench (Sierra, 2024)&lt;/a> — tool-agent-user benchmark con pass^k.&lt;/li>
&lt;li>&lt;a href="https://arxiv.org/abs/2604.02022">ATBench (2026)&lt;/a> — trajectory safety benchmark.&lt;/li>
&lt;li>&lt;a href="https://arxiv.org/abs/2510.04550">TRAJECT-Bench (2026)&lt;/a> — trajectory-aware agentic tool use.&lt;/li>
&lt;li>&lt;a href="https://arxiv.org/html/2503.16416v2">Survey on Evaluation of LLM-based Agents&lt;/a> — el survey de referencia.&lt;/li>
&lt;/ul>
&lt;p>Comparativas 2026:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.comet.com/site/blog/llm-evaluation-frameworks/">LLM Evaluation Frameworks: Head-to-Head Comparison (Comet)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://atlan.com/know/llm-evaluation-frameworks-compared/">RAGAS, TruLens, DeepEval: LLM Evaluation Frameworks 2026 (Atlan)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://inference.net/content/llm-evaluation-tools-comparison/">LLM Evaluation Tools: Complete Comparison Guide 2026 (Inference.net)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://futureagi.com/blog/llm-as-judge-best-practices-2026">LLM-as-Judge Best Practices in 2026: Calibration, Bias, and Cost (FutureAGI)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://futureagi.com/blog/best-llm-judge-models-2026/">Best LLM Judge Models in 2026&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://medium.com/@nairmilind3/llm-evaluation-in-2026-e631a78c67dc">LLM Evaluation in 2026 (Milind Nair, Medium)&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>Cross-references:&lt;/p>
&lt;ul>
&lt;li>Serie eBPF: &lt;a href="https://blog.lo0.es/posts/ebpf-cilium-tcp-ip-bypass/">eBPF de cero a Cilium&lt;/a>, &lt;a href="https://blog.lo0.es/posts/tetragon-runtime-security/">Tetragon&lt;/a>, &lt;a href="https://blog.lo0.es/posts/hubble-observabilidad-ebpf/">Hubble&lt;/a>, &lt;a href="https://blog.lo0.es/posts/agentsight-tracing-llm/">AgentSight y tracing LLM&lt;/a>.&lt;/li>
&lt;li>Serie de inferencia: &lt;a href="https://blog.lo0.es/posts/kv-cache-fundamentos/">KV cache&lt;/a>, &lt;a href="https://blog.lo0.es/posts/vllm-kubernetes/">vLLM en K8s&lt;/a>, &lt;a href="https://blog.lo0.es/posts/pagedattention-deep-dive/">PagedAttention&lt;/a>, &lt;a href="https://blog.lo0.es/posts/operators-llm-kubernetes/">Operators LLM K8s&lt;/a>.&lt;/li>
&lt;/ul></description></item><item><title>AgentSight y el nuevo tracing de LLMs: zero-instrumentation con eBPF frente a Langfuse, LangSmith, Phoenix y compañía</title><link>https://blog.lo0.es/posts/agentsight-tracing-llm/</link><pubDate>Tue, 19 May 2026 18:00:00 +0200</pubDate><guid>https://blog.lo0.es/posts/agentsight-tracing-llm/</guid><description>&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>Observar un agente de LLM en producción en 2026 se divide en dos enfoques con filosofías opuestas. El &lt;strong>instrumentado&lt;/strong>, dominante hasta 2025, vive en herramientas como &lt;a href="https://langfuse.com/">Langfuse&lt;/a>, &lt;a href="https://www.langchain.com/langsmith">LangSmith&lt;/a>, &lt;a href="https://phoenix.arize.com/">Arize Phoenix&lt;/a>, &lt;a href="https://www.helicone.ai/">Helicone&lt;/a>, &lt;a href="https://www.traceloop.com/openllmetry">OpenLLMetry/Traceloop&lt;/a> o &lt;a href="https://pydantic.dev/logfire">Pydantic Logfire&lt;/a>: instalas un SDK, decoras tus llamadas, emites spans con la convención &lt;strong>OpenTelemetry GenAI&lt;/strong> (&lt;code>gen_ai.request.model&lt;/code>, &lt;code>gen_ai.usage.input_tokens&lt;/code>, etc.) y los exportas a un backend. Profundidad altísima cuando controlas el código; cero visibilidad cuando el agente es un binario opaco que ejecutas sin instrumentar. El &lt;strong>zero-instrumentation&lt;/strong>, que &lt;a href="https://github.com/eunomia-bpf/agentsight">AgentSight&lt;/a> ha popularizado en la segunda mitad de 2025, gira la perspectiva 180º: pone hooks &lt;strong>eBPF en las uprobes de las bibliotecas SSL/TLS&lt;/strong> y captura el plaintext de cada petición HTTPS antes del cifrado, &lt;strong>sin tocar el código de la app&lt;/strong>, con menos del &lt;strong>3% de overhead&lt;/strong> y la garantía de ser &lt;strong>tamper-proof&lt;/strong> (el agente no puede falsificar lo que se ve en el kernel). Combinado con captura BPF de stdio para servidores MCP locales, AgentSight te da observabilidad completa de cualquier agente —incluyendo binarios cerrados como Claude Code, Gemini CLI o Cursor— en un cluster Kubernetes. Las dos familias no son enemigas: la pila de referencia 2026 combina ambas (instrumented para apps propias con LangChain, eBPF para binarios opacos y compliance de tamper-proof) sobre &lt;strong>OpenTelemetry GenAI semantic conventions&lt;/strong> como vocabulario común que el ecosistema está estabilizando este año.&lt;/p>
&lt;blockquote>
&lt;p>Este es el &lt;strong>cuarto y último post de la serie sobre eBPF&lt;/strong>. Parte 1: &lt;a href="https://blog.lo0.es/posts/ebpf-cilium-tcp-ip-bypass/">eBPF de cero a Cilium&lt;/a>. Parte 2: &lt;a href="https://blog.lo0.es/posts/tetragon-runtime-security/">Tetragon: seguridad de runtime&lt;/a>. Parte 3: &lt;a href="https://blog.lo0.es/posts/hubble-observabilidad-ebpf/">Hubble: observabilidad de red&lt;/a>. Aquí cerramos el círculo con la dimensión &lt;strong>semántica&lt;/strong> —qué hace un agente IA, no solo qué red abre o qué syscalls emite—.&lt;/p>
&lt;/blockquote>
&lt;h2 id="la-analogía-apm-tradicional-vs-sniffer-de-red">La analogía: APM tradicional vs sniffer de red&lt;/h2>
&lt;p>Quien haya operado aplicaciones empresariales conoce las dos tribus del monitoring. La tribu &lt;strong>APM&lt;/strong> (New Relic, AppDynamics, Datadog APM): instalas un agente o un SDK en cada aplicación, marcas spans, recoges traces con profundidad enorme dentro de cada proceso —líneas de código, queries SQL, métodos de Java—. La tribu &lt;strong>wire-level&lt;/strong> (sniffers de red, herramientas tipo SolarWinds NPM, NetFlow): no toca la aplicación; observa el cable, ve protocolos, latencias, retransmisiones, identifica problemas que la app no sabe que tiene.&lt;/p>
&lt;p>Cada una ve cosas distintas y las dos sirven. Quien ha vivido un incidente serio donde APM decía &amp;ldquo;todo verde&amp;rdquo; mientras los usuarios sufrían sabe que el wire-level habría detectado el problema (un middlebox saturado, un MTU mal configurado, un timeout de TCP). Quien ha intentado debuggear un memory leak con sniffers sabe que sin APM era imposible.&lt;/p>
&lt;p>La observabilidad de agentes LLM en 2026 está exactamente en este punto. El &lt;strong>APM-style&lt;/strong> lleva un par de años montado: Langfuse, LangSmith, Phoenix, OpenLLMetry. Profundidad enorme, requiere instrumentar la app. El &lt;strong>wire-level con eBPF&lt;/strong> acaba de llegar: AgentSight es el primer proyecto que lo lleva a productivo. Profundidad menor en el interior del agente, pero ve cualquier agente sin tocar nada y es &lt;strong>tamper-proof&lt;/strong>. Los dos sirven. La industria está en plena coexistencia.&lt;/p>
&lt;h2 id="por-qué-observar-agentes-llm-es-distinto">Por qué observar agentes LLM es distinto&lt;/h2>
&lt;p>Antes de entrar en herramientas, vale la pena detenerse en qué hace específicos a los agentes LLM como sujetos de observabilidad:&lt;/p>
&lt;p>&lt;strong>No-determinismo.&lt;/strong> El mismo input puede producir outputs distintos. Reproducir un incidente requiere capturar &lt;strong>exactamente&lt;/strong> la conversación, el modelo, los parámetros y, idealmente, la seed. Una métrica agregada &amp;ldquo;latencia p95&amp;rdquo; se queda corta; lo que necesitas es replay de la traza individual.&lt;/p>
&lt;p>&lt;strong>Cadena de invocaciones externas.&lt;/strong> Un agente típico llama LLM → herramientas (tool calling) → MCP servers → otras APIs → vuelta a LLM. Una sesión de chat puede generar &lt;strong>decenas de llamadas encadenadas&lt;/strong> que hay que correlar por trace_id para entender la decisión.&lt;/p>
&lt;p>&lt;strong>Coste lineal en tokens.&lt;/strong> Cada llamada se paga en tokens. Sin trazar input/output tokens por petición, no puedes asignar coste a tenant ni equipo, ni detectar bucles que se comen tu presupuesto en una hora.&lt;/p>
&lt;p>&lt;strong>Riesgo semántico.&lt;/strong> Prompt injection (un user input que contiene instrucciones para manipular al modelo), jailbreaks, leakage de secretos via tool calls. Es un tipo de problema que no aparece en aplicaciones tradicionales y la observabilidad debe verlo.&lt;/p>
&lt;p>&lt;strong>Binarios opacos.&lt;/strong> En 2026, muchos equipos despliegan &lt;strong>agentes de terceros&lt;/strong> —Claude Code, Cursor agent, Aider, Gemini CLI, Codex CLI— como herramientas internas. No son aplicaciones propias; son binarios cerrados que llaman a la API del vendor. Instrumentarlos es imposible. Observarlos requiere otra cosa.&lt;/p>
&lt;p>&lt;strong>Multi-agent y orquestación.&lt;/strong> Cada vez más arquitecturas tienen agentes que invocan a otros agentes (planner → executor → critic). La observabilidad debe entender la topología, no solo el span individual.&lt;/p>
&lt;p>Con estos cinco puntos en mente, las herramientas que vamos a ver se diferencian principalmente en &lt;strong>qué partes&lt;/strong> del problema cubren bien y &lt;strong>qué partes&lt;/strong> dejan ciegas.&lt;/p>
&lt;h2 id="el-enfoque-instrumentado-cómo-funciona">El enfoque instrumentado: cómo funciona&lt;/h2>
&lt;p>El modelo es directo y conocido:&lt;/p>
&lt;ol>
&lt;li>Tu código llama al LLM o a herramientas usando una librería oficial: &lt;code>openai&lt;/code>, &lt;code>anthropic&lt;/code>, &lt;code>langchain&lt;/code>, &lt;code>llama_index&lt;/code>, &lt;code>dspy&lt;/code>.&lt;/li>
&lt;li>Instalas un SDK del tracer (Langfuse, LangSmith, OpenLLMetry, Logfire) que &lt;strong>wrappea&lt;/strong> o &lt;strong>monkey-patcha&lt;/strong> esas librerías.&lt;/li>
&lt;li>Cada llamada emite un &lt;strong>span OpenTelemetry&lt;/strong> con atributos estandarizados: modelo usado, tokens input/output, latencia, parámetros, mensajes, herramienta invocada, resultado.&lt;/li>
&lt;li>Los spans se exportan vía OTLP a un backend que los muestra como un árbol de traces.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Ejemplo típico con OpenLLMetry + cualquier SDK&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">traceloop.sdk&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Traceloop&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">OpenAI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">Traceloop&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">app_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;my-agent&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">api_endpoint&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;https://otel-collector:4318&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">client&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpenAI&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># este call emite automáticamente un span con&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># gen_ai.request.model, gen_ai.usage.input_tokens, etc.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">resp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">client&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">completions&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;gpt-4.1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;...&amp;#34;&lt;/span>&lt;span class="p">}]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Lo que ves después: un dashboard con cada conversación como un trace, cada llamada como un span, los prompts y completions completos (si optas in), el coste calculado, latencias por span, errores marcados.&lt;/p>
&lt;h3 id="opentelemetry-genai-semantic-conventions-el-vocabulario-común">OpenTelemetry GenAI semantic conventions: el vocabulario común&lt;/h3>
&lt;p>La fragmentación del campo se está mitigando con &lt;a href="https://opentelemetry.io/docs/specs/semconv/gen-ai/">&lt;strong>OpenTelemetry GenAI Semantic Conventions&lt;/strong>&lt;/a>. Es el esfuerzo de la CNCF para que &lt;strong>todas&lt;/strong> las herramientas emitan spans con los mismos nombres de atributos:&lt;/p>
&lt;ul>
&lt;li>&lt;code>gen_ai.system&lt;/code> — el proveedor (openai, anthropic, vertex_ai, etc.).&lt;/li>
&lt;li>&lt;code>gen_ai.request.model&lt;/code> — modelo solicitado (&lt;code>gpt-4.1&lt;/code>, &lt;code>claude-3-5-sonnet&lt;/code>).&lt;/li>
&lt;li>&lt;code>gen_ai.response.model&lt;/code> — modelo realmente usado (a veces difiere, eg fallbacks).&lt;/li>
&lt;li>&lt;code>gen_ai.usage.input_tokens&lt;/code> y &lt;code>gen_ai.usage.output_tokens&lt;/code> — contadores.&lt;/li>
&lt;li>&lt;code>gen_ai.request.temperature&lt;/code>, &lt;code>gen_ai.request.top_p&lt;/code>, etc. — parámetros.&lt;/li>
&lt;li>&lt;code>gen_ai.response.finish_reasons&lt;/code> — por qué terminó (stop, length, content_filter).&lt;/li>
&lt;li>&lt;code>gen_ai.operation.name&lt;/code> — el tipo de operación (chat, embedding, completion).&lt;/li>
&lt;/ul>
&lt;p>A principios de 2026, los &lt;strong>client spans&lt;/strong> salieron de experimental a estable. El resto (server spans, multi-agent events) sigue en desarrollo. El significado operacional: si tu SDK emite estos atributos, &lt;strong>cualquier backend que entienda OTel GenAI&lt;/strong> puede consumirlos. Cambiar de Langfuse a Phoenix a Helicone no implica re-instrumentar, solo cambiar el exporter.&lt;/p>
&lt;p>La SIG está activamente desarrollando &lt;strong>conventions for multi-agent systems&lt;/strong>: agent teams, tasks, actions, memory, artifact tracking. Esto es lo que falta para que las arquitecturas de agentes complejas tengan vocabulario común. En 2026 está experimental; se espera estabilización a finales de año o principios de 2027.&lt;/p>
&lt;h3 id="herramientas-instrumentadas-el-panorama-2026">Herramientas instrumentadas: el panorama 2026&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Herramienta&lt;/th>
&lt;th>Licencia&lt;/th>
&lt;th>Self-host&lt;/th>
&lt;th>Foco&lt;/th>
&lt;th>Donde brilla&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Langfuse&lt;/strong>&lt;/td>
&lt;td>MIT&lt;/td>
&lt;td>&lt;strong>Sí&lt;/strong>&lt;/td>
&lt;td>LLM observability + evals + prompt mgmt&lt;/td>
&lt;td>Mejor balance OSS, suite completa&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>LangSmith&lt;/strong>&lt;/td>
&lt;td>Comercial&lt;/td>
&lt;td>No&lt;/td>
&lt;td>LangChain/LangGraph nativo&lt;/td>
&lt;td>Si usas LangChain, integración cero-config&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Arize Phoenix&lt;/strong>&lt;/td>
&lt;td>ELv2 (OSS)&lt;/td>
&lt;td>Sí&lt;/td>
&lt;td>OTel-native, RAG fuerte&lt;/td>
&lt;td>Vector DBs, retrieval, embeddings&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Helicone&lt;/strong>&lt;/td>
&lt;td>Comercial + OSS lite&lt;/td>
&lt;td>Sí (lite)&lt;/td>
&lt;td>Proxy simple&lt;/td>
&lt;td>Setup minutos, OpenAI-only&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>OpenLLMetry / Traceloop&lt;/strong>&lt;/td>
&lt;td>Apache 2.0&lt;/td>
&lt;td>Sí&lt;/td>
&lt;td>SDK OTel para LLMs&lt;/td>
&lt;td>Vendor-neutral, exporta a cualquier OTel backend&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Pydantic Logfire&lt;/strong>&lt;/td>
&lt;td>Comercial&lt;/td>
&lt;td>No&lt;/td>
&lt;td>App + LLM unificado&lt;/td>
&lt;td>Si usas Pydantic AI, integración nativa&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Weights &amp;amp; Biases Weave&lt;/strong>&lt;/td>
&lt;td>Comercial&lt;/td>
&lt;td>Limitado&lt;/td>
&lt;td>Experimentación + producción&lt;/td>
&lt;td>Si ya usas W&amp;amp;B para training&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Laminar / Braintrust&lt;/strong>&lt;/td>
&lt;td>Comercial&lt;/td>
&lt;td>No / Sí&lt;/td>
&lt;td>Evals + tracing&lt;/td>
&lt;td>Más recientes, foco en evaluación&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="deep-dive-langfuse">Deep dive: Langfuse&lt;/h3>
&lt;p>Merece detenerse en &lt;a href="https://langfuse.com/">Langfuse&lt;/a> porque es, en 2026, &lt;strong>la elección por defecto entre las opciones open-source&lt;/strong> y la que más equipos han adoptado este año. Es proyecto de &lt;a href="https://github.com/langfuse/langfuse">YC W23&lt;/a>, licencia &lt;strong>MIT&lt;/strong>, y lleva un ritmo de release sostenido con cambios arquitectónicos serios entre versiones.&lt;/p>
&lt;p>&lt;strong>Cuatro pilares declarados&lt;/strong>: observability (tracing), evaluations, prompt management, playground/datasets. Cada uno por separado tiene productos comerciales completos detrás; Langfuse los integra en una sola plataforma con un solo backend.&lt;/p>
&lt;h4 id="el-sdk-v4-otel-native-no-un-sustituto">El SDK v4: OTEL-native, no un sustituto&lt;/h4>
&lt;p>El gran cambio operacional reciente es el &lt;strong>SDK v4&lt;/strong>, una capa fina sobre el cliente oficial de OpenTelemetry. La elección es deliberada: en lugar de mantener un cliente propio que se atrase respecto a las primitives OTel, Langfuse usa el SDK estándar y &lt;strong>enriquece&lt;/strong> los spans con atributos y helpers específicos para LLM. La consecuencia: cualquier código que ya esté instrumentado con OpenTelemetry vainilla (&lt;code>@opentelemetry/sdk-node&lt;/code>, &lt;code>opentelemetry-sdk&lt;/code> en Python) &lt;strong>puede exportar a Langfuse sin cambios mayores&lt;/strong>, y al revés, si mañana quieres migrar de Langfuse a otro backend OTel, los spans son portables.&lt;/p>
&lt;p>En Python el decorador idiomático es &lt;code>@observe&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langfuse&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">observe&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">get_client&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">langfuse&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_client&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@observe&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">buscar_documentos&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># cualquier llamada interna también se traza&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">vector_store&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">similarity_search&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@observe&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">as_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;generation&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">llamar_llm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">prompt&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># marcada como &amp;#34;generation&amp;#34; para que aparezca con metadata LLM&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">openai_client&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">completions&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">...&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@observe&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">pipeline_rag&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pregunta&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">docs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">buscar_documentos&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pregunta&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">llamar_llm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">build_prompt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pregunta&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">docs&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>El árbol de llamadas se captura automáticamente: la traza muestra &lt;code>pipeline_rag&lt;/code> como root span, con &lt;code>buscar_documentos&lt;/code> y &lt;code>llamar_llm&lt;/code> como hijos, anidados. Sin escribir un solo &lt;code>with tracer.start_as_current_span(...)&lt;/code> a mano.&lt;/p>
&lt;p>En TypeScript el equivalente es modular: instalas &lt;code>@langfuse/tracing&lt;/code>, &lt;code>@langfuse/otel&lt;/code> y &lt;code>@opentelemetry/sdk-node&lt;/code>, y puedes usar decoradores TS, context managers o spans manuales —los tres modelos interoperan—. La consecuencia: bibliotecas terceras que emiten spans OTel (&lt;code>openai&lt;/code>, &lt;code>@anthropic-ai/sdk&lt;/code>, instrumentaciones de Vercel AI SDK) se ven en Langfuse sin trabajo adicional.&lt;/p>
&lt;h4 id="arquitectura-self-host-pensada-para-producción-seria">Arquitectura self-host: pensada para producción seria&lt;/h4>
&lt;p>La arquitectura del backend Langfuse tiene &lt;strong>dos decisiones explícitas&lt;/strong> que distinguen su despliegue self-host:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Persistencia primero en S3/Blob Storage&lt;/strong>. Cuando un evento de tracing entra, &lt;strong>se persiste en object storage antes de tocar la base de datos&lt;/strong>. Solo cuando el procesado posterior confirma OK se inserta en Postgres/Clickhouse. Si la DB cae temporalmente, los eventos &lt;strong>no se pierden&lt;/strong>; quedan en S3 esperando reproceso. Para producción donde perder traces de un incidente equivale a perder evidencia, esto es load-bearing.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Migraciones largas como background jobs&lt;/strong>. Los upgrades de schema que en otras plataformas implican ventana de downtime, en Langfuse se ejecutan en background mientras la aplicación sigue sirviendo. El downtime de upgrade se reduce drásticamente.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Los modos de despliegue soportados oficialmente:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Docker Compose&lt;/strong>: para desarrollo y POCs. Un comando, todo arriba.&lt;/li>
&lt;li>&lt;strong>VM&lt;/strong>: un único nodo, contenedores, sin orquestación. Para entornos pequeños.&lt;/li>
&lt;li>&lt;strong>Kubernetes con Helm&lt;/strong>: el modo recomendado para producción. Chart oficial mantenido. Soporta external Postgres, external Clickhouse, external S3, HPA.&lt;/li>
&lt;/ul>
&lt;p>Las dependencias externas en producción típica: &lt;strong>Postgres&lt;/strong> (metadata, prompts, configuración), &lt;strong>Clickhouse&lt;/strong> (eventos de tracing, queries de alta cardinalidad), &lt;strong>S3 o blob compatible&lt;/strong> (eventos pendientes), &lt;strong>Redis&lt;/strong> (cola entre componentes). Sí, son varias piezas; es lo que sostiene la durabilidad y la escala.&lt;/p>
&lt;h4 id="prompt-management-como-ciudadano-de-primera-clase">Prompt management como ciudadano de primera clase&lt;/h4>
&lt;p>Lo que diferencia a Langfuse de las plataformas centradas solo en tracing es que &lt;strong>los prompts viven en Langfuse&lt;/strong>, no en el repo de la aplicación o en hojas de cálculo. Cada prompt tiene:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Nombre y versión&lt;/strong> (v1, v2, v3&amp;hellip;). Cambiar el prompt no requiere redeploy de la app: la app pide el prompt al SDK, que lo cachea y refresca cuando hay versión nueva.&lt;/li>
&lt;li>&lt;strong>Variables tipadas&lt;/strong>: &lt;code>{{user_input}}&lt;/code>, &lt;code>{{context}}&lt;/code>. Render con validación.&lt;/li>
&lt;li>&lt;strong>Tags y labels&lt;/strong>: por entorno (&lt;code>production&lt;/code>, &lt;code>staging&lt;/code>), por equipo, por experimento.&lt;/li>
&lt;li>&lt;strong>Cache cliente y servidor&lt;/strong>: el SDK cachea localmente con TTL configurable, evita roundtrip a Langfuse en cada llamada.&lt;/li>
&lt;li>&lt;strong>Linkage con traces&lt;/strong>: cada trace recoge qué versión exacta de qué prompt se usó. Investigar &amp;ldquo;esta respuesta salió mal&amp;rdquo; lleva al prompt versión Y, no a &amp;ldquo;alguna versión del prompt en algún momento&amp;rdquo;.&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langfuse&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">get_client&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">langfuse&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_client&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">prompt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">langfuse&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_prompt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;rag-system-prompt&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">version&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># o por label: langfuse.get_prompt(&amp;#34;rag-system-prompt&amp;#34;, label=&amp;#34;production&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">compiled&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">prompt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">docs_text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">user_input&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">question&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># &amp;#39;compiled&amp;#39; es el string final, listo para mandar al LLM&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Para equipos que iteran sobre prompts a diario, esto es lo que evita el caos de &amp;ldquo;qué versión del prompt está corriendo realmente en producción ahora mismo&amp;rdquo;.&lt;/p>
&lt;h4 id="evaluations-cuatro-modelos-de-evaluación-combinables">Evaluations: cuatro modelos de evaluación combinables&lt;/h4>
&lt;p>Langfuse cubre los cuatro patrones de evaluación de respuestas:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>LLM-as-a-judge&lt;/strong>: configuras un modelo (típicamente GPT-4 o Claude) con una rúbrica y evalúa cada respuesta. Resultado: score numérico (0-1) y justificación. Aplicable a tracing automático (todas las respuestas) o batch (selección de dataset).&lt;/li>
&lt;li>&lt;strong>User feedback&lt;/strong>: la app permite al usuario marcar respuesta como buena/mala. El feedback se asocia al trace y al prompt version, lo que permite ver qué versiones tienen peor rate.&lt;/li>
&lt;li>&lt;strong>Manual labeling&lt;/strong>: una UI donde labelers humanos puntúan respuestas. Útil para datasets dorados y para evaluar el judge.&lt;/li>
&lt;li>&lt;strong>Custom evaluators vía API/SDK&lt;/strong>: evals propios (un test unitario, una métrica de negocio) reportan score vía API. Se integran con CI.&lt;/li>
&lt;/ul>
&lt;p>Combinadas, dan &lt;strong>regression testing&lt;/strong> del prompt: cambias de v3 a v4, evalúas el dataset dorado con LLM-as-judge, comparas; si v4 empeora en alguno de los segmentos, el merge falla.&lt;/p>
&lt;h4 id="integraciones">Integraciones&lt;/h4>
&lt;p>Langfuse no compite con OpenLLMetry, LangChain o LiteLLM: los &lt;strong>integra&lt;/strong>. Las que están testeadas y documentadas:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>OpenTelemetry&lt;/strong>: cualquier instrumentación OTel emite a Langfuse vía OTLP.&lt;/li>
&lt;li>&lt;strong>LangChain y LangGraph&lt;/strong>: callback nativo que captura toda la cadena.&lt;/li>
&lt;li>&lt;strong>LlamaIndex&lt;/strong>: callback nativo.&lt;/li>
&lt;li>&lt;strong>OpenAI SDK&lt;/strong> (Python y TS): wrapper que añade tracing automáticamente.&lt;/li>
&lt;li>&lt;strong>LiteLLM&lt;/strong>: integración como callback, lo que cubre 100+ proveedores via LiteLLM.&lt;/li>
&lt;li>&lt;strong>OpenLLMetry / Traceloop&lt;/strong>: emiten a Langfuse como cualquier backend OTel.&lt;/li>
&lt;li>&lt;strong>MLflow&lt;/strong>: vía exporter OTel desde MLflow a Langfuse.&lt;/li>
&lt;li>&lt;strong>Vercel AI SDK&lt;/strong>: instrumentación nativa.&lt;/li>
&lt;/ul>
&lt;p>La estrategia es clara: &lt;strong>Langfuse es backend, no SDK&lt;/strong>. Tu equipo elige cómo instrumenta; Langfuse acepta cualquier camino. La consecuencia operativa: cambiar de Langfuse a otro backend OTel mañana es viable.&lt;/p>
&lt;h4 id="cuándo-langfuse-no-es-la-respuesta">Cuándo Langfuse no es la respuesta&lt;/h4>
&lt;p>Para no presentarlo como bala de plata:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Si solo usas LangChain y no tienes recursos para self-host&lt;/strong>: LangSmith te dará integración más fluida (es el mismo equipo).&lt;/li>
&lt;li>&lt;strong>Si tu única necesidad es proxy con cost tracking sin evals&lt;/strong>: Helicone es más simple.&lt;/li>
&lt;li>&lt;strong>Si quieres una solución vendor commercial integrada&lt;/strong>: Datadog LLM Observability, New Relic AI Monitoring o Dynatrace AI son alternativas Enterprise con soporte 24/7.&lt;/li>
&lt;li>&lt;strong>Si tu carga es batch puro de inferencia masiva sin agentes&lt;/strong>: probablemente no necesitas tracing semántico; Prometheus + Grafana con métricas OTel basta.&lt;/li>
&lt;/ul>
&lt;p>Para todo lo demás —apps propias con tracing serio, multi-tenant con cuotas, equipos que iteran prompts a diario, RAG con evaluación continua—, Langfuse es la apuesta segura.&lt;/p>
&lt;p>&lt;strong>Resumen de elección rápido&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>LangChain → LangSmith&lt;/strong> (cero esfuerzo, instrumentación automática).&lt;/li>
&lt;li>&lt;strong>Aplicaciones propias multi-framework con OSS → Langfuse&lt;/strong> (MIT, self-host, completo).&lt;/li>
&lt;li>&lt;strong>RAG con vector stores → Arize Phoenix&lt;/strong> (mejor visibilidad de retrieval).&lt;/li>
&lt;li>&lt;strong>Proxy simple, presupuesto bajo → Helicone&lt;/strong>.&lt;/li>
&lt;li>&lt;strong>Vendor neutrality estricta → OpenLLMetry/Traceloop&lt;/strong>.&lt;/li>
&lt;li>&lt;strong>Pydantic AI → Logfire&lt;/strong> (mismo equipo).&lt;/li>
&lt;/ul>
&lt;h3 id="fortalezas-y-debilidades-del-modelo-instrumentado">Fortalezas y debilidades del modelo instrumentado&lt;/h3>
&lt;p>&lt;strong>Fortalezas&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Profundidad enorme&lt;/strong>: spans anidados con todo el contexto (chain steps, retrieval, embeddings, tool calls).&lt;/li>
&lt;li>&lt;strong>Vocabulario semántico&lt;/strong>: SDK conoce el dominio (LLM, vector store, agent).&lt;/li>
&lt;li>&lt;strong>Madurez&lt;/strong>: tres años de evolución, ecosistema rico, dashboards listos.&lt;/li>
&lt;li>&lt;strong>Evals integradas&lt;/strong>: las plataformas top combinan tracing con evaluación (judge LLM, datasets, regression).&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Debilidades&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Requiere control del código&lt;/strong>: si no puedes instrumentar, no funciona.&lt;/li>
&lt;li>&lt;strong>Trust en la app&lt;/strong>: si la app reporta mal o tiene un bug, la traza también. No es tamper-proof.&lt;/li>
&lt;li>&lt;strong>Acoplamiento al SDK&lt;/strong>: cambios de versión de una librería pueden romper la instrumentación.&lt;/li>
&lt;li>&lt;strong>Cobertura desigual&lt;/strong>: SDKs de Python están maduros; Go, Rust, JS más jóvenes.&lt;/li>
&lt;/ul>
&lt;h2 id="el-enfoque-zero-instrumentation-agentsight">El enfoque zero-instrumentation: AgentSight&lt;/h2>
&lt;p>&lt;a href="https://github.com/eunomia-bpf/agentsight">AgentSight&lt;/a> es el proyecto del grupo &lt;code>eunomia-bpf&lt;/code> que abandera el enfoque opuesto. Su &lt;a href="https://arxiv.org/abs/2508.02736">paper en arxiv (2508.02736)&lt;/a>, presentado en el &lt;em>Workshop on Practical Adoption Challenges of ML for Systems&lt;/em>, formaliza la propuesta. La premisa es directa:&lt;/p>
&lt;blockquote>
&lt;p>&lt;em>Instead of instrumenting the agent, observe it at the system boundary.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;p>Y &amp;ldquo;system boundary&amp;rdquo; significa &lt;strong>el límite del kernel&lt;/strong>: el último punto antes de que un dato salga del proceso hacia la red o el filesystem. Ahí, con eBPF, se ven las cosas tal como son, sin que la aplicación pueda cooperar para esconderlas.&lt;/p>
&lt;h3 id="arquitectura-tres-planos">Arquitectura: tres planos&lt;/h3>
&lt;p>AgentSight monta tres capas:&lt;/p>
&lt;p>&lt;strong>Plano 1 — SSL/TLS uprobes&lt;/strong>. eBPF puede atar programas a funciones de &lt;strong>bibliotecas userspace&lt;/strong> (uprobes). Las funciones objetivo son las de cifrado: &lt;code>SSL_write&lt;/code>, &lt;code>SSL_read&lt;/code> de OpenSSL/BoringSSL, equivalentes en Rustls. AgentSight les pone hooks que &lt;strong>capturan los argumentos&lt;/strong>: el buffer &lt;strong>plaintext&lt;/strong> que la app pasa para que sea cifrado, justo antes de que TLS lo procese. En la recepción, hace lo simétrico: hook después de &lt;code>SSL_read&lt;/code> con el plaintext recién descifrado. Resultado: AgentSight ve el contenido completo de cualquier petición HTTPS que la app haga &lt;strong>sin necesidad de man-in-the-middle ni certificados ni descifrar tráfico&lt;/strong>. El payload es plaintext porque se capturó &lt;strong>antes&lt;/strong> de cifrarse.&lt;/p>
&lt;p>Esto funciona porque las uprobes son baratas (~100 ns por invocación) y porque las apps usan bibliotecas de TLS comunes. Las pocas apps que implementan su propio TLS (raras en producción) escapan a este hook; para esas hace falta un kprobe diferente o instrumentación manual.&lt;/p>
&lt;p>&lt;strong>Plano 2 — Kernel events&lt;/strong>. Paralelamente, AgentSight observa syscalls relevantes a través de tracepoints: &lt;code>execve&lt;/code> (qué procesos arrancan), &lt;code>connect&lt;/code>/&lt;code>accept&lt;/code> (red), &lt;code>read&lt;/code>/&lt;code>write&lt;/code> con file descriptors (filesystem y stdio), &lt;code>unlink&lt;/code>, &lt;code>clone&lt;/code>. Cualquier acción del agente que tenga efecto fuera del proceso pasa por aquí. Esto cubre, entre otros, &lt;strong>comandos shell ejecutados por el agente&lt;/strong> —si un agente Claude Code decide ejecutar &lt;code>rm -rf&lt;/code> para &amp;ldquo;limpiar el proyecto&amp;rdquo;, el &lt;code>execve&lt;/code> se ve aunque la API LLM no lo reporte—.&lt;/p>
&lt;p>&lt;strong>Plano 3 — Correlation engine&lt;/strong>. Los dos planos anteriores producen streams de eventos asíncronos. AgentSight tiene un componente en userspace que los &lt;strong>correlaciona causalmente cross-process&lt;/strong>: una petición HTTP saliente con &lt;code>bash -c rm -rf&lt;/code> puede ser correlada con la respuesta LLM previa que la sugirió, vía PIDs, tiempos y heurísticas. El paper menciona el uso opcional de &lt;strong>un LLM secundario&lt;/strong> (Anthropic Claude por ejemplo) que analiza la secuencia de eventos y produce alertas semánticas: &amp;ldquo;el agente respondió con una tool call que no estaba en la whitelist&amp;rdquo;, &amp;ldquo;la cadena de reasoning lleva 47 iteraciones sin converger&amp;rdquo;.&lt;/p>
&lt;h3 id="stdiocap-capturar-stdio-de-servidores-mcp-locales">&lt;code>stdiocap&lt;/code>: capturar stdio de servidores MCP locales&lt;/h3>
&lt;p>Una pieza específica que merece mención propia es &lt;code>stdiocap&lt;/code>, una herramienta BPF separada incluida en el repo. El &lt;strong>Model Context Protocol (MCP)&lt;/strong>, popularizado por Anthropic en 2024 y mainstream en 2025-2026, tiene dos modos de transport: HTTP/SSE (red) y &lt;strong>stdio&lt;/strong> (entre el cliente y el server que arranca como subproceso). Los servidores MCP locales —los que corren en la misma máquina y son arrancados por el cliente como hijos vía pipes— comunican por stdin/stdout/stderr con JSON-RPC.&lt;/p>
&lt;p>&lt;code>stdiocap&lt;/code> engancha &lt;code>read&lt;/code>/&lt;code>write&lt;/code>/&lt;code>dup&lt;/code> sobre los file descriptors de stdin/stdout/stderr de un proceso target y &lt;strong>registra todo el tráfico JSON-RPC&lt;/strong> entre cliente y server MCP. Es la misma idea que la captura SSL pero para stdio: observas la conversación sin que ni el cliente ni el server lo sepan. Caso de uso típico: ver qué tools del MCP server &lt;code>filesystem-mcp&lt;/code> ha invocado un agente Claude Code en la última hora, qué argumentos pasó, qué errores recibió. Imposible con instrumentación clásica (los servers MCP suelen ser binarios de terceros).&lt;/p>
&lt;h3 id="garantías-tamper-proof-kernel-safety-3-overhead">Garantías: tamper-proof, kernel safety, &amp;lt;3% overhead&lt;/h3>
&lt;p>Tres propiedades hacen a AgentSight interesante para producción:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Tamper-proof&lt;/strong>: la observación ocurre en el kernel (uprobes, syscalls). Una aplicación maliciosa o comprometida no puede falsificar lo que se ve. Comparar con instrumentación: si el agente decide no emitir el span de su acción, no aparece en Langfuse. Aquí no tiene elección.&lt;/li>
&lt;li>&lt;strong>Kernel safety&lt;/strong>: eBPF verifica formalmente que los programas terminen y respeten bounds checks. No puede crashear el kernel. Igual que en el resto de la serie eBPF.&lt;/li>
&lt;li>&lt;strong>&amp;lt;3% CPU overhead&lt;/strong> medido sobre cargas reales de agentes (paper). El número compara favorablemente con instrumentación SDK que típicamente añade 5-10% en aplicaciones intensas.&lt;/li>
&lt;/ul>
&lt;h3 id="lo-que-detecta-out-of-the-box">Lo que detecta out of the box&lt;/h3>
&lt;p>El paper y la documentación destacan tres clases de detección:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Prompt injection en tiempo real&lt;/strong>: el correlation engine puede aplicar reglas o un modelo de detección sobre el plaintext capturado por las uprobes SSL. Si el prompt contiene patrones sospechosos —&amp;ldquo;ignore all previous instructions&amp;rdquo;, system prompt embebido en un user input, instrucciones para exfiltrar datos—, marca alerta.&lt;/li>
&lt;li>&lt;strong>Reasoning loops que gastan recursos&lt;/strong>: agentes que entran en bucles infinitos llamando a herramientas sin progresar. Detectables porque la cadena causal no converge a &amp;ldquo;respuesta final&amp;rdquo; y los tokens se acumulan. El correlation engine los marca.&lt;/li>
&lt;li>&lt;strong>Bottlenecks en multi-agent&lt;/strong>: cuando varios agentes coordinan, AgentSight ve la matriz de comunicaciones entre todos y puede detectar agentes que se bloquean esperando, deadlocks, fan-out excesivo.&lt;/li>
&lt;/ul>
&lt;h2 id="el-choque-y-la-coexistencia">El choque y la coexistencia&lt;/h2>
&lt;p>Las dos familias parecen competir, pero en realidad ven cosas distintas y se complementan en producción.&lt;/p>
&lt;h3 id="lo-que-solo-el-instrumentado-ve">Lo que solo el instrumentado ve&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Variables internas del agente&lt;/strong> que no salen al cable: el estado intermedio de un chain LangChain, los valores antes de pasarlos a una herramienta, el cómo se construye un prompt a partir de un template con vars internos.&lt;/li>
&lt;li>&lt;strong>Spans semánticos profundos&lt;/strong>: &lt;code>retrieval &amp;gt; embed &amp;gt; vector_search &amp;gt; rerank &amp;gt; format_context &amp;gt; prompt_template &amp;gt; llm&lt;/code>. AgentSight ve solo la llamada final al LLM; el camino para construirla es invisible.&lt;/li>
&lt;li>&lt;strong>Evaluaciones&lt;/strong>: scoring de respuestas, judge LLMs, regresión de calidad. Esto vive solo en plataformas instrumentadas.&lt;/li>
&lt;/ul>
&lt;h3 id="lo-que-solo-ebpf-ve">Lo que solo eBPF ve&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Binarios opacos&lt;/strong>: Claude Code, Cursor, Gemini CLI, agentes de terceros. No tienes el código; no puedes instrumentarlos. Solo eBPF los ve.&lt;/li>
&lt;li>&lt;strong>Acciones a nivel sistema&lt;/strong>: el agente decide ejecutar &lt;code>git push --force&lt;/code> o &lt;code>kubectl delete&lt;/code>. La acción se ve en el &lt;code>execve&lt;/code>. La instrumentación del agente puede no reportarla (especialmente si fue un comando que el agente generó como output sin pasar por una &amp;ldquo;tool&amp;rdquo; explícita).&lt;/li>
&lt;li>&lt;strong>Tamper-proof audit&lt;/strong>: para compliance regulatorio (HIPAA, SOC2, NIS2), tener observación que la app no puede burlar tiene valor formal. eBPF lo da.&lt;/li>
&lt;li>&lt;strong>MCP servers locales con stdio&lt;/strong>: invisibles para instrumentación clásica salvo que cada server emita sus propios spans (raro).&lt;/li>
&lt;/ul>
&lt;h3 id="lo-que-ambos-ven-complementariamente">Lo que ambos ven, complementariamente&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Prompts y completions&lt;/strong>: instrumentado los emite con metadata rica; eBPF los captura del cable. Cross-check perfecto para detectar discrepancias.&lt;/li>
&lt;li>&lt;strong>Llamadas a APIs externas&lt;/strong>: APM lo marca; eBPF lo confirma a nivel kernel.&lt;/li>
&lt;li>&lt;strong>Latencia&lt;/strong>: APM por span; eBPF mide RTT a nivel TCP y conectividad red.&lt;/li>
&lt;/ul>
&lt;h3 id="matriz-de-decisión">Matriz de decisión&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Caso&lt;/th>
&lt;th>Instrumentado&lt;/th>
&lt;th>eBPF (AgentSight)&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>App propia con LangChain&lt;/td>
&lt;td>&lt;strong>Sí, primero&lt;/strong>&lt;/td>
&lt;td>Opcional&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>App propia multi-framework&lt;/td>
&lt;td>&lt;strong>Sí&lt;/strong>&lt;/td>
&lt;td>Opcional&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Binario de terceros (Claude Code, Cursor)&lt;/td>
&lt;td>&lt;strong>No funciona&lt;/strong>&lt;/td>
&lt;td>&lt;strong>Sí, único camino&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Cumplimiento normativo tamper-proof&lt;/td>
&lt;td>Insuficiente&lt;/td>
&lt;td>&lt;strong>Sí, requerido&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Multi-tenant zero-trust&lt;/td>
&lt;td>Insuficiente&lt;/td>
&lt;td>&lt;strong>Sí, requerido&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Servidores MCP locales (stdio)&lt;/td>
&lt;td>Difícil&lt;/td>
&lt;td>&lt;strong>Sí, con stdiocap&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Evaluación de calidad de respuestas&lt;/td>
&lt;td>&lt;strong>Sí, requerido&lt;/strong>&lt;/td>
&lt;td>No (fuera de scope)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Profundidad de chain interno&lt;/td>
&lt;td>&lt;strong>Sí, requerido&lt;/strong>&lt;/td>
&lt;td>No (caja negra para AgentSight)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Reasoning loop detection&lt;/td>
&lt;td>Posible con plumbing&lt;/td>
&lt;td>&lt;strong>Sí, integrado&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Prompt injection en tiempo real&lt;/td>
&lt;td>Posible (post-procesado)&lt;/td>
&lt;td>&lt;strong>Sí, en stream&lt;/strong>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>La conclusión natural: &lt;strong>para apps propias, instrumentado; para binarios opacos o compliance, eBPF; para todo lo importante, ambos&lt;/strong>.&lt;/p>
&lt;h2 id="arquitectura-de-referencia-2026">Arquitectura de referencia 2026&lt;/h2>
&lt;p>Cuatro recetas que cubren el grueso de los casos reales:&lt;/p>
&lt;h3 id="setup-a--aplicación-propia-con-langchain-o-similar">Setup A — Aplicación propia con LangChain o similar&lt;/h3>
&lt;p>Necesidades: profundidad, evals, equipo cómodo con SDKs.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Langfuse self-host&lt;/strong> o &lt;strong>LangSmith cloud&lt;/strong> como backend.&lt;/li>
&lt;li>&lt;strong>OpenLLMetry SDK&lt;/strong> o &lt;strong>LangSmith SDK&lt;/strong> instrumentando el código.&lt;/li>
&lt;li>&lt;strong>OpenTelemetry Collector&lt;/strong> entre la app y el backend para flexibilidad de routing (a Langfuse + Tempo + Loki por ejemplo).&lt;/li>
&lt;li>&lt;strong>Hubble&lt;/strong> para la capa de red en el cluster (latencia inter-pod, drop attribution).&lt;/li>
&lt;/ul>
&lt;h3 id="setup-b--productivizar-un-binario-opaco-claude-code-gemini-cli">Setup B — Productivizar un binario opaco (Claude Code, Gemini CLI)&lt;/h3>
&lt;p>Necesidades: observar sin tocar, auditar, controlar coste.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>AgentSight&lt;/strong> desplegado como DaemonSet sobre el cluster (o standalone en el nodo).&lt;/li>
&lt;li>&lt;strong>Grafana con dashboards&lt;/strong> alimentados por las métricas de AgentSight.&lt;/li>
&lt;li>&lt;strong>Exportador OTLP&lt;/strong> de AgentSight a un backend OTel (Tempo, Jaeger). Los spans usarán las semantic conventions GenAI cuando se estandaricen del todo.&lt;/li>
&lt;li>&lt;strong>Tetragon&lt;/strong> opcional para política sobre qué puede ejecutar el agente (Sigkill si intenta &lt;code>rm -rf&lt;/code> o similar).&lt;/li>
&lt;/ul>
&lt;h3 id="setup-c--plataforma-multi-tenant-zero-trust">Setup C — Plataforma multi-tenant zero-trust&lt;/h3>
&lt;p>Necesidades: agentes de distintos clientes corriendo en el mismo cluster, auditoría obligatoria, ninguno confía en el otro.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>AgentSight&lt;/strong> como capa de auditoría tamper-proof. Compliance lo requiere.&lt;/li>
&lt;li>&lt;strong>Langfuse multi-tenant&lt;/strong> para los clientes que sí instrumentan.&lt;/li>
&lt;li>&lt;strong>Tetragon&lt;/strong> con &lt;code>TracingPolicyNamespaced&lt;/code> por tenant (políticas distintas por namespace).&lt;/li>
&lt;li>&lt;strong>Hubble&lt;/strong> con flow logs persistentes para forensics.&lt;/li>
&lt;li>&lt;strong>Cilium NetworkPolicy&lt;/strong> para aislar tenants entre sí en red.&lt;/li>
&lt;/ul>
&lt;h3 id="setup-d--servidor-mcp-local-en-una-workstation">Setup D — Servidor MCP local en una workstation&lt;/h3>
&lt;p>Necesidades: ver qué hace un agente con un MCP server stdio.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>AgentSight stdiocap&lt;/strong> apuntando al PID del cliente o del server.&lt;/li>
&lt;li>Captura JSON-RPC completo a fichero o a un endpoint OTLP.&lt;/li>
&lt;li>Visualización: Grafana o simplemente &lt;code>jq&lt;/code> sobre el log.&lt;/li>
&lt;/ul>
&lt;p>Caso de uso real: si estás integrando un MCP server propio y quieres ver qué tool calls hace un agente Claude Code o Cursor a tu server, &lt;code>stdiocap&lt;/code> es la forma más limpia. No necesitas modificar ni cliente ni server.&lt;/p>
&lt;h2 id="trampas-operativas">Trampas operativas&lt;/h2>
&lt;h3 id="datos-sensibles-en-prompts-instrumentado">Datos sensibles en prompts (instrumentado)&lt;/h3>
&lt;p>Por defecto, Langfuse, LangSmith y similares capturan &lt;strong>el contenido completo&lt;/strong> de prompts y completions. Si tu app procesa PII, secretos, datos médicos, &lt;strong>eso va a tu backend de observabilidad&lt;/strong>. Configurar &lt;strong>redacción&lt;/strong> o &lt;strong>content-opt-out&lt;/strong> antes de pasar a producción es obligado. OTel GenAI tiene flags específicos (&lt;code>OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=false&lt;/code>) para evitarlo.&lt;/p>
&lt;h3 id="datos-sensibles-en-prompts-agentsight">Datos sensibles en prompts (AgentSight)&lt;/h3>
&lt;p>Mismo problema, peor: AgentSight captura &lt;strong>literalmente lo que va al cable&lt;/strong>, plaintext. Si el agente conversó con &lt;code>api.openai.com&lt;/code> con un prompt que contenía datos sensibles, AgentSight tiene ese plaintext. Hay que cifrar o redactar antes de almacenar.&lt;/p>
&lt;h3 id="certificados-pinned-o-tls-no-estándar">Certificados pinned o TLS no estándar&lt;/h3>
&lt;p>Algunas apps de seguridad alta hacen certificate pinning o usan implementaciones de TLS no convencionales (Go&amp;rsquo;s &lt;code>crypto/tls&lt;/code>, BoringSSL custom). En esos casos, las uprobes a &lt;code>libssl&lt;/code> no las cubren. AgentSight detecta cuándo no puede observar y reporta gap; igual hay que añadir hooks específicos al SDK alternativo.&lt;/p>
&lt;h3 id="volumen-de-tokens-y-storage">Volumen de tokens y storage&lt;/h3>
&lt;p>Una aplicación con tráfico medio puede generar &lt;strong>millones de tokens al día&lt;/strong>. Si los almacenas todos en Langfuse o Phoenix con retención largos, la base de datos crece deprisa. Estrategias: sampling agresivo, retención corta para sesiones normales y larga solo para errores/anomalías, redaction de contenido y guardar solo metadata.&lt;/p>
&lt;h3 id="tracing-con-sampling-y-consistencia">Tracing con sampling y consistencia&lt;/h3>
&lt;p>Para reducir coste, muchas instalaciones samplean: solo 1 de cada N traces se persiste. &lt;strong>Cuidado con el sampling no consistente&lt;/strong>: un trace puede llevar varios spans en múltiples servicios, y si la decisión de samplear se toma per-span, acabas con traces incompletos. OTel tiene &lt;strong>head sampling&lt;/strong> (en el SDK al principio) que es consistente, y &lt;strong>tail sampling&lt;/strong> (en el collector al final) que permite reglas más finas. Para LLM, el tail sampling es ideal: muestrea todo, descarta solo las traces &amp;ldquo;normales&amp;rdquo; y conserva las que tienen errores, latencia alta o cost alto.&lt;/p>
&lt;h3 id="multi-agent-y-trace-propagation">Multi-agent y trace propagation&lt;/h3>
&lt;p>Cuando agente A llama a agente B, hay que &lt;strong>propagar el trace context&lt;/strong> (W3C Trace Context headers) para que se vea como un árbol único. Si no lo haces, ves dos traces inconexos. Las plataformas modernas lo hacen automáticamente con &lt;code>inject&lt;/code>/&lt;code>extract&lt;/code>, pero si tu transport entre agentes es custom (vía Redis pub/sub, vía DB), tienes que propagar a mano.&lt;/p>
&lt;h3 id="coste-de-las-uprobes-en-bibliotecas-críticas">Coste de las uprobes en bibliotecas críticas&lt;/h3>
&lt;p>Hookear &lt;code>libssl&lt;/code> añade ~100 ns por invocación. En cargas de tráfico TLS extremo (decenas de miles de conexiones/s por core), eso suma. AgentSight lo mantiene por debajo de 3% en cargas típicas de agentes (que son chatty pero no networking-intensive). Si tu uso fuese sniffing de todo el HTTPS del nodo, podría doler más.&lt;/p>
&lt;h2 id="lo-que-no-hemos-cubierto-próxima-serie">Lo que no hemos cubierto (próxima serie)&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Evals&lt;/strong>: la siguiente capa después de tracing. Phoenix, Langfuse, LangSmith y compañía ofrecen evaluación de respuestas (judge LLM, datasets, regression). Es un mundo aparte.&lt;/li>
&lt;li>&lt;strong>Guardrails y safety&lt;/strong>: NeMo Guardrails, Llama Guard, Llama Prompt Guard, evaluadores específicos para prompt injection y jailbreaks.&lt;/li>
&lt;li>&lt;strong>MCP server observability profunda&lt;/strong>: cómo OpenTelemetry GenAI conventions están extendiéndose a MCP servers para trace-aware tools.&lt;/li>
&lt;li>&lt;strong>eBPF + on-device inference&lt;/strong>: cuando el LLM corre localmente vía vLLM o llama.cpp, las uprobes pueden ver la cola tokens-output ANTES de que vayan al cliente. Territorio nuevo.&lt;/li>
&lt;li>&lt;strong>Análisis estadístico de flows de agentes&lt;/strong>: detectar drift, outliers, patrones que indican degradación.&lt;/li>
&lt;/ul>
&lt;h2 id="cerrando-la-serie-ebpf">Cerrando la serie eBPF&lt;/h2>
&lt;p>Esta serie de cuatro artículos ha recorrido eBPF desde el primer principio hasta la frontera 2026:&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://blog.lo0.es/posts/ebpf-cilium-tcp-ip-bypass/">eBPF de cero a Cilium&lt;/a> — qué es eBPF, hooks de networking, cómo Cilium se salta la pila TCP/IP, BGP Control Plane v2.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/posts/tetragon-runtime-security/">Tetragon: seguridad de runtime&lt;/a> — observabilidad y enforcement de procesos en el kernel.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/posts/hubble-observabilidad-ebpf/">Hubble: observabilidad de red&lt;/a> — flow logs L3-L7 y la frontera con los agentes IA.&lt;/li>
&lt;li>&lt;strong>Este&lt;/strong> — AgentSight, tracing de LLMs, instrumentado vs zero-instrumentation.&lt;/li>
&lt;/ol>
&lt;p>Si has llegado hasta aquí tienes el mapa para sentarte con un equipo de plataforma, de seguridad o de IA en 2026 y reconocer qué hace cada pieza, qué problema resuelve y por dónde empezar. Toda esa pila —Cilium para CNI y BGP, Tetragon para seguridad de runtime, Hubble para observabilidad de red, AgentSight para agentes IA— compartiendo eBPF como sustrato común, gobernanza Cloud Native y vocabulario OpenTelemetry. Es la arquitectura limpia que la industria pidió hace una década y por fin existe.&lt;/p>
&lt;h2 id="referencias">Referencias&lt;/h2>
&lt;p>AgentSight:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/eunomia-bpf/agentsight">AgentSight GitHub (eunomia-bpf)&lt;/a> — el proyecto.&lt;/li>
&lt;li>&lt;a href="https://arxiv.org/abs/2508.02736">AgentSight: System-Level Observability for AI Agents Using eBPF (arxiv 2508.02736)&lt;/a> — paper formal.&lt;/li>
&lt;li>&lt;a href="https://dl.acm.org/doi/10.1145/3766882.3767169">AgentSight ACM workshop publication&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://eunomia.dev/blog/2025/08/26/agentsight-keeping-your-ai-agents-under-control-with-ebpf-powered-system-observability/">AgentSight blog post (eunomia.dev)&lt;/a> — descripción accesible.&lt;/li>
&lt;/ul>
&lt;p>OpenTelemetry GenAI semantic conventions:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://opentelemetry.io/docs/specs/semconv/gen-ai/">OpenTelemetry — Semantic conventions for generative AI systems&lt;/a> — referencia oficial.&lt;/li>
&lt;li>&lt;a href="https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/">Semantic conventions for generative client AI spans&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-metrics/">Semantic conventions for generative AI metrics&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://opentelemetry.io/blog/2026/genai-observability/">Inside the LLM Call: GenAI Observability with OpenTelemetry (OTel blog 2026)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://github.com/open-telemetry/semantic-conventions/issues/2664">Multi-agent Semantic Conventions (GitHub issue #2664)&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>Plataformas instrumentadas:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://langfuse.com/">Langfuse&lt;/a> — MIT, self-host + cloud.&lt;/li>
&lt;li>&lt;a href="https://www.langchain.com/langsmith">LangSmith&lt;/a> — LangChain team.&lt;/li>
&lt;li>&lt;a href="https://phoenix.arize.com/">Arize Phoenix&lt;/a> — OSS, OTel-native.&lt;/li>
&lt;li>&lt;a href="https://www.helicone.ai/">Helicone&lt;/a> — proxy simple.&lt;/li>
&lt;li>&lt;a href="https://github.com/traceloop/openllmetry">OpenLLMetry (Traceloop)&lt;/a> — Apache 2.0, SDK OTel.&lt;/li>
&lt;li>&lt;a href="https://pydantic.dev/docs/logfire/get-started/ai-observability/">Pydantic Logfire — AI observability&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>Comparativas 2026:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.braintrust.dev/articles/langfuse-alternatives-2026">Langfuse alternatives 2026 (Braintrust)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://www.braintrust.dev/articles/best-llm-tracing-tools-2026">7 best LLM tracing tools for multi-agent AI systems (2026)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://medium.com/@kanerika/llmops-observability-langsmith-vs-arize-vs-langfuse-vs-w-b-f1baeabd1bbf">LLMOps Observability: LangSmith vs Arize vs Langfuse vs W&amp;amp;B&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://www.firecrawl.dev/blog/best-llm-observability-tools">Best LLM Observability Tools in 2026 (Firecrawl)&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://www.spheron.network/blog/llm-observability-gpu-cloud-langfuse-arize-phoenix-helicone/">LLM Observability on GPU Cloud (Spheron 2026 guide)&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>Cross-references de la serie:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://blog.lo0.es/posts/ebpf-cilium-tcp-ip-bypass/">eBPF de cero a Cilium&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/posts/tetragon-runtime-security/">Tetragon: seguridad de runtime&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/posts/hubble-observabilidad-ebpf/">Hubble: observabilidad de red&lt;/a>.&lt;/li>
&lt;li>Serie de inferencia LLM: &lt;a href="https://blog.lo0.es/posts/kv-cache-fundamentos/">KV cache&lt;/a>, &lt;a href="https://blog.lo0.es/posts/vllm-kubernetes/">vLLM en Kubernetes&lt;/a>, &lt;a href="https://blog.lo0.es/posts/pagedattention-deep-dive/">PagedAttention&lt;/a>, &lt;a href="https://blog.lo0.es/posts/operators-llm-kubernetes/">Operators LLM K8s&lt;/a>.&lt;/li>
&lt;/ul></description></item></channel></rss>