Aller au contenu
mcpd
aucun daemon
Source

Concepts

Une poignée de mots porte tout le modèle de données. Le reste de la documentation suppose que vous les connaissez, alors cette page définit chacun d’eux et dit à quoi il sert.

Span

Un span est une unité de travail. Il a un nom, un type, une heure de début, en général une heure de fin, et un statut. Il peut porter ce qui est entré, ce qui est sorti, le nombre de tokens employés, ce qu’il a coûté, et une erreur s’il a échoué.

Gardez le nom à faible cardinalité. search_docs est un nom ; search_docs(query=hello) est un nom et une valeur collés ensemble, et cela rend le regroupement par nom inutile dès que vous avez deux exécutions.

Trace

Une trace est l’ensemble des spans d’une exécution, réunis par un identifiant de trace de 128 bits. À l’intérieur de la trace, parent_span_id donne sa forme à l’arbre : un appel d’outil fait dans une étape de modèle est un enfant de cette étape, si bien que l’imbrication à l’écran est celle qui a vraiment eu lieu.

Les identifiants ont la forme OpenTelemetry : 32 caractères hexadécimaux minuscules pour une trace et 16 pour un span. Ce n’est pas de la décoration. C’est ce qui permet à une trace commencée dans votre couche web et finie dans votre agent de rester une seule trace des deux côtés, et ce qui permet à mcpd de se poser à côté de tout ce qui lit déjà votre télémétrie.

Un span dont le parent vient d’un système de traçage étranger le porte dans external_parent_span_id à la place. mcpd garde cette valeur pour la corrélation mais ne bâtit jamais son arbre dessus, parce qu’un identifiant de parent qui nomme un span que mcpd n’a jamais reçu accrocherait tout le sous-arbre à rien.

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.

mcpd stocke aussi une projection de chaque trace : le nombre de spans, le nombre d’erreurs, le total des tokens, le coût total, combien d’appels de modèle et combien d’appels d’outil. Cette ligne est recalculée depuis les spans à chaque écriture plutôt qu’incrémentée, parce que les spans arrivent dans le désordre, font l’objet de nouvelles tentatives et sont mis à jour sur place. Un compteur dérive sous ces trois effets, et un nombre de spans visiblement faux dans la liste fait douter le lecteur de tous les autres nombres de la page.

Spans racines et spans d’événement

Un span racine est un span sans parent à l’intérieur de la trace. C’est normalement un agent_run ou un workflow_run, et c’est de lui que la trace tient son nom, ses étiquettes et sa corrélation. Les étiquettes n’ont de sens que sur une racine, où elles marquent l’exécution entière.

Un span d’événement est un point dans le temps plutôt qu’une durée : il n’a ni fin ni durée. Un chunk diffusé en est le cas courant. La distinction est stockée plutôt que déduite d’une heure de fin absente, parce qu’un span qui n’a jamais eu de fin et un span qui n’est pas encore terminé sont deux faits différents, et qu’un seul des deux est un problème.

Une trace est complète une fois que sa racine s’est terminée et qu’aucun span n’est encore ouvert. Jusque-là elle reste listée, avec le meilleur nom disponible, plutôt que cachée jusqu’à ce qu’elle finisse. L’exécution qui n’a jamais fini est souvent celle que vous êtes venu regarder.

Type de span

Le type dit ce qu’une opération est. Il décide de la façon dont le span est dessiné, des attributs qui ont un sens dessus, et de savoir si la comptabilité des coûts le regarde. mcpd définit 33 types, par familles :

FamilleTypes
Agent agent_run
Modèle model_generation, model_step, model_inference, model_chunk
Outils tool_call, client_tool_call, provider_tool_call, mcp_tool_call
Workflow workflow_run, workflow_step, workflow_conditional, workflow_parallel, workflow_loop, et le reste
Récupération rag_ingestion, rag_embedding, rag_vector_operation, rag_action, retrieval, memory_operation, graph_action
Évaluation scorer_run, scorer_step, guardrail, processor_run
Autres mapping, skill_resolution, workspace_action, http_request, generic

Quatre types facturent des tokens : model_generation, model_step, model_inference et rag_embedding. Ce sont les spans que lit la comptabilité des coûts. generic est toujours valide et jamais déduit, si bien qu’un span que mcpd ne sait pas classer est étiqueté honnêtement plutôt que deviné. Le modèle de données liste chaque type avec ce qu’il veut dire.

La hiérarchie du modèle

Quatre de ces types s’imbriquent les uns dans les autres, et cette imbrication est la chose la plus utile du modèle :

  • model_generation est une génération logique : tout, de la première requête à la réponse finale.
  • model_step est une étape à l’intérieur. Une génération qui appelle des outils deux fois a trois étapes.
  • model_inference est le seul aller-retour vers le fournisseur, sans processeurs et sans exécution d’outil dedans.
  • model_chunk est un chunk diffusé, enregistré comme un événement.

La raison de quatre niveaux plutôt qu’un seul, c’est que dire que l’appel de modèle a été lent n’est presque jamais vrai tel quel. Un appel depuis votre code n’est pas un aller-retour HTTP dès que des outils entrent en jeu : c’est une requête, un outil, une autre requête, un garde-fou, une autre requête. Ramenez tout cela à un seul span, et une exécution qui a passé six secondes dans votre propre boucle de nouvelles tentatives ressemble en tout point à une exécution qui a passé six secondes à attendre un fournisseur. Séparer l’inférence de l’étape et de la génération est ce qui rend la différence lisible, et le premier événement de chunk est ce qui vous donne le temps jusqu’au premier token.

Enregistrez la consommation de tokens une seule fois, sur le span qui a fait l’appel au fournisseur. La projection de la trace additionne les tokens d’entrée et de sortie de tous les spans de la trace : les mêmes comptes attachés à une génération puis de nouveau à chacune de ses étapes doubleront le total des tokens et doubleront le coût à l’écran. La hiérarchie sert au chronométrage ; les tokens appartiennent au niveau qui a réellement parlé au fournisseur.

Les six signaux

Les spans sont l’une des six choses que mcpd stocke. Les logs sont les lignes qu’une exécution a émises. Les métriques sont des observations numériques, sous forme de compteurs, de jauges ou d’histogrammes. Les scores sont l’évaluation d’un span ou d’une trace par une machine. Le feedback est celui d’une personne. Une note d’aspect est une phrase sur une exécution terminée. Un modèle écrit la plupart d’entre elles. Le daemon écrit les notes outcome, à partir du statut de l’exécution et d’autres faits qu’il détient déjà.

  • 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

Les six portent l’identifiant de trace auquel ils appartiennent, et la plupart aussi l’identifiant de span, et les six passent par le même pipeline de masquage avant que quoi que ce soit ne soit écrit. Un secret fuit tout aussi bien par une ligne de log que par un prompt.

Un score déclare toujours son échelle : la valeur, et le minimum et le maximum entre lesquels elle se situe. Chaque SDK exige les deux à l’endroit de l’appel, parce qu’un 0.7 nu, sans échelle attachée, ne peut être comparé à rien, pas même à la sortie du même scorer la semaine dernière.

Le feedback est gardé à un endroit séparé des scores, et jamais moyenné avec eux. Il se présente sous cinq formes : thumbs, rating, correction, tag et comment. Une correction est la plus précieuse des cinq, parce que c’est le seul signal qui porte la bonne réponse.

Corrélation

La corrélation est le contexte auquel un signal appartient. C’est la différence entre un tas d’exécutions et un ensemble que vous pouvez découper.

ChampCe qu’il contient
projectLa clé de cloisonnement. Chaque signal appartient à un seul.
environmentOù cela s’est exécuté, par exemple production ou staging.
service_nameLe service émetteur.
service_versionSa version, pour rattacher une régression à une publication.
session_idUne session côté utilisateur. Regroupe plusieurs traces en une conversation.
thread_idUn fil à l’intérieur de cette session.
user_idL’utilisateur final pour qui l’exécution a eu lieu.
resource_idUn locataire ou un espace de travail dans votre propre application.
run_idVotre propre identifiant pour cette exécution.
request_idLa requête entrante qui a causé le travail.
experiment_idRenseigné quand une expérience a produit l’exécution.
releaseUn nom de publication ou un sha git.

project est le seul champ obligatoire. Quand un émetteur n’en nomme pas, le daemon classe le signal sous la valeur par défaut de --project, si bien que rien n’est jamais stocké sans endroit où appartenir.

Renseignez session_id même quand cela paraît redondant. Une exécution d’agent est une trace, mais une plainte porte presque toujours sur une conversation, et sans identifiant de session rien ne retransforme onze traces séparées en l’échange que la personne a réellement eu.

La liste des traces filtre directement sur environment, session_id, thread_id et user_id, à côté du statut, du type, du nom, des étiquettes, du modèle, de la plage de temps, de la durée minimale, du coût minimal et du score. Retrouver une exécution les met ensemble.

Liens

Un span a un seul parent et autant de liens que l’on veut. Un lien pointe vers un autre span ou une autre trace et dit pourquoi : follows_from, retry_of, replay_of, ou ce que vous nommez vous-même.

Les liens existent parce que la parenté ne sait pas exprimer une convergence. Un traitement par lots causé par vingt requêtes a vingt liens et un seul parent. Forcer cela dans l’arbre inventerait dix-neuf sous-arbres en double, ou jetterait dix-neuf des causes.

Ensuite