Conceitos
Um punhado de palavras carrega o modelo de dados inteiro. O resto da documentação presume que você as conhece, então esta página define cada uma e diz para que ela serve.
Span
Um span é uma unidade de trabalho. Ele tem um nome, um tipo, um horário de início, em geral um horário de fim, e um status. Ele pode carregar o que entrou, o que saiu, quantos tokens usou, quanto custou e um erro, se falhou.
Mantenha o nome com cardinalidade baixa. search_docs é um nome;
search_docs(query=hello) é um nome e um valor colados, e isso
torna o agrupamento por nome inútil no instante em que você tem duas
execuções.
Trace
Um trace são todos os spans de uma execução, unidos por um id de trace de
128 bits. Dentro do trace, parent_span_id dá a forma da árvore:
uma chamada de ferramenta feita dentro de uma etapa de modelo é filha dessa
etapa, então o aninhamento na tela é o aninhamento que aconteceu de verdade.
Os ids têm o formato do OpenTelemetry: 32 caracteres hexadecimais minúsculos para um trace e 16 para um span. Isso não é enfeite. É o que permite que um trace iniciado na sua camada web e terminado no seu agente continue sendo um único trace nas duas, e o que permite ao mcpd ficar ao lado de qualquer outra coisa que já leia a sua telemetria.
Um span cujo pai veio de um sistema de tracing de fora carrega esse pai em
external_parent_span_id. O mcpd guarda esse valor para a
correlação, mas nunca constrói a sua árvore a partir dele, porque um id de
pai que nomeia um span que o mcpd nunca recebeu penduraria a subárvore
inteira em 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.
O mcpd também guarda uma projeção de cada trace: a contagem de spans, a contagem de erros, o total de tokens, o custo total, quantas chamadas de modelo e quantas chamadas de ferramenta. Essa linha é recalculada a partir dos spans a cada escrita, em vez de incrementada, porque os spans chegam fora de ordem, são repetidos e são atualizados no lugar. Um contador se desvia nos três casos, e uma contagem de spans visivelmente errada na lista faz o leitor desconfiar de todos os outros números da página.
Spans raiz e spans de evento
Um span raiz é um span sem pai dentro do trace. Em geral é um
agent_run ou um workflow_run, e é dele que o trace
tira o nome, as tags e a correlação. As tags só fazem sentido em um span
raiz, onde rotulam a execução inteira.
Um span de evento é um ponto no tempo, e não uma duração, então não tem fim nem duração. O caso comum é um chunk de streaming. A distinção é guardada, e não deduzida da falta de um horário de fim, porque “isto nunca teve um fim” e “isto ainda não terminou” são fatos diferentes e só um dos dois é um problema.
Um trace está completo quando o seu span raiz terminou e nenhum span continua aberto. Até lá ele continua na lista, com o melhor nome disponível, em vez de ficar escondido até acabar. A execução que nunca terminou costuma ser justamente aquela que você veio ver.
Tipo de span
O tipo diz o que uma operação é. Ele decide como o span é desenhado, quais atributos significam alguma coisa nele e se a apuração de custos olha para ele. O mcpd define 33 tipos, em famílias:
| Família | Tipos |
|---|---|
| Agente | agent_run |
| Modelo | model_generation, model_step,
model_inference, model_chunk |
| Ferramentas | tool_call, client_tool_call,
provider_tool_call, mcp_tool_call |
| Workflow | workflow_run, workflow_step,
workflow_conditional, workflow_parallel,
workflow_loop, e os demais
|
| Recuperação | rag_ingestion, rag_embedding,
rag_vector_operation, rag_action,
retrieval, memory_operation,
graph_action |
| Avaliação | scorer_run, scorer_step,
guardrail, processor_run |
| Outros | mapping, skill_resolution,
workspace_action, http_request,
generic |
Quatro tipos cobram tokens: model_generation,
model_step, model_inference e
rag_embedding. São esses os spans que a apuração de custos
lê. generic é sempre válido e nunca é deduzido, então um span que
o mcpd não consegue classificar é rotulado com honestidade, em vez de
adivinhado.
O modelo de dados
lista cada tipo com o que ele significa.
A hierarquia do modelo
Quatro desses tipos se aninham uns dentro dos outros, e o aninhamento é a coisa mais útil do modelo:
-
model_generationé uma geração lógica: tudo, da primeira requisição até a resposta final. -
model_stepé uma etapa dentro dela. Uma geração que chama ferramentas duas vezes tem três etapas. -
model_inferenceé só a ida e volta ao provedor, sem processadores e sem execução de ferramenta dentro dela. -
model_chunké um chunk de streaming, registrado como um evento.
A razão de haver quatro níveis, e não um, é que “a chamada do modelo estava lenta” quase nunca é verdade do jeito que foi dita. Uma chamada feita pelo seu código não é uma ida e volta HTTP quando há ferramentas no meio: é uma requisição, uma ferramenta, outra requisição, um guardrail, outra requisição. Junte tudo isso em um span só e uma execução que passou seis segundos no seu próprio laço de repetição fica idêntica a outra que passou seis segundos esperando um provedor. Separar a inferência da etapa, e a etapa da geração, é o que torna a diferença legível, e o evento do primeiro chunk é o que dá o tempo até o primeiro token.
Registre o uso de tokens uma vez, no span que fez a chamada ao provedor. A projeção do trace soma os tokens de entrada e de saída de todos os spans do trace, então as mesmas contagens anexadas a uma geração e de novo a cada uma das etapas dela vão dobrar o total de tokens e dobrar o custo na tela. A hierarquia serve para o tempo; os tokens pertencem ao nível que de fato falou com o provedor.
Os seis sinais
Os spans são uma das seis coisas que o mcpd guarda. Os logs são as linhas
que uma execução emitiu. As métricas são observações numéricas, na forma de
contadores, gauges ou histogramas. As notas são a avaliação de uma máquina
sobre um span ou um trace. O feedback é o de uma pessoa. Uma anotação de
aspecto é uma frase sobre uma execução já terminada. Um modelo escreve a
maioria delas. O daemon escreve as anotações de outcome, a
partir do status da execução e de outros fatos que ele já tem.
-
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
Os seis carregam o id de trace a que pertencem, e quase todos também o id de span, e os seis passam pelo mesmo pipeline de ocultação antes de qualquer coisa ser escrita. Um segredo vaza por uma linha de log exatamente tão bem quanto por um prompt.
Uma nota sempre declara a sua escala: o valor, e o mínimo e o máximo entre os quais ele fica. Todo SDK exige os dois no ponto da chamada, porque um 0,7 solto, sem escala anexada, não pode ser comparado com nada, nem mesmo com o resultado do mesmo avaliador na semana passada.
O feedback fica guardado em um lugar separado das notas, e nunca entra na
média junto com elas. Ele vem em cinco formatos: thumbs,
rating, correction, tag e
comment. Uma correção é o mais valioso dos cinco, porque é o
único sinal que carrega a resposta certa.
Correlação
Correlação é o contexto a que um sinal pertence. É a diferença entre um monte de execuções e um conjunto que você consegue fatiar.
| Campo | O que ele guarda |
|---|---|
project | A chave de isolamento. Todo sinal pertence a exatamente um. |
environment | Onde rodou, por exemplo produção ou staging. |
service_name | O serviço que emitiu. |
service_version | A versão dele, para que uma regressão possa ser presa a um release. |
session_id | Uma sessão vista pelo usuário. Agrupa muitos traces em uma conversa. |
thread_id | Uma thread dentro dessa sessão. |
user_id | O usuário final para quem a execução foi feita. |
resource_id | Um inquilino ou espaço de trabalho dentro da sua própria aplicação. |
run_id | O seu próprio identificador para esta execução. |
request_id | A requisição de entrada que causou o trabalho. |
experiment_id | Definido quando um experimento produziu a execução. |
release | Um nome de release ou um sha do git. |
project é o único campo obrigatório. Quando quem envia não nomeia
um projeto, o daemon arquiva o sinal sob o padrão de --project,
para que nada seja guardado sem ter a que pertencer.
Defina session_id mesmo quando parecer redundante. Uma execução
de agente é um trace, mas uma reclamação quase sempre é sobre uma conversa, e
sem um id de sessão não há nada que transforme onze traces separados de volta
na troca que a pessoa de fato teve.
A lista de traces filtra direto por environment,
session_id, thread_id e user_id, junto
com status, tipo, nome, tags, modelo, intervalo de tempo, duração mínima,
custo mínimo e nota.
Encontrar uma execução junta
tudo isso.
Links
Um span tem um pai e qualquer número de links. Um link aponta para outro span
ou para outro trace e diz por quê: follows_from,
retry_of, replay_of, ou o nome que você der.
Os links existem porque a relação de pai e filho não consegue expressar a convergência de várias causas. Um trabalho em lote causado por vinte requisições tem vinte links e um pai. Forçar isso dentro da árvore inventaria dezenove subárvores duplicadas ou jogaria fora dezenove das causas.
Em seguida
- Cada entidade e cada campo por inteiro: Modelo de dados.
- Como essas palavras aparecem no código: os SDKs.
- O que o mcpd deduz quando os spans chegam como OTLP: OpenTelemetry.
- Transformando o vocabulário em uma consulta: Encontrar uma execução.