Conceptos
Un puñado de palabras sostiene todo el modelo de datos. El resto de la documentación da por hecho que las conoces, así que esta página define cada una y dice para qué sirve.
Span
Un span es una unidad de trabajo. Tiene un nombre, un tipo, una hora de inicio, casi siempre una hora de fin, y un estado. Puede llevar qué entró, qué salió, cuántos tokens usó, cuánto costó y un error si falló.
Mantén el nombre con poca cardinalidad. search_docs es un
nombre; search_docs(query=hello) es un nombre y un valor
pegados, y deja inservible agrupar por nombre en cuanto tienes dos
ejecuciones.
Traza
Una traza son todos los spans de una ejecución, unidos por un id de traza de
128 bits. Dentro de la traza, parent_span_id le da forma al
árbol: una llamada a una herramienta hecha dentro de un paso del modelo es
hija de ese paso, así que el anidamiento en pantalla es el anidamiento que
ocurrió de verdad.
Los ids tienen la forma de OpenTelemetry: 32 caracteres hexadecimales en minúscula para una traza y 16 para un span. Eso no es decoración. Es lo que permite que una traza que empezó en tu capa web y terminó en tu agente siga siendo una sola traza en las dos, y lo que permite que mcpd conviva con cualquier otra cosa que ya lea tu telemetría.
Un span cuyo padre viene de otro sistema de trazado lo lleva en
external_parent_span_id. mcpd conserva ese valor para la
correlación, pero nunca construye su árbol a partir de él, porque un id de
padre que nombra un span que mcpd nunca recibió dejaría todo el subárbol
colgando de nada.
- agent support_agent fail
- model chat
- tool returns_policy
- model chat
- tool returns_policy
- model chat
- tool returns_policy
The model called one tool three times and never answered. That is visible in four seconds here, and invisible in a log file.
mcpd guarda además una proyección de cada traza: el número de spans, el número de errores, el total de tokens, el costo total, cuántas llamadas al modelo y cuántas llamadas a herramientas. Esa fila se recalcula a partir de los spans en cada escritura, en vez de irse incrementando, porque los spans llegan desordenados, se reintentan y se actualizan en el sitio. Un contador se desvía con las tres cosas, y un número de spans visiblemente equivocado en la lista hace que quien lo lee desconfíe de las demás cifras de la página.
Spans raíz y spans de evento
Un span raíz es el que no tiene padre dentro de la traza. Normalmente es un
agent_run o un workflow_run, y es de donde la traza
saca su nombre, sus etiquetas y su correlación. Las etiquetas solo tienen
sentido en una raíz, donde etiquetan la ejecución entera.
Un span de evento es un punto en el tiempo y no una duración, así que no tiene fin ni duración. El caso habitual es un chunk de un flujo. La distinción se guarda en vez de deducirse de una hora de fin ausente, porque «esto nunca tuvo fin» y «esto todavía no ha terminado» son hechos distintos y solo uno de los dos es un problema.
Una traza está completa cuando su raíz ha terminado y no queda ningún span abierto. Hasta entonces sigue apareciendo en la lista, con el mejor nombre disponible, en vez de esconderse hasta acabar. La ejecución que nunca terminó suele ser la que viniste a mirar.
Tipo de span
El tipo dice qué es una operación. Decide cómo se dibuja el span, qué atributos significan algo en él y si la contabilidad de costos lo mira. mcpd define 33 tipos, agrupados en familias:
| Familia | Tipos |
|---|---|
| Agente | agent_run |
| Modelo | model_generation, model_step,
model_inference, model_chunk |
| Herramientas | tool_call, client_tool_call,
provider_tool_call, mcp_tool_call |
| Workflow | workflow_run, workflow_step,
workflow_conditional, workflow_parallel,
workflow_loop, y el resto
|
| Recuperación | rag_ingestion, rag_embedding,
rag_vector_operation, rag_action,
retrieval, memory_operation,
graph_action |
| Evaluación | scorer_run, scorer_step,
guardrail, processor_run |
| Otros | mapping, skill_resolution,
workspace_action, http_request,
generic |
Cuatro tipos facturan tokens: model_generation,
model_step, model_inference y
rag_embedding. Esos son los spans que lee la contabilidad de
costos. generic siempre es válido y nunca se deduce, así que un
span que mcpd no puede clasificar queda etiquetado con honestidad en vez de
a base de suposiciones.
El modelo de datos
enumera cada tipo con lo que significa.
La jerarquía del modelo
Cuatro de esos tipos se anidan unos dentro de otros, y ese anidamiento es lo más útil del modelo:
-
model_generationes una generación lógica: todo, desde la primera solicitud hasta la respuesta final. -
model_stepes un paso dentro de ella. Una generación que llama a herramientas dos veces tiene tres pasos. -
model_inferencees solo la ida y vuelta al proveedor, sin procesadores y sin ejecución de herramientas dentro. -
model_chunkes un chunk del flujo, registrado como evento.
La razón de que haya cuatro niveles y no uno es que «la llamada al modelo fue lenta» casi nunca es cierto tal cual. Una llamada desde tu código no es una sola ida y vuelta HTTP en cuanto hay herramientas de por medio: es una solicitud, una herramienta, otra solicitud, un guardrail, otra solicitud. Junta todo eso en un solo span y una ejecución que pasó seis segundos en tu propio bucle de reintentos parece idéntica a otra que pasó seis segundos esperando a un proveedor. Separar la inferencia del paso, y el paso de la generación, es lo que hace legible la diferencia, y el evento del primer chunk es lo que te da el tiempo hasta el primer token.
Registra el uso de tokens una sola vez, en el span que hizo la llamada al proveedor. La proyección de la traza suma los tokens de entrada y de salida de todos los spans de la traza, así que las mismas cifras puestas en una generación y otra vez en cada uno de sus pasos duplicarán el total de tokens y duplicarán el costo en pantalla. La jerarquía es para los tiempos; los tokens pertenecen al nivel que habló de verdad con el proveedor.
Las seis señales
Los spans son una de las seis cosas que guarda mcpd. Los logs son las
líneas que emitió una ejecución. Las métricas son observaciones numéricas,
en forma de contadores, medidores o histogramas. Las puntuaciones son la
evaluación que una máquina hace de un span o de una traza. El feedback es el
de una persona. Una nota de aspecto es una frase sobre
una ejecución ya terminada. Un modelo escribe la mayoría. El daemon escribe
las notas de outcome, a partir del estado de la ejecución y de
otros hechos que ya tiene.
-
Spans
What ran, nested, with timings
-
Logs
Lines the run emitted
-
Metrics
Numbers, with exemplars back to a run
-
Scores
Machine evaluation
-
Feedback
What a person thought
-
Aspect notes
A sentence a model wrote about the run
Las seis llevan el id de traza al que pertenecen, y casi todas también el id de span, y las seis pasan por el mismo pipeline de ocultación antes de que se escriba nada. Un secreto se escapa por una línea de log igual de bien que por un prompt.
Una puntuación siempre declara su escala: el valor, y el mínimo y el máximo entre los que está. Todos los SDK exigen los dos en el punto de llamada, porque un 0.7 suelto y sin escala no se puede comparar con nada, ni siquiera con lo que dio el mismo evaluador la semana pasada.
El feedback se guarda aparte de las puntuaciones, y nunca se promedia con
ellas. Viene en cinco formas: thumbs, rating,
correction, tag y comment. La
corrección es la más valiosa de las cinco, porque es la única señal que trae
la respuesta correcta.
Correlación
La correlación es el contexto al que pertenece una señal. Es la diferencia entre un montón de ejecuciones y un conjunto que puedes segmentar.
| Campo | Qué contiene |
|---|---|
project | La clave de tenencia. Cada señal pertenece exactamente a uno. |
environment | Dónde se ejecutó, por ejemplo production o staging. |
service_name | El servicio que la emite. |
service_version | Su versión, para poder atribuir una regresión a una entrega. |
session_id | Una sesión de cara al usuario. Agrupa muchas trazas en una conversación. |
thread_id | Un hilo dentro de esa sesión. |
user_id | El usuario final para el que era la ejecución. |
resource_id | Un inquilino o espacio de trabajo dentro de tu propia aplicación. |
run_id | Tu propio identificador de esta ejecución. |
request_id | La solicitud entrante que provocó el trabajo. |
experiment_id | Se rellena cuando la ejecución la produjo un experimento. |
release | Un nombre de entrega o un sha de git. |
project es el único campo obligatorio. Cuando quien envía no
nombra ninguno, el daemon archiva la señal bajo el valor por defecto de
--project, así nada queda guardado sin un sitio al que
pertenecer.
Rellena session_id aunque parezca redundante. Una ejecución de
un agente es una traza, pero una queja casi siempre trata de una
conversación, y sin un id de sesión no hay nada que devuelva once trazas
sueltas al intercambio que la persona tuvo de verdad.
La lista de trazas filtra directamente por environment,
session_id, thread_id y user_id,
junto con el estado, el tipo, el nombre, las etiquetas, el modelo, el rango
de tiempo, la duración mínima, el costo mínimo y la puntuación.
Encontrar una ejecución
los junta todos.
Enlaces
Un span tiene un padre y cualquier número de enlaces. Un enlace apunta a
otro span o a otra traza y dice por qué: follows_from,
retry_of, replay_of, o el nombre que tú le pongas.
Los enlaces existen porque la paternidad no sabe expresar una convergencia. Un trabajo por lotes provocado por veinte solicitudes tiene veinte enlaces y un padre. Meter eso a la fuerza en el árbol inventaría diecinueve subárboles duplicados o tiraría diecinueve de las causas.
A continuación
- Cada entidad y cada campo al completo: Modelo de datos.
- Cómo aparecen estas palabras en el código: los SDK.
- Qué deduce mcpd cuando los spans llegan como OTLP: OpenTelemetry.
- Convertir el vocabulario en una consulta: Encontrar una ejecución.