Nuevo Regístrate gratis, 10 llamadas de regalo. Hasta 1 $, sin tarjeta.

Observabilidad de agentes LLM: trazas, sesiones y 10 problemas

Contenido
  1. ¿Qué son las trazas, los spans y las sesiones de un agente LLM?
  2. ¿Qué vista responde a cada pregunta?
  3. ¿Por qué va lento un agente LLM?
  4. ¿Por qué sale caro un agente LLM?
  5. ¿Cómo depuras un agente LLM a partir de la queja de un usuario?
  6. ¿Puedes trazar un agente de programación que no has escrito?
  7. ¿Puede un modelo leer las trazas por ti?
  8. ¿Qué debería registrar todo agente?
  9. ¿Qué queda fuera de las trazas del gateway?
  10. Preguntas frecuentes
  11. ¿Qué es la observabilidad de agentes LLM?
  12. Lecturas relacionadas

La observabilidad de un agente LLM empieza por agrupar sus llamadas al modelo de dos formas: una traza representa una ejecución del agente en una línea de tiempo; una sesión reúne una conversación y su coste total. Basta con añadir tres cabeceras a cada llamada para que un gateway LLM genere ambas a partir de su registro de peticiones, sin un SDK de trazabilidad. El gateway actúa como proxy entre tu código y los proveedores de modelos y registra cada petición. Probamos esta configuración con un pequeño agente de soporte y con Claude Code, y reprodujimos diez problemas habituales: tres que ralentizan el agente, cuatro que encarecen su uso y tres que provocan fallos.

TL;DR

  • Tres cabeceras (X-Trace-Id, X-Span-Id, X-Session-Id) convierten el registro de peticiones del gateway de Synthorai en trazas y sesiones, sin un SDK de trazabilidad.
  • Enviar a la vez tres comprobaciones independientes de subagentes redujo la mediana de su duración de 3.7 s a 1.8 s, sin cambiar el coste.
  • Quitar la marca de tiempo de la primera línea del prompt en GPT-6 Luna elevó la tasa de aciertos de caché del 0% al 73%, partiendo de una caché vacía.
  • Una ejecución de Claude Code costó $0.1728. La primera llamada de cada uno de sus tres agentes supuso el 72% del total.

Este artículo resume una serie de siete guías. Cada sección presenta los resultados de una guía y enlaza al código y las capturas. Todas las ejecuciones son del 10 y el 11 de octubre de 2026. Las cifras de latencia son medianas de cinco ejecuciones; las demás proceden de una sola ejecución. El código está en github.com/synthorai-io/use-cases.

¿Qué son las trazas, los spans y las sesiones de un agente LLM?

Una traza abarca todo lo que hace un agente para resolver un mensaje de usuario o una tarea. Un span es un paso dentro de esa traza, y una sesión es la conversación completa, formada por varias trazas. En nuestro agente de soporte, una conversación de dos turnos con un cliente es una sesión con dos trazas. Cada traza contiene cinco o seis llamadas al modelo. Algunas proceden de un subagente: un segundo agente que el principal inicia para resolver una parte de la tarea, con su propio prompt y, a menudo, un modelo más barato.

TérminoQué abarcaCabeceraDónde enviar el mismo valor
Trazauna ejecución del agenteX-Trace-Iden todas las llamadas de la ejecución
Spanuna llamada al modelo dentro de la ejecuciónX-Span-Idsolo en esa llamada
Sesiónuna conversaciónX-Session-Iden todas las llamadas de la conversación
Agentequé subagente hizo la llamadaX-Agent-Iden todas las llamadas de ese subagente
Etiquetasusuario, funcionalidad, versiónX-Synthorai-Metadataen cualquier llamada que quieras agrupar o filtrar

Los identificadores son cadenas que eliges tú, de hasta 128 caracteres ASCII imprimibles cada una. Las etiquetas se envían como un objeto JSON plano de cadenas, con un máximo de 10 por petición y hasta 128 bytes por valor. El gateway devuelve los identificadores en la respuesta y no reenvía ninguna de estas cabeceras al proveedor del modelo. En el SDK de Python de OpenAI, las cabeceras de cada petición se pasan en extra_headers:

resp = client.chat.completions.create(
    model="gpt-6-luna",
    messages=messages,
    extra_headers={
        "X-Session-Id": session_id,   # one per conversation
        "X-Trace-Id": trace_id,       # one per user message
        "X-Span-Id": "plan",          # one per call
        "X-Synthorai-Metadata": '{"feature":"support-agent","_user":"u_1002"}',
    },
)

Si tu agente ya envía identificadores de traza mediante otra herramienta, quizá no tengas que añadir nada. Para cada uno de los tres identificadores que falte en una petición, el gateway lee la cabecera equivalente de OpenTelemetry, LiteLLM, Langfuse, Open WebUI, Claude Code o la CLI de OpenAI Codex. OpenTelemetry es el estándar abierto de trazabilidad; su cabecera traceparent incluye un identificador de traza. Trazar un agente LLM con 3 cabeceras HTTP explica paso a paso cómo construir el agente de ejemplo: una llamada de planificación a GPT-6 Luna, dos herramientas locales, tres comprobaciones en paralelo con DeepSeek V4.1 Flash y una llamada para generar la respuesta. La ejecución de ejemplo hizo 21 llamadas al modelo por $0.0017.

¿Qué vista responde a cada pregunta?

Cada pregunta de la serie se resuelve en una vista de la consola o consultando el registro desde fuera de ella. La consola muestra cada traza como un diagrama de cascada: una barra por llamada al modelo, sobre un eje temporal común. Las llamadas en paralelo se solapan; las que esperan unas a otras forman una escalera.

PreguntaDónde mirarGuía
¿Por qué esta ejecución tardó 8 segundos?el resumen de la traza: tiempo en el gateway frente a tiempo en tu aplicaciónLatencia del agente
¿Qué turno de esta conversación costó más?la página de la sesión, con una fila por trazaCoste del agente
¿Por qué la tasa de aciertos de caché es del 0%?la columna de aciertos de caché en la página de la sesiónCoste del agente
¿Qué ocurrió ayer con la petición de este usuario?una búsqueda por etiqueta en la lista de trazasDepuración del agente
¿Qué subagente de Claude Code generó el gasto?la tabla de agentes en la página de la sesiónCoste de Claude Code por subagente
¿Puedo hacer estas preguntas en un chat?un conector MCP en ClaudeConsulta a Claude sobre tus registros de LLM
¿Puede mi programa investigar el registro?herramientas MCP o la API RESTDale a tu agente herramientas para consultar registros

Cada página de traza tiene también un botón de comparación. Muestra dos trazas en la misma página, empareja las llamadas por nombre y coloca ambos diagramas sobre un único eje temporal. Así comprobamos cada corrección de la serie, comparando una ejecución anterior al cambio con otra posterior.

¿Por qué va lento un agente LLM?

Empieza por el desglose que aparece en la parte superior de la traza. Divide el tiempo total que esperó el usuario, desde la primera petición hasta la última respuesta, en tiempo en el gateway y tiempo en tu aplicación. El primero corresponde a los intervalos con al menos una petición al modelo abierta; el segundo, a aquellos en los que solo se ejecutaba tu código. En la traza de ejemplo, los 8.5 s totales se repartían entre 7.0 s en el gateway y 1.6 s en la aplicación, así que había que revisar las llamadas al modelo. La guía de latencia reprodujo tres causas y ejecutó cada caso cinco veces:

CausaQué muestra la trazaCorrecciónMediana antesMediana después
Llamadas independientes enviadas una a unabarras en escaleraenviarlas juntas con asyncio.gather, que permite esperar varias llamadas a la vez en Python3.7 s1.8 s
Código lento entre llamadasuna fila your app largaejecutar las cuatro consultas a la vez11.0 s9.2 s
Razonamiento para respuestas de una líneaun recuento de salida muy superior al de la respuestareasoning_effort="none"25.6 s para cinco respuestas10.2 s

En el caso del código lento, las llamadas al modelo tardaron aproximadamente lo mismo en ambas ejecuciones. Lo que cambió fue el tiempo de la aplicación: en las dos ejecuciones que muestra la guía, la fila your app pasó de 4.6 s a 1.3 s. Cambiar de modelo no puede acortar esa parte; hay que empezar por el perfilador de tu código o los spans de OpenTelemetry. El tercer caso se ejecutó con GPT-6 Luna. reasoning_effort es el parámetro de la petición que controla cuánto razona el modelo antes de responder. Al ponerlo en none, los tokens de salida de las cinco respuestas bajaron de 1,150 a 190. ¿Por qué va lento mi agente LLM? incluye el código y las trazas comparadas de los tres casos.

¿Por qué sale caro un agente LLM?

Ordena la lista de trazas por coste, abre la sesión más cara y revisa las columnas de aciertos de caché y entrada turno a turno. La tasa de aciertos de caché es la proporción de tokens de entrada leídos de la caché de prompts del proveedor. Esta permite facturar un prefijo de prompt ya visto a una fracción del precio de entrada. La guía de costes reprodujo cuatro causas. Los importes son fracciones de céntimo porque el ejemplo es pequeño; lo extrapolable son las proporciones:

CausaDónde se veAntesDespués
Una marca de tiempo en la primera línea del promptlos aciertos de caché se mantienen en el 0%0% en caché73% en caché, coste de entrada un 66% menor
Un historial que reenvía todos los resultados de herramientasla entrada crece en cada turno24,546 tokens de entrada8,053 tokens de entrada
Un bucle de reintentosuna traza con demasiadas llamadas, todas con estado 20010 llamadas2 llamadas
Un modelo caro para un paso sencillola tabla de agentes en la página de la sesión$0.0012$0.0003

El primer caso se ejecutó con GPT-6 Luna, partiendo de una caché vacía. La guía muestra otra forma de perder los aciertos de caché: añadir una instrucción a cada mensaje del usuario al enviarlo, pero no al guardarlo. Así, cada turno reconstruye un prompt que el turno anterior nunca envió. Guardar el mensaje tal como se había enviado elevó la tasa de aciertos de esa conversación del 0% al 76%. En el caso del historial, triplicar los tokens de entrada solo aumentó su coste un 21%, porque el 71% se leyó de la caché. En el último caso, tres comprobaciones de subagentes con GPT-6.1 Sol suponían el 81% del coste de la sesión. Las mismas comprobaciones con DeepSeek V4.1 Flash costaron una décima parte. ¿Por qué sale caro mi agente LLM? detalla cada caso.

¿Cómo depuras un agente LLM a partir de la queja de un usuario?

Localiza las ejecuciones del usuario mediante una etiqueta y revisa la traza hasta encontrar la llamada que falló, aunque muchas veces haya devuelto un estado 200. Si cada petición incluye la etiqueta _user, buscar metadata._user = u_1002 en la lista de trazas devuelve las sesiones y trazas de ese usuario. La guía de depuración reprodujo tres fallos:

  • Un 404 con reintento. Una llamada a un identificador de modelo inexistente falló en 95 ms y costó $0. El reintento conservó el identificador de traza y usó un nuevo nombre de span (policy-check.retry), de modo que el fallo y el reintento aparecen juntos en el diagrama de cascada.
  • Respuestas truncadas con estado 200. Con max_tokens=40 y el razonamiento activado, tres llamadas consecutivas a DeepSeek V4.1 Flash devolvieron un estado 200 con exactamente 40 tokens de salida y una respuesta vacía: el razonamiento había agotado el límite. La traza muestra el mismo span tres veces, con un recuento de salida igual al límite. Subirlo a 2,000 y desactivar el razonamiento permitió obtener una respuesta de 49 tokens en una sola llamada. Subir solo el límite también funcionó, pero esa llamada consumió 1,876 tokens de razonamiento y tardó 22 s.
  • Un 400 en el segundo turno. El historial guardado había perdido una llamada a una herramienta. Por eso GPT-6 Luna rechazó el segundo turno en 0.5 s y sin coste, aunque el primero había funcionado.

El segundo fallo explica por qué todas las llamadas deben registrar finish_reason, el campo de la respuesta que indica por qué se detuvo el modelo. El valor length significa que la respuesta alcanzó el límite de max_tokens y debe contarse como un fallo aunque el estado sea 200. Depurar un agente LLM enumera los cinco campos que todo agente debería registrar, que también recogemos al final de este artículo.

¿Puedes trazar un agente de programación que no has escrito?

Claude Code se puede trazar sin modificarlo porque ya envía un identificador de sesión y otro de agente en cada petición. Dos variables de entorno bastan para dirigirlo al gateway; una tercera añade el tipo de cada subagente:

export ANTHROPIC_BASE_URL="https://synthorai.io"   # no /v1: Claude Code adds /v1/messages itself
export ANTHROPIC_API_KEY="<your gateway key>"
export CLAUDE_CODE_GATEWAY_HINT_HEADERS=1          # optional: names sub-agent types such as Explore

Una ejecución de Claude Code con Claude Sonnet 5.5 y dos subagentes hizo 11 peticiones por $0.1728 para corregir un test que fallaba. La página de la sesión desglosó el gasto por agente: los dos subagentes supusieron el 39% del coste, las escrituras en caché el 77% y la primera llamada de cada uno de los tres agentes el 72%. Repetir la misma ejecución medio minuto después, con la caché caliente, costó $0.0812. Coste de Claude Code por subagente también muestra cómo desglosar el gasto de un equipo por desarrollador y repositorio.

¿Puede un modelo leer las trazas por ti?

Un modelo puede leerlas mediante MCP (Model Context Protocol, el estándar para dar acceso a herramientas a un modelo), ya que el gateway expone su registro de peticiones como servidor MCP. La forma de consultar el registro depende de quién lo haga:

Quién consultaQué usarTokens del modeloResultado medido
Una persona con una preguntaClaude con el gateway añadido como conectorincluidos en el plan de chat3 preguntas en 14 llamadas a herramientas; todas las cifras coincidieron con los registros de facturación
Un programa con una consulta fijala API RESTningunolas 3 sesiones más caras por $0
Tu propio agente, que decide qué revisarherramientas MCP en el programase facturan aparteuna investigación de costes por $0.0015

En el caso del chat, Claude Fable 5.1 se conectó mediante OAuth, con un inicio de sesión en el navegador en lugar de pegar una clave de API. Solo se le concedió acceso de lectura al registro de peticiones. Así obtuvo cuatro herramientas de solo lectura y una clave que caduca en 7 días. Las herramientas devuelven costes, tokens y estados, pero no el texto de los prompts ni de las respuestas. En el caso del programa, GPT-6 Luna encontró entre 26 sesiones las que tenían problemas de caché, de elección de modelo y de bucles de reintentos, con una sola llamada a herramientas por $0.0015. Claude Sonnet 5.5 encontró las mismas sesiones en tres llamadas a herramientas por $0.0631, tras consultar los precios. Consulta a Claude sobre tus registros de LLM y Dale a tu agente herramientas para consultar registros explican ambas configuraciones.

¿Qué debería registrar todo agente?

Cinco campos cubren todos los problemas de la serie:

  • Un identificador de traza por ejecución y uno de sesión por conversación, enviados como cabeceras y guardados también en tus propios registros.
  • Un nombre de span por llamada que identifique el paso y el intento, como plan-2 o policy-check.retry.
  • Etiquetas de usuario, funcionalidad y versión, para localizar las ejecuciones que originaron una queja o una factura.
  • La cabecera de respuesta x-request-id de cada llamada, que permite consultar después el coste facturado de esa llamada.
  • finish_reason y el número de tokens de salida de cada llamada, tratando length como un fallo.

Configura también un tiempo de espera del cliente y un valor de max_tokens en cada llamada, ambos con margen suficiente. Ajustar el límite solo a la respuesta visible fue lo que causó las respuestas 200 vacías del ejemplo. Además, un modelo de razonamiento puede tardar minutos en una sola llamada larga.

¿Qué queda fuera de las trazas del gateway?

Las trazas generadas a partir del registro de peticiones cubren las llamadas al modelo, pero no lo que ocurre dentro de tu código. El gateway deduce el tiempo de ejecución de tu código a partir de los intervalos entre peticiones, como vimos en el caso del código lento. Para añadir spans de herramientas, recuperación de información y colas necesitas un SDK de OpenTelemetry. Ambas vistas pueden compartir un identificador de traza, porque el gateway lee traceparent cuando falta X-Trace-Id. Las trazas tampoco incluyen los cuerpos de los prompts ni de las respuestas, y reflejan el coste a posteriori. Para controlar el presupuesto en tiempo real, tu bucle del agente debe calcular el coste del usage de cada respuesta en cuanto llega.

Preguntas frecuentes

¿Qué es la observabilidad de agentes LLM?

La observabilidad de agentes LLM permite ver qué hizo un agente en cada ejecución: a qué modelos llamó, en qué orden, cuánto tardó cada llamada, cuánto costó y cuáles fallaron. En la práctica, consiste en agrupar las llamadas en trazas (una ejecución) y sesiones (una conversación), con etiquetas de usuario y funcionalidad.

Lecturas relacionadas

← Volver al blog