Ir para o conteúdo
mcpd
sem daemon
Código

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.

Trace b3d9e71a Fault
0ms 2.1s 4.2s 6.3s 8.4s
  1. agent support_agent fail
  2. model chat
  3. tool returns_policy
  4. model chat
  5. tool returns_policy
  6. model chat
  7. 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íliaTipos
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

trace_id Store Search Export

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.

CampoO que ele guarda
projectA chave de isolamento. Todo sinal pertence a exatamente um.
environmentOnde rodou, por exemplo produção ou staging.
service_nameO serviço que emitiu.
service_versionA versão dele, para que uma regressão possa ser presa a um release.
session_idUma sessão vista pelo usuário. Agrupa muitos traces em uma conversa.
thread_idUma thread dentro dessa sessão.
user_idO usuário final para quem a execução foi feita.
resource_idUm inquilino ou espaço de trabalho dentro da sua própria aplicação.
run_idO seu próprio identificador para esta execução.
request_idA requisição de entrada que causou o trabalho.
experiment_idDefinido quando um experimento produziu a execução.
releaseUm 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.

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