Vai al contenuto
mcpd
nessun daemon
Codice

Concetti

Poche parole reggono tutto il modello dei dati. Il resto della documentazione dà per scontato che tu le conosca, quindi questa pagina definisce ognuna e dice a che cosa serve.

Span

Uno span è una singola unità di lavoro. Ha un nome, un tipo, un istante di inizio, di solito un istante di fine, e uno stato. Può portare che cosa è entrato, che cosa è uscito, quanti token ha consumato, quanto è costato, e un errore se è fallito.

Tieni il nome a bassa cardinalità. search_docs è un nome; search_docs(query=hello) è un nome e un valore incollati insieme, e rende inutile il raggruppamento per nome nel momento stesso in cui hai due esecuzioni.

Traccia

Una traccia è l’insieme degli span di una sola esecuzione, uniti da un id di traccia a 128 bit. Dentro la traccia, parent_span_id dà all’albero la sua forma: una chiamata a uno strumento fatta dentro un passo del modello è figlia di quel passo, così l’annidamento sullo schermo è l’annidamento che è avvenuto davvero.

Gli id hanno la forma di OpenTelemetry: 32 caratteri esadecimali minuscoli per una traccia e 16 per uno span. Non è un ornamento. È quello che permette a una traccia iniziata nel tuo strato web e finita nel tuo agente di restare una sola traccia attraverso tutti e due, ed è quello che permette a mcpd di stare accanto a qualunque altra cosa legga già la tua telemetria.

Uno span il cui genitore viene da un sistema di tracciamento esterno lo porta invece in external_parent_span_id. mcpd conserva quel valore per la correlazione ma non costruisce mai il suo albero a partire da lì, perché un id di genitore che nomina uno span che mcpd non ha mai ricevuto appenderebbe tutto il sottoalbero a niente.

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 archivia anche una proiezione di ogni traccia: il numero di span, il numero di errori, i token totali, il costo totale, quante chiamate al modello e quante chiamate a uno strumento. Quella riga viene ricalcolata dagli span a ogni scrittura invece di essere incrementata, perché gli span arrivano fuori ordine, vengono ritentati e vengono aggiornati sul posto. Un contatore va alla deriva con tutte e tre le cose, e un numero di span visibilmente sbagliato nell’elenco fa perdere a chi legge la fiducia in ogni altro numero della pagina.

Span radice e span evento

Uno span radice è uno span senza genitore dentro la traccia. Di solito è un agent_run o un workflow_run, ed è da lì che la traccia prende il suo nome, i suoi tag e la sua correlazione. I tag hanno un senso solo su una radice, dove etichettano l’esecuzione intera.

Uno span evento è un istante e non una durata, quindi non ha fine e non ha durata. Il caso tipico è un chunk in streaming. La distinzione viene archiviata invece che dedotta da un istante di fine mancante, perché «questo non ha mai avuto una fine» e «questo non è ancora finito» sono fatti diversi e solo uno dei due è un problema.

Una traccia è completa quando la sua radice è finita e nessuno span è ancora aperto. Fino ad allora resta comunque nell’elenco, con il miglior nome disponibile, invece di essere nascosta finché non finisce. L’esecuzione che non è mai finita è spesso proprio quella che sei venuto a guardare.

Tipo di span

Il tipo dice che cosa è un’operazione. Decide come lo span viene disegnato, quali attributi hanno un senso su di esso, e se la contabilità dei costi lo guarda. mcpd definisce 33 tipi, raccolti in famiglie:

FamigliaTipi
Agente agent_run
Modello model_generation, model_step, model_inference, model_chunk
Strumenti tool_call, client_tool_call, provider_tool_call, mcp_tool_call
Workflow workflow_run, workflow_step, workflow_conditional, workflow_parallel, workflow_loop, e gli altri
Recupero rag_ingestion, rag_embedding, rag_vector_operation, rag_action, retrieval, memory_operation, graph_action
Valutazione scorer_run, scorer_step, guardrail, processor_run
Altro mapping, skill_resolution, workspace_action, http_request, generic

Quattro tipi addebitano token: model_generation, model_step, model_inference e rag_embedding. Sono gli span che legge la contabilità dei costi. generic è sempre valido e non viene mai dedotto, così uno span che mcpd non riesce a classificare viene etichettato in modo onesto invece che tirato a indovinare. Il modello dei dati elenca ogni tipo con il suo significato.

La gerarchia del modello

Quattro di quei tipi si annidano l’uno dentro l’altro, e l’annidamento è la cosa più utile di tutto il modello:

  • model_generation è una generazione logica: tutto quello che va dalla prima richiesta alla risposta finale.
  • model_step è un passo al suo interno. Una generazione che chiama gli strumenti due volte ha tre passi.
  • model_inference è il solo giro di andata e ritorno verso il fornitore, senza processori e senza esecuzione di strumenti al suo interno.
  • model_chunk è un singolo chunk in streaming, registrato come evento.

Il motivo per cui i livelli sono quattro e non uno è che «la chiamata al modello è stata lenta» non è quasi mai vero così come viene detto. Una chiamata dal tuo codice non è un unico giro di andata e ritorno HTTP quando ci sono di mezzo gli strumenti: è una richiesta, uno strumento, un’altra richiesta, un guardrail, un’altra richiesta. Comprimi tutto questo in un solo span e un’esecuzione che ha passato sei secondi dentro il tuo ciclo di nuovi tentativi sembra identica a una che ha passato sei secondi ad aspettare un fornitore. Separare l’inferenza dal passo, e il passo dalla generazione, è quello che rende leggibile la differenza, e l’evento del primo chunk è quello che ti dà il tempo al primo token.

Registra il consumo di token una volta sola, sullo span che ha fatto la chiamata al fornitore. La proiezione della traccia somma i token di input e di output di ogni span della traccia, quindi gli stessi conteggi attaccati a una generazione e di nuovo a ciascuno dei suoi passi raddoppiano il totale dei token e raddoppiano il costo sullo schermo. La gerarchia serve per i tempi; i token appartengono al livello che ha davvero parlato con il fornitore.

I sei segnali

Gli span sono una delle sei cose che mcpd archivia. I log sono le righe che un’esecuzione ha emesso. Le metriche sono osservazioni numeriche, sotto forma di counter, gauge o istogrammi. I punteggi sono la valutazione che una macchina dà di uno span o di una traccia. Il feedback è la valutazione di una persona. Una nota di aspetto è una frase su un’esecuzione conclusa. La maggior parte la scrive un modello. Le note outcome le scrive il daemon, a partire dallo stato dell’esecuzione e da altri fatti che ha già.

  • 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

Tutti e sei portano l’id di traccia a cui appartengono, e quasi tutti anche l’id di span, e tutti e sei passano dalla stessa pipeline di oscuramento prima che venga scritto qualcosa. Un segreto esce da una riga di log esattamente come esce da un prompt.

Un punteggio dichiara sempre la sua scala: il valore, e il minimo e il massimo tra cui sta. Ogni SDK li richiede entrambi al punto di chiamata, perché uno 0.7 nudo, senza una scala attaccata, non si può confrontare con niente, nemmeno con quello che lo stesso scorer ha prodotto la settimana prima.

Il feedback sta in un posto separato dai punteggi, e non viene mai mediato con loro. Arriva in cinque forme: thumbs, rating, correction, tag e comment. Una correction è la più preziosa delle cinque, perché è l’unico segnale che porta con sé la risposta giusta.

Correlazione

La correlazione è il contesto a cui appartiene un segnale. È la differenza tra un mucchio di esecuzioni e un insieme che puoi tagliare a fette.

CampoChe cosa contiene
projectLa chiave di tenancy. Ogni segnale appartiene esattamente a uno.
environmentDove è stato eseguito, per esempio production o staging.
service_nameIl servizio che lo emette.
service_versionLa sua versione, così una regressione si attribuisce a una release.
session_idUna sessione lato utente. Raggruppa molte tracce in una conversazione.
thread_idUn thread dentro quella sessione.
user_idL’utente finale per cui era l’esecuzione.
resource_idUn tenant o un workspace dentro la tua applicazione.
run_idIl tuo identificatore per questa esecuzione.
request_idLa richiesta in entrata che ha causato il lavoro.
experiment_idImpostato quando l’esecuzione è nata da un esperimento.
releaseIl nome di una release o uno sha git.

project è l’unico campo obbligatorio. Quando chi invia non ne indica uno, il daemon archivia il segnale sotto il valore predefinito di --project, così niente viene mai archiviato senza un posto a cui appartenere.

Imposta session_id anche quando sembra ridondante. Una singola esecuzione dell’agente è una traccia, ma una lamentela riguarda quasi sempre una conversazione, e senza un id di sessione non c’è niente che rimetta undici tracce separate nello scambio che quella persona ha avuto davvero.

L’elenco delle tracce filtra direttamente su environment, session_id, thread_id e user_id, insieme a stato, tipo, nome, tag, modello, intervallo di tempo, durata minima, costo minimo e punteggio. Trovare un’esecuzione li mette insieme.

Collegamenti

Uno span ha un solo genitore e un numero qualsiasi di collegamenti. Un collegamento punta a un altro span o a un’altra traccia e dice perché: follows_from, retry_of, replay_of, o come lo chiami tu.

I collegamenti esistono perché il rapporto genitore-figlio non sa esprimere il fan-in. Un lavoro batch causato da venti richieste ha venti collegamenti e un solo genitore. Forzarlo dentro l’albero inventerebbe diciannove sottoalberi duplicati, oppure butterebbe via diciannove delle cause.

Da leggere dopo