NicoGIS Tech Weekly | AI Engineering · .NET · Distributed Tracing · Azure
Osservabilità degli agenti AI: Microsoft Agent Framework, OpenTelemetry e Azure Monitor
Come ricostruire il percorso di esecuzione di un agente, correlare chiamate a LLM e tool, misurare latenza e token e individuare i colli di bottiglia nei sistemi agentici distribuiti.
Un agente AI non esegue semplicemente una richiesta verso un modello linguistico. Può pianificare operazioni, interrogare sistemi esterni, invocare strumenti, recuperare informazioni e ripetere le chiamate al modello prima di produrre una risposta. Questo cambia radicalmente il problema dell'osservabilità.
In una normale applicazione distribuita, il tracing permette di ricostruire il percorso di una richiesta HTTP attraverso servizi, database e code di messaggi. Nei sistemi agentici occorre estendere lo stesso modello a operazioni non necessariamente deterministiche, il cui numero e ordine possono variare tra un'esecuzione e l'altra.
1. Dall'osservabilità applicativa all'osservabilità agentica
Si consideri un agente incaricato di analizzare un documento aziendale e produrne una sintesi. Potrebbe essere necessaria una prima inferenza per definire il piano, una ricerca, il download del documento e una seconda inferenza per la risposta finale.
Schema della sequenza logica, non rappresentazione rigorosa dei rapporti padre-figlio. Tutte le durate sono illustrative.
Una singola richiesta produce più operazioni correlate. Senza distributed tracing, eventi separati nei log non consentono sempre di ricostruire con certezza l'esecuzione. Con una trace distribuita si possono osservare modello invocato, tool, dipendenze HTTP e database, token, errori, retry e punti di maggiore latenza.
2. OpenTelemetry GenAI Semantic Conventions
OpenTelemetry organizza la telemetria in traces, metrics e logs. Le GenAI Semantic Conventions definiscono vocabolario e attributi per descrivere operazioni di modelli generativi, agenti e tool. Esempi di nomi di operazione includono:
| Operazione | Significato |
|---|---|
invoke_agent | Invocazione di un agente |
chat | Interazione conversazionale con un modello |
execute_tool | Esecuzione di uno strumento |
invoke_workflow | Esecuzione di un workflow agentico, se supportata dall'instrumentation adottata |
plan | Pianificazione, nei sistemi che la rappresentano esplicitamente |
retrieval | Recupero di informazioni, dove previsto dall'instrumentation |
Alcuni attributi utili per analizzare un'esecuzione sono:
gen_ai.operation.name
gen_ai.agent.name
gen_ai.provider.name
gen_ai.request.model
gen_ai.tool.name
gen_ai.usage.input_tokens
gen_ai.usage.output_tokens
Attenzione alla compatibilità: le convenzioni agentiche sono un'area in evoluzione; denominazioni, stabilità e adozione degli attributi possono differire in base alla versione delle specifiche e dei pacchetti. Le operazioni sopra elencate non implicano che ogni runtime le emetta automaticamente. Verificare sempre le convenzioni ufficiali per gli agenti e quelle relative alle operazioni GenAI.
3. L'architettura: da Agent Framework ad Azure Monitor
Il protocollo OTLP permette anche l'invio verso un collector o altri backend compatibili, come Jaeger e Grafana.
Agent Framework e i client strumentati producono segnali. OpenTelemetry raccoglie e correla i dati. Gli exporter li inviano ai backend. Separare questi livelli riduce l'accoppiamento tra orchestrazione dell'agente e prodotto di monitoraggio.
4. Laboratorio .NET: configurare tracing e instrumentation
Un esempio ASP.NET Core può utilizzare la distribuzione Microsoft OpenTelemetry. Il comando per installare il pacchetto è:
dotnet add package Microsoft.OpenTelemetry
La configurazione esatta dipende dalla versione del pacchetto. Nelle versioni che espongono UseMicrosoftOpenTelemetry e ExportTarget, uno schema di configurazione è il seguente:
using Microsoft.OpenTelemetry;
var builder = WebApplication.CreateBuilder(args);
builder.UseMicrosoftOpenTelemetry(options =>
{
options.Exporters =
ExportTarget.AzureMonitor |
ExportTarget.Otlp;
});
var app = builder.Build();
app.MapGet("/health", () => Results.Ok());
app.Run();
La destinazione Azure Monitor utilizza la connection string configurata nell'ambiente:
APPLICATIONINSIGHTS_CONNECTION_STRING
Per OTLP, quando usato, è possibile configurare:
OTEL_EXPORTER_OTLP_ENDPOINT
Questa configurazione abilita la pipeline, ma non crea alcun agente. Per generare span agentici occorre istanziare e invocare componenti effettivamente strumentati.
Instrumentare chat client e agente
Le versioni di Microsoft Agent Framework basate sull'API ChatClientAgent possono essere strumentate tramite UseOpenTelemetry() per il client e WithOpenTelemetry() per l'agente:
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
// chatClient è un IChatClient già configurato.
IChatClient instrumentedClient = chatClient
.AsBuilder()
.UseOpenTelemetry()
.Build();
var agent = new ChatClientAgent(
instrumentedClient,
name: "DocumentAnalyzer",
instructions:
"Analyze documents and report verified findings."
).WithOpenTelemetry();
Frammento focalizzato sull'instrumentation, non un progetto completo eseguibile. Microsoft Agent Framework è in evoluzione: controllare overload, namespace, pacchetti e metodo di creazione dell'agente rispetto alla versione NuGet installata.
Span personalizzati con ActivitySource
Per correlare operazioni applicative si può utilizzare System.Diagnostics.ActivitySource:
using System.Diagnostics;
public static class AgentTelemetry
{
public const string SourceName =
"NicoGIS.TechWeekly.AgentDemo";
public static readonly ActivitySource Source =
new(SourceName);
public static async Task<T> TraceDocumentLoadAsync<T>(
Func<Task<T>> loadDocument)
{
using var activity = Source.StartActivity(
"document.load", ActivityKind.Internal);
try
{
var result = await loadDocument();
activity?.SetTag("document.operation", "load");
return result;
}
catch (Exception ex)
{
activity?.SetStatus(
ActivityStatusCode.Error, ex.Message);
activity?.AddException(ex);
throw;
}
}
}
La ActivitySource personalizzata deve essere aggiunta alla configurazione del tracing:
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
tracing.AddSource(AgentTelemetry.SourceName));
Quando la nuova attività viene aperta in presenza di un contesto Activity.Current valido, il runtime stabilisce la relazione con lo span corrente. Le informazioni applicative possono usare attributi dedicati; le chiavi gen_ai.* vanno invece utilizzate nel rispetto delle convenzioni ufficiali.
5. TraceId, SpanId e propagazione del contesto
La correlazione si fonda sul contesto distribuito e, frequentemente, sugli header W3C Trace Context.
| Elemento | Ruolo |
|---|---|
TraceId | Identifica l'intera esecuzione distribuita. |
SpanId | Identifica una singola operazione. |
ParentSpanId | Collega lo span a quello padre. |
traceparent | Propaga il contesto tra servizi. |
tracestate | Veicola informazioni supplementari del contesto. |
HTTP POST /analyze
└── invoke_agent DocumentAnalyzer
├── chat (planning)
├── execute_tool ReadDocument
│ └── HTTP GET /api/documents/42
│ └── SQL SELECT ...
└── chat (synthesis)
Con le instrumentation HTTP corrette, il contesto attraversa il confine tra client e servizio ricevente. Nel caso dei tool MCP non bisogna dare per scontata la propagazione: trasporto, client, server e intermediari devono supportarla. Quando manca, due segmenti della stessa esecuzione possono comparire come trace indipendenti.
6. Azure Monitor: analisi con KQL
In Application Insights collegato a un workspace Log Analytics, le dipendenze possono essere interrogate tramite la tabella AppDependencies. Per ricostruire gli eventi relativi a un OperationId:
let traceId = "INSERT_TRACE_ID";
AppDependencies
| where OperationId == traceId
| project
TimeGenerated,
Name,
DependencyType,
DurationMs,
Success,
OperationId,
ParentId,
Id,
Properties
| order by TimeGenerated asc
Per identificare le dipendenze con maggiore latenza al 95° percentile:
AppDependencies
| where TimeGenerated > ago(24h)
| summarize
Calls = count(),
Failures = countif(Success == false),
AvgMs = avg(DurationMs),
P95Ms = percentile(DurationMs, 95)
by Name, DependencyType
| order by P95Ms desc
Queste query sono punti di partenza: il mapping delle operazioni GenAI in tabelle e proprietà di Application Insights dipende dall'exporter e dalla versione in uso. È quindi necessario verificare che gli span agentici siano realmente esportati in AppDependencies e che i loro attributi siano disponibili in Properties.
Le metriche GenAI consentono inoltre di osservare durata e consumo, ad esempio con nomi come gen_ai.client.operation.duration e gen_ai.client.token.usage quando emessi dalle librerie utilizzate. Le unità di misura non vanno confuse: DurationMs è espresso in millisecondi, mentre le convenzioni GenAI possono esprimere le durate in secondi.
7. Latenza, token e costo economico
Due esecuzioni dello stesso compito possono produrre una risposta comparabile con un consumo di risorse molto diverso.
| Indicatore | Esecuzione A | Esecuzione B |
|---|---|---|
| Chiamate LLM | 2 | 6 |
| Tool eseguiti | 1 | 4 |
| Token totali | 3.200 | 11.800 |
| Durata | 2,4 s | 8,7 s |
La seconda esecuzione utilizza circa 3,7 volte i token della prima. Questo non indica automaticamente un errore: può dipendere dalla complessità del compito. La trace permette però di verificare retry, retrieval ridondanti, contesti eccessivamente ampi e output dei tool poco pertinenti.
Il costo monetario non coincide con i token totali. Una stima credibile distingue token in ingresso e in uscita, modello, eventuale caching, tariffe, strumenti e risorse esterne.
8. Tracing e valutazione della qualità
L'osservabilità tecnica non equivale a una verifica della correttezza dei risultati. Un sistema agentico maturo dovrebbe rispondere a quattro domande complementari.
| Dimensione | Domanda |
|---|---|
| Tecnica | Dove si trova il collo di bottiglia? |
| Economica | Quanto costa completare la richiesta? |
| Comportamentale | Perché sono stati utilizzati determinati strumenti? |
| Qualitativa | Il risultato è corretto, pertinente e verificabile? |
Il tracing è essenziale per ricostruire la traiettoria esecutiva. La valutazione della qualità richiede invece dataset di test, verifiche dei risultati e controlli sull'uso degli strumenti. Il fatto che una risposta sia stata generata senza errori tecnici non dimostra che sia corretta.
9. Sicurezza e privacy della telemetria
Prompt, risposte, argomenti dei tool e documenti possono contenere informazioni personali, riservate o segreti. Le funzionalità che acquisiscono contenuti sensibili, come EnableSensitiveData dove disponibili, non dovrebbero essere abilitate indiscriminatamente in produzione.
- Redigere o escludere PII, credenziali e dati riservati prima dell'esportazione.
- Applicare retention e sampling proporzionati alle necessità diagnostiche.
- Limitare l'accesso ai workspace e alle dashboard.
- Preferire identificatori tecnici non sensibili per la correlazione.
- Controllare la cardinalità di tag e dimensioni metriche.
Inserire prompt interi e identificatori ad alta cardinalità nelle metriche può comportare rischi di sicurezza e costi elevati. I contenuti delle conversazioni richiedono un trattamento diverso da normali misure di durata o conteggi.
10. Conclusioni: verso l'osservabilità delle traiettorie agentiche
La principale evoluzione consiste nel passaggio dal monitoraggio di singole chiamate ai modelli all'analisi di traiettorie di esecuzione: la sequenza concreta di inferenze, tool e dipendenze attraversata dall'agente per raggiungere un risultato.
Microsoft Agent Framework fornisce i componenti di orchestrazione; OpenTelemetry introduce un modello interoperabile di tracing, metriche e log; Azure Monitor rende possibile la correlazione e l'analisi in produzione. Per ottenere un sistema affidabile occorre completare questa telemetria con controlli sulla qualità delle risposte e sulle decisioni operative.
Nessun commento:
Posta un commento