{"id":6535,"date":"2026-09-29T08:57:00","date_gmt":"2026-09-29T06:57:00","guid":{"rendered":"https:\/\/blog-david.moreno-morales.com\/?p=6535"},"modified":"2026-09-27T20:59:56","modified_gmt":"2026-09-27T18:59:56","slug":"observabilidad-aplicaciones-ia","status":"publish","type":"post","link":"https:\/\/blog-david.moreno-morales.com\/index.php\/2026\/09\/29\/observabilidad-aplicaciones-ia\/","title":{"rendered":"Observabilidad para aplicaciones con IA: qu\u00e9 medir m\u00e1s all\u00e1 de logs y errores"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"6535\" class=\"elementor elementor-6535\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-1f790ae elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"1f790ae\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-858b1f5\" data-id=\"858b1f5\" data-element_type=\"column\" data-e-type=\"column\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-61e0e1f elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"61e0e1f\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-inner-column elementor-element elementor-element-1cc40bf\" data-id=\"1cc40bf\" data-element_type=\"column\" data-e-type=\"column\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-085053d elementor-widget elementor-widget-text-editor\" data-id=\"085053d\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p data-pm-slice=\"1 1 []\">Cuando una aplicaci\u00f3n tradicional empieza a comportarse mal, solemos buscar se\u00f1ales conocidas: errores HTTP, excepciones, consumo de CPU, memoria, consultas lentas o mensajes en los logs.<\/p><p data-pm-slice=\"1 1 []\">Con una aplicaci\u00f3n basada en inteligencia artificial, esas se\u00f1ales siguen siendo necesarias. El problema es que ya no son suficientes.<\/p><p>Imagina que un agente tarda 35 segundos en responder. La petici\u00f3n termina correctamente, no aparece ninguna excepci\u00f3n y la infraestructura funciona con normalidad. Desde el punto de vista de la observabilidad tradicional, quiz\u00e1 no haya ning\u00fan incidente.<\/p><p>Pero quedan muchas preguntas abiertas. \u00bfEl modelo tard\u00f3 demasiado? \u00bfSe realizaron m\u00e1s llamadas de las previstas? \u00bfUna herramienta respondi\u00f3 lentamente? \u00bfEl agente entr\u00f3 en un bucle? \u00bfSe enviaron demasiados tokens? \u00bfHubo reintentos? \u00bfEl retrieval recuper\u00f3 informaci\u00f3n irrelevante? \u00bfLa respuesta fue t\u00e9cnicamente correcta pero innecesariamente cara?<\/p><p>La observabilidad de aplicaciones con IA necesita responder a todas esas preguntas. Y para conseguirlo debemos dejar de pensar \u00fanicamente en logs y empezar a observar la ejecuci\u00f3n completa.<\/p><h2>De observar servicios a observar ejecuciones<\/h2><p>En una aplicaci\u00f3n web convencional podemos imaginar una petici\u00f3n relativamente sencilla:<\/p><p>Usuario \u2192 API \u2192 Base de datos \u2192 Respuesta<\/p><p>Una aplicaci\u00f3n con IA puede ejecutar algo mucho m\u00e1s parecido a esto:<\/p><p>\u00a0 \u00a0 \u00a0 \u00a0 Usuario \u2192 Aplicaci\u00f3n \u2192 LLM \u2192 Tool call \u2192 API externa \u2192 LLM \u2192 Retrieval \u2192 LLM \u2192 Respuesta<\/p><p>Adem\u00e1s, cualquiera de esos pasos puede repetirse. Un agente puede decidir utilizar una herramienta, analizar su resultado, llamar a otra, volver al modelo y repetir el proceso hasta obtener una respuesta final.<\/p><p>Por eso el elemento fundamental de observabilidad deja de ser \u00fanicamente la petici\u00f3n HTTP. Necesitamos observar el workflow completo.<\/p><p>Una buena traza deber\u00eda permitir reconstruir la ejecuci\u00f3n desde que entra la petici\u00f3n del usuario hasta que se genera la respuesta final.<\/p><h2>Las trazas se convierten en la pieza central<\/h2><p>OpenTelemetry lleva a\u00f1os proporcionando un est\u00e1ndar abierto para trabajar con trazas, m\u00e9tricas y logs en sistemas distribuidos.<\/p><p>La llegada de la IA generativa ha a\u00f1adido nuevas necesidades. Actualmente existen convenciones sem\u00e1nticas espec\u00edficas para GenAI que contemplan operaciones como inferencia, retrieval, memoria y ejecuci\u00f3n de herramientas.<\/p><p>La idea es sencilla: representar las operaciones de IA mediante spans dentro de una traza distribuida.<\/p><p>Una ejecuci\u00f3n podr\u00eda verse as\u00ed:<\/p><pre><code class=\"language-text\">agent.run                        4.82 s\n\u251c\u2500\u2500 model.inference              1.34 s\n\u251c\u2500\u2500 execute_tool                 0.61 s\n\u2502   \u2514\u2500\u2500 database.query           0.48 s\n\u2514\u2500\u2500 model.inference              2.21 s<\/code><\/pre><p>De repente, una pregunta como \u201c\u00bfpor qu\u00e9 esta respuesta tard\u00f3 cinco segundos?\u201d resulta mucho m\u00e1s f\u00e1cil de investigar.<\/p><p>No vemos simplemente que la petici\u00f3n tard\u00f3 cinco segundos, vemos d\u00f3nde se consumi\u00f3 ese tiempo. Esta diferencia es fundamental para diagnosticar agentes.<\/p><h2>1. Latencia: medir mucho m\u00e1s que el tiempo total<\/h2><p>La primera m\u00e9trica evidente sigue siendo la latencia, pero medir \u00fanicamente el tiempo total de respuesta puede esconder el problema real.<\/p><p>Conviene separar al menos:<\/p><ul data-spread=\"false\"><li><p>latencia total del workflow;<\/p><\/li><li><p>latencia de cada llamada al modelo;<\/p><\/li><li><p>latencia de cada herramienta;<\/p><\/li><li><p>latencia del retrieval;<\/p><\/li><li><p>tiempo empleado en reintentos;<\/p><\/li><li><p>tiempo hasta comenzar a recibir la respuesta cuando existe streaming.<\/p><\/li><\/ul><p>Adem\u00e1s, las medias pueden resultar enga\u00f1osas. En producci\u00f3n suele ser m\u00e1s \u00fatil observar percentiles como p50, p95 y p99.<\/p><p>Un agente podr\u00eda tener una latencia media perfectamente aceptable mientras un porcentaje peque\u00f1o de ejecuciones tarda varias veces m\u00e1s.<\/p><p>La pregunta interesante no es solamente: \u00bfCu\u00e1nto tarda mi aplicaci\u00f3n?<\/p><p>Sino: \u00bfQu\u00e9 componente est\u00e1 provocando las ejecuciones lentas?<\/p><p>Las trazas permiten responder a la segunda.<\/p><h2>2. Tokens: una m\u00e9trica t\u00e9cnica y econ\u00f3mica<\/h2><p>En aplicaciones con LLMs, los tokens son una de las se\u00f1ales m\u00e1s importantes. Conviene registrar, cuando el proveedor lo permita:<\/p><pre><code class=\"language-text\">input_tokens\noutput_tokens\ncached_tokens\nreasoning_tokens\ntotal_tokens<\/code><\/pre><p>No solo para calcular costes. Un crecimiento inesperado del n\u00famero de tokens puede revelar problemas arquitect\u00f3nicos.<\/p><p>Por ejemplo:<\/p><ul data-spread=\"false\"><li><p>prompts que acumulan demasiado contexto;<\/p><\/li><li><p>historiales de conversaci\u00f3n que crecen indefinidamente;<\/p><\/li><li><p>documentos excesivamente grandes enviados al modelo;<\/p><\/li><li><p>agentes que realizan m\u00e1s iteraciones de las necesarias;<\/p><\/li><li><p>herramientas que devuelven informaci\u00f3n demasiado extensa.<\/p><\/li><\/ul><p>Por eso resulta especialmente \u00fatil observar tokens por ejecuci\u00f3n y no \u00fanicamente\u00a0tokens totales del d\u00eda.<\/p><p>Dos aplicaciones pueden consumir un mill\u00f3n de tokens diarios y comportarse de manera completamente diferente. Una puede atender 10.000 solicitudes eficientes, la otra puede atender 500 workflows extraordinariamente caros.<\/p><h2>3. Coste por workflow<\/h2><p>Los tokens permiten construir otra m\u00e9trica operativa muy \u00fatil: <code class=\"language-text\">coste_por_ejecucion<\/code><\/p><p>Tambi\u00e9n podemos agregarla por:<\/p><pre><code class=\"language-text\">coste_por_usuario\ncoste_por_agente\ncoste_por_modelo\ncoste_por_funcionalidad\ncoste_por_cliente<\/code><\/pre><p>Esto permite detectar algo que la observabilidad tradicional raramente necesitaba considerar: una aplicaci\u00f3n puede estar t\u00e9cnicamente sana y econ\u00f3micamente degradada.<\/p><p>No hay errores, no hay ca\u00edda del servicio, la latencia incluso puede ser correcta, pero una modificaci\u00f3n en el prompt ha duplicado el consumo de tokens. Desde la perspectiva del negocio, eso tambi\u00e9n es una regresi\u00f3n.<\/p><h2>4. Tool calls: observar las decisiones del agente<\/h2><p>Cuando introducimos agentes aparece otra dimensi\u00f3n importante, el modelo ya no se limita a producir texto, puede decidir ejecutar acciones.<\/p><p>Por ejemplo:<\/p><pre><code class=\"language-text\">buscar_cliente()\nconsultar_pedido()\nbuscar_documentacion()\nejecutar_consulta_sql()\nenviar_email()<\/code><\/pre><p>Por tanto, deber\u00edamos observar qu\u00e9 herramientas utiliza el agente y c\u00f3mo las utiliza.<\/p><p>Algunas m\u00e9tricas interesantes son:<\/p><pre><code class=\"language-text\">tool_calls_por_ejecucion\ntool_error_rate\ntool_latency\ntool_retry_count<\/code><\/pre><p>Pero tambi\u00e9n conviene conservar la relaci\u00f3n causal, queremos poder reconstruir algo parecido a:<\/p><pre><code class=\"language-text\">Modelo\n  \u2193\ndecide ejecutar buscar_cliente\n  \u2193\nTool call\n  \u2193\nresultado\n  \u2193\nModelo\n  \u2193\ndecide ejecutar consultar_pedido<\/code><\/pre><p>Esto permite distinguir un problema de infraestructura de un problema de razonamiento u orquestaci\u00f3n. Una API puede responder perfectamente en 100 milisegundos.<\/p><p>Pero si el agente la llama doce veces cuando deber\u00eda llamarla una, el problema est\u00e1 en otro sitio.<\/p><h2>5. Reintentos y bucles<\/h2><p>Los retries merecen atenci\u00f3n especial. Un retry puede ser totalmente leg\u00edtimo, diez retries pueden indicar un problema.<\/p><p>En sistemas de agentes interesa observar:<\/p><pre><code class=\"language-text\">iterations_per_run\nmodel_calls_per_run\ntool_calls_per_run\nretry_count<\/code><\/pre><p>y establecer distribuciones normales para cada workflow. Si normalmente un agente resuelve una tarea utilizando dos llamadas al modelo y repentinamente empieza a necesitar siete, existe una regresi\u00f3n aunque todas las ejecuciones terminen correctamente.<\/p><p>Esta es una caracter\u00edstica importante de los sistemas con IA: el \u00e9xito funcional no implica eficiencia operativa.<\/p><h2>6. Errores: HTTP 500 ya no cuenta toda la historia<\/h2><p>Los errores tradicionales contin\u00faan siendo importantes:<\/p><ul data-spread=\"false\"><li><p>timeouts;<\/p><\/li><li><p>errores HTTP;<\/p><\/li><li><p>excepciones;<\/p><\/li><li><p>rate limits;<\/p><\/li><li><p>errores de autenticaci\u00f3n;<\/p><\/li><li><p>servicios externos no disponibles.<\/p><\/li><\/ul><p>Pero aparecen otras categor\u00edas.<\/p><p>Por ejemplo:<\/p><pre><code class=\"language-text\">tool_selection_error\ninvalid_tool_arguments\nmax_iterations_reached\nguardrail_triggered\ncontext_limit\nstructured_output_validation_error<\/code><\/pre><p>Incluso podemos tener ejecuciones t\u00e9cnicamente exitosas pero funcionalmente in\u00fatiles.<\/p><p>El modelo responde, la API devuelve 200, pero la respuesta no satisface la tarea.<\/p><p>Esto introduce una frontera interesante entre observabilidad y evaluaci\u00f3n de calidad.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-26a56fa elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"26a56fa\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-bf5ce92\" data-id=\"bf5ce92\" data-element_type=\"column\" data-e-type=\"column\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2c79896 elementor-widget elementor-widget-image\" data-id=\"2c79896\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/blog-david.moreno-morales.com\/wp-content\/uploads\/2026\/09\/observa_002-1024x576.png\" class=\"attachment-large size-large wp-image-6536\" alt=\"De un log aislado a una traza end-to-end\" \/>\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">De un log aislado a una traza end-to-end<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-5d576d9\" data-id=\"5d576d9\" data-element_type=\"column\" data-e-type=\"column\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d7256b4 elementor-widget elementor-widget-image\" data-id=\"d7256b4\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/blog-david.moreno-morales.com\/wp-content\/uploads\/2026\/09\/observa_003-1024x576.png\" class=\"attachment-large size-large wp-image-6537\" alt=\"Las cinco se\u00f1ales que hay que med\" \/>\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">Las cinco se\u00f1ales que hay que med<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-e8ae2ac elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"e8ae2ac\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-inner-column elementor-element elementor-element-7c91588\" data-id=\"7c91588\" data-element_type=\"column\" data-e-type=\"column\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-af8d6c7 elementor-widget elementor-widget-text-editor\" data-id=\"af8d6c7\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<h2 data-pm-slice=\"1 1 []\">7. Observabilidad y evaluaci\u00f3n no son lo mismo<\/h2><p>Conviene separar ambos conceptos. La observabilidad intenta responder:<\/p><blockquote><p>\u00bfQu\u00e9 ocurri\u00f3 durante esta ejecuci\u00f3n?<\/p><\/blockquote><p>La evaluaci\u00f3n intenta responder:<\/p><blockquote><p>\u00bfFue buena la respuesta?<\/p><\/blockquote><p>Son problemas diferentes, aunque deber\u00edan conectarse. Podemos imaginar una traza con atributos como:<\/p><pre><code class=\"language-text\">trace_id\nmodel\ninput_tokens\noutput_tokens\nlatency\ntool_calls\nretry_count<\/code><\/pre><p>y asociarle posteriormente una evaluaci\u00f3n:<\/p><pre><code class=\"language-text\">correctness_score\nrelevance_score\ngroundedness\nuser_feedback<\/code><\/pre><p>Esta combinaci\u00f3n es extremadamente \u00fatil. Por ejemplo, podr\u00edamos descubrir que las respuestas con peor evaluaci\u00f3n aparecen cuando:<\/p><ul data-spread=\"false\"><li><p>se utiliza determinado modelo;<\/p><\/li><li><p>el retrieval devuelve pocos documentos;<\/p><\/li><li><p>el agente supera determinado n\u00famero de iteraciones;<\/p><\/li><li><p>una herramienta concreta falla;<\/p><\/li><li><p>el contexto supera cierto tama\u00f1o.<\/p><\/li><\/ul><p>Ah\u00ed es donde observabilidad y evaluaci\u00f3n empiezan a convertirse en una herramienta real de ingenier\u00eda.<\/p><h2>8. El modelo tambi\u00e9n debe formar parte de la telemetr\u00eda<\/h2><p>En sistemas tradicionales solemos registrar la versi\u00f3n del servicio desplegado. Con IA debemos hacer algo parecido con los modelos.<\/p><p>Resulta \u00fatil registrar informaci\u00f3n como:<\/p><pre><code class=\"language-text\">model\nprovider\nworkflow_version\nprompt_version\nagent_version<\/code><\/pre><p>Esto permite comparar comportamiento entre versiones. Si cambiamos un modelo podemos preguntar:<\/p><ul data-spread=\"false\"><li><p>\u00bfha cambiado la latencia?<\/p><\/li><li><p>\u00bfha cambiado el consumo de tokens?<\/p><\/li><li><p>\u00bfutiliza m\u00e1s herramientas?<\/p><\/li><li><p>\u00bfha aumentado el coste?<\/p><\/li><li><p>\u00bfhan mejorado las evaluaciones?<\/p><\/li><\/ul><p>Sin esta informaci\u00f3n, investigar una regresi\u00f3n despu\u00e9s de cambiar de modelo puede convertirse en un ejercicio de arqueolog\u00eda.<\/p><h2>9. El prompt tambi\u00e9n necesita versionado<\/h2><p>Un cambio de prompt puede modificar radicalmente el comportamiento de una aplicaci\u00f3n sin cambiar una sola l\u00ednea de c\u00f3digo. Por eso los prompts deber\u00edan tratarse como artefactos versionados.<\/p><p>En lugar de depender \u00fanicamente del contenido completo del prompt, podemos registrar:<\/p><pre><code class=\"language-text\">prompt_name\nprompt_version<\/code><\/pre><p>Por ejemplo:<\/p><pre><code class=\"language-text\">customer_support_agent\nv17<\/code><\/pre><p>As\u00ed podemos comparar:<\/p><pre><code class=\"language-text\">latencia v16 vs v17\ntokens v16 vs v17\ntool calls v16 vs v17\nevaluaciones v16 vs v17<\/code><\/pre><p>Esto convierte cambios aparentemente subjetivos en cambios observables.<\/p><h2>10. Cuidado con registrar prompts completos<\/h2><p>Aqu\u00ed aparece uno de los principales riesgos. Guardar prompts y respuestas completas facilita enormemente el debugging.<\/p><p>Pero tambi\u00e9n puede introducir:<\/p><ul data-spread=\"false\"><li><p>datos personales;<\/p><\/li><li><p>informaci\u00f3n confidencial;<\/p><\/li><li><p>credenciales;<\/p><\/li><li><p>c\u00f3digo privado;<\/p><\/li><li><p>documentos internos;<\/p><\/li><li><p>informaci\u00f3n empresarial sensible.<\/p><\/li><\/ul><p>Por tanto, \u201cregistrarlo todo\u201d no deber\u00eda ser la estrategia predeterminada. Una arquitectura madura deber\u00eda decidir expl\u00edcitamente: qu\u00e9 contenido se captura, durante cu\u00e1nto tiempo y qui\u00e9n puede consultarlo.<\/p><p>Podemos utilizar t\u00e9cnicas como:<\/p><ul data-spread=\"false\"><li><p>redacci\u00f3n de informaci\u00f3n sensible;<\/p><\/li><li><p>allowlists de atributos;<\/p><\/li><li><p>sampling;<\/p><\/li><li><p>almacenamiento separado;<\/p><\/li><li><p>controles de acceso;<\/p><\/li><li><p>periodos de retenci\u00f3n diferentes.<\/p><\/li><\/ul><p>En muchos casos ser\u00e1 posible obtener observabilidad suficiente registrando metadatos y capturando contenido \u00fanicamente en determinadas ejecuciones.<\/p><h2>11. Sampling: no todas las trazas tienen el mismo valor<\/h2><p>Guardar cada detalle de cada ejecuci\u00f3n puede resultar caro, por eso el sampling tambi\u00e9n es importante. Una estrategia sencilla podr\u00eda conservar:<\/p><pre><code class=\"language-text\">100 % de errores\n100 % de ejecuciones anormalmente lentas\n100 % de workflows excesivamente caros\n5 % de ejecuciones normales<\/code><\/pre><p>As\u00ed obtenemos informaci\u00f3n detallada precisamente sobre los casos m\u00e1s interesantes sin multiplicar innecesariamente el volumen de telemetr\u00eda.<\/p><p>En aplicaciones con IA, adem\u00e1s, el sampling puede depender de se\u00f1ales espec\u00edficas:<\/p><pre><code class=\"language-text\">token_count &gt; l\u00edmite\ntool_calls &gt; l\u00edmite\nlatency &gt; l\u00edmite\nretry_count &gt; l\u00edmite\nevaluation_score &lt; l\u00edmite<\/code><\/pre><h2>12. M\u00e9tricas agregadas para detectar problemas<\/h2><p>Las trazas sirven para investigar ejecuciones concretas, las m\u00e9tricas permiten descubrir tendencias. Un dashboard b\u00e1sico de una aplicaci\u00f3n con IA podr\u00eda incluir:<\/p><pre><code class=\"language-text\">Requests\/min\nLatencia p50 \/ p95 \/ p99\nModel calls\/run\nTool calls\/run\nTool error rate\nInput tokens\/run\nOutput tokens\/run\nCost\/run\nRetry rate<\/code><\/pre><p>Si existe evaluaci\u00f3n autom\u00e1tica o feedback del usuario, podemos a\u00f1adir se\u00f1ales de calidad. La combinaci\u00f3n es especialmente potente.<\/p><p>Por ejemplo:<\/p><pre><code class=\"language-text\">Latencia \u2191\nTokens \u2191\nTool calls \u2191\nCalidad =<\/code><\/pre><p>podr\u00eda indicar que el agente se ha vuelto menos eficiente sin aportar mejores resultados.<\/p><h2>13. OpenTelemetry empieza a proporcionar un lenguaje com\u00fan<\/h2><p>Uno de los avances m\u00e1s interesantes es que esta telemetr\u00eda empieza a normalizarse. Las convenciones de OpenTelemetry para IA generativa definen atributos y operaciones espec\u00edficas para representar interacciones con modelos y otros componentes de sistemas GenAI.<\/p><p>Entre ellas aparecen conceptos relacionados con:<\/p><ul data-spread=\"false\"><li><p>inferencia;<\/p><\/li><li><p>agentes;<\/p><\/li><li><p>ejecuci\u00f3n de herramientas;<\/p><\/li><li><p>retrieval;<\/p><\/li><li><p>memoria;<\/p><\/li><li><p>tokens;<\/p><\/li><li><p>modelos;<\/p><\/li><li><p>latencia.<\/p><\/li><\/ul><p>Esto es importante porque evita que cada organizaci\u00f3n invente desde cero su propio esquema. Aun as\u00ed, es un terreno en evoluci\u00f3n. En 2026 siguen existiendo discusiones sobre c\u00f3mo representar mejor workflows duraderos, checkpoints, reanudaciones, delegaciones, efectos externos y otras caracter\u00edsticas propias de agentes complejos.<\/p><p>Por eso conviene adoptar est\u00e1ndares, pero evitando acoplar toda la arquitectura a campos experimentales sin una capa propia de abstracci\u00f3n.<\/p><h2>14. Los SDK de agentes ya incorporan tracing<\/h2><p>La observabilidad tampoco tiene que construirse completamente desde cero, frameworks y SDK modernos empiezan a incorporar tracing directamente. Por ejemplo, el Agents SDK de OpenAI registra eventos relacionados con generaciones del modelo, llamadas a herramientas, handoffs, guardrails y otros elementos de una ejecuci\u00f3n. Tambi\u00e9n permite obtener informaci\u00f3n agregada sobre uso de tokens durante un run. Esto reduce considerablemente el esfuerzo necesario para empezar.<\/p><p>Pero disponer de tracing autom\u00e1tico no elimina la necesidad de dise\u00f1ar una estrategia de observabilidad.<\/p><p>Seguimos teniendo que decidir:<\/p><ul data-spread=\"false\"><li><p>qu\u00e9 m\u00e9tricas importan;<\/p><\/li><li><p>qu\u00e9 atributos necesitamos;<\/p><\/li><li><p>qu\u00e9 alertas tienen sentido;<\/p><\/li><li><p>qu\u00e9 datos podemos almacenar;<\/p><\/li><li><p>c\u00f3mo relacionamos telemetr\u00eda t\u00e9cnica con resultados de negocio.<\/p><\/li><\/ul><h2>15. Un modelo pr\u00e1ctico de observabilidad para IA<\/h2><p>Una forma sencilla de empezar consiste en dividir las se\u00f1ales en cinco grupos.<\/p><h3>Rendimiento<\/h3><pre><code class=\"language-text\">latency\ntime_to_first_token\nmodel_latency\ntool_latency\nretrieval_latency<\/code><\/pre><h3>Consumo<\/h3><pre><code class=\"language-text\">input_tokens\noutput_tokens\ncached_tokens\nmodel_calls\ncost<\/code><\/pre><h3>Comportamiento del agente<\/h3><pre><code class=\"language-text\">iterations\ntool_calls\nhandoffs\nretries<\/code><\/pre><h3>Fiabilidad<\/h3><pre><code class=\"language-text\">errors\ntimeouts\ntool_errors\nrate_limits\nvalidation_errors<\/code><\/pre><h3>Calidad<\/h3><pre><code class=\"language-text\">evaluations\nuser_feedback\ntask_success<\/code><\/pre><p>No todas las aplicaciones necesitan todas las m\u00e9tricas.<\/p><p>La pregunta debe ser: \u00bfQu\u00e9 informaci\u00f3n necesitar\u00edamos ma\u00f1ana para explicar una ejecuci\u00f3n incorrecta, lenta o demasiado cara?<\/p><p>La respuesta define buena parte de la telemetr\u00eda que deber\u00edamos implementar hoy.<\/p><h2>De \u201c\u00bfhay errores?\u201d a \u201c\u00bfqu\u00e9 ocurri\u00f3 realmente?\u201d<\/h2><p>Ese es probablemente el cambio conceptual m\u00e1s importante. La observabilidad tradicional suele empezar preguntando:<\/p><blockquote><p>\u00bfEst\u00e1 funcionando el sistema?<\/p><\/blockquote><p>En aplicaciones con IA necesitamos preguntas adicionales:<\/p><blockquote><p>\u00bfQu\u00e9 hizo exactamente?<\/p><\/blockquote><blockquote><p>\u00bfPor qu\u00e9 tard\u00f3 tanto?<\/p><\/blockquote><blockquote><p>\u00bfQu\u00e9 herramientas utiliz\u00f3?<\/p><\/blockquote><blockquote><p>\u00bfCu\u00e1ntos tokens consumi\u00f3?<\/p><\/blockquote><blockquote><p>\u00bfCu\u00e1nto cost\u00f3?<\/p><\/blockquote><blockquote><p>\u00bfCu\u00e1ntas veces lo intent\u00f3?<\/p><\/blockquote><blockquote><p>\u00bfQu\u00e9 versi\u00f3n del modelo y del prompt utiliz\u00f3?<\/p><\/blockquote><blockquote><p>\u00bfY el resultado fue realmente \u00fatil?<\/p><\/blockquote><p>Los logs contin\u00faan siendo necesarios, las m\u00e9tricas contin\u00faan siendo necesarias, las trazas contin\u00faan siendo necesarias, pero la unidad que necesitamos comprender ha cambiado. Ya no observamos \u00fanicamente servicios.<\/p><p>Observamos ejecuciones inteligentes compuestas por decisiones, modelos, herramientas y datos.<\/p><p>Y cuanto m\u00e1s aut\u00f3nomos sean nuestros agentes, m\u00e1s importante ser\u00e1 poder reconstruir exactamente qu\u00e9 hicieron. Porque cuando un agente falle en producci\u00f3n, saber que la API devolvi\u00f3 <code dir=\"ltr\">200 OK<\/code> probablemente ser\u00e1 la parte menos interesante del incidente.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-4fa9b73 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"4fa9b73\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-inner-column elementor-element elementor-element-eeaff01\" data-id=\"eeaff01\" data-element_type=\"column\" data-e-type=\"column\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-6abbbf9 elementor-widget elementor-widget-heading\" data-id=\"6abbbf9\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">REFERENCIAS\n<\/h4>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4439ef8 elementor-widget elementor-widget-text-editor\" data-id=\"4439ef8\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;tc_dark_mode_responsive_hide_in_dark&quot;:&quot;no&quot;,&quot;tc_dark_mode_responsive_hide_in_light&quot;:&quot;no&quot;}\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<ul class=\"content-list\"><li>OpenTelemetry \u2014 Inside the LLM Call: GenAI Observability with OpenTelemetry (2026): https:\/\/opentelemetry.io\/blog\/2026\/genai-observability\/<\/li><li>OpenTelemetry \u2014 Semantic conventions for generative client AI spans: https:\/\/github.com\/open-telemetry\/semantic-conventions-genai\/blob\/main\/docs\/gen-ai\/gen-ai-spans.md<\/li><li>OpenTelemetry \u2014 Semantic Conventions 1.44.0: https:\/\/opentelemetry.io\/docs\/specs\/semconv\/<\/li><li>OpenAI Agents SDK \u2014 Tracing: https:\/\/openai.github.io\/openai-agents-python\/tracing\/<\/li><li>OpenAI Agents SDK \u2014 Usage: https:\/\/openai.github.io\/openai-agents-python\/usage\/<\/li><li>OpenTelemetry GenAI \u2014 Proposal: observability semantics for durable agentic runtime execution (Issue #462, 2026): https:\/\/github.com\/open-telemetry\/semantic-conventions-genai\/issues\/462<\/li><\/ul>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Trazar llamadas al modelo, herramientas, tokens, latencia y errores; c\u00f3mo usar telemetr\u00eda para diagnosticar agentes y aplicaciones con IA.<\/p>\n","protected":false},"author":1,"featured_media":6538,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[38],"tags":[71,47,49,52,70,48],"class_list":["post-6535","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software","tag-aplicaciones","tag-desarrollo","tag-ia","tag-inteligenciaartificial","tag-observabilidad","tag-software"],"_links":{"self":[{"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/posts\/6535","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/comments?post=6535"}],"version-history":[{"count":3,"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/posts\/6535\/revisions"}],"predecessor-version":[{"id":6541,"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/posts\/6535\/revisions\/6541"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/media\/6538"}],"wp:attachment":[{"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/media?parent=6535"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/categories?post=6535"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog-david.moreno-morales.com\/index.php\/wp-json\/wp\/v2\/tags?post=6535"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}