e-naxosMAF COURSE / COURS
English

MICROSOFT AGENT FRAMEWORK · 0.16.0-rc.1

Demo420 — Safe Telemetry

Observer des spans sûrs et distinguer mode déterministe et requêtes réelles.

Objectifs

Préparer un essai isolé

Depuis la racine BaseTechnique ou du dépôt extrait, compiler la solution Release. Le projet App appelle ObservabilityDemo dans Maf.Observability ; Demo420 et Demo430 partagent cette implémentation. Le mode documenté --deterministic ne charge aucun modèle, embedding ou collecteur. Une base neuve permet de distinguer les actions de cet essai.

dotnet build BaseTechnique.slnx -m:1 -c Release

Lancer sans modèle

$journal = Join-Path $env:TEMP ("maf-lot012-" + [guid]::NewGuid().ToString("N") + ".db")
dotnet run --project demos/Demo420_SafeTelemetry/Demo420.App.csproj -c Release --no-build -- --deterministic --db $journal

Noter ExecutionId, TraceId et Database. Attendre le workflow accepté puis ActionCommitted et ExecutionSucceeded. Les Trace: sont des JSON SafeSpan ; les Workflow event: sont des événements de progression. Dans ce mode, aucune consommation modèle n’est mesurée. Les identifiants et durées changent à chaque exécution.

public static SafeSpan Project(Activity activity) => new(
    activity.Source.Name == Source.Name ? "host" : activity.Source.Name.StartsWith("System.Net.Http", StringComparison.Ordinal)
        ? "http" : activity.Source.Name.StartsWith("Microsoft.Agents.AI.Workflows", StringComparison.Ordinal)
            ? "maf.workflow" : activity.Source.Name.StartsWith("Microsoft.Extensions.AI", StringComparison.Ordinal)
                ? "maf.model" : "maf.agent",
    activity.Source.Name == Source.Name && activity.OperationName is "execution" or "tool" or "workflow" or "model"
        ? activity.OperationName : "operation",
    activity.TraceId.ToString(), activity.SpanId.ToString(), activity.ParentSpanId.ToString(),
    activity.Duration.TotalMilliseconds, activity.Status.ToString());

shared/Maf.Observability/Telemetry.cs · L30–L38 · 9a895c94534c

Code source · Maf.Observability · Dossier

Injecter une panne et relire

dotnet run --project demos/Demo420_SafeTelemetry/Demo420.App.csproj -c Release --no-build -- --deterministic --fail --db $journal

Cette nouvelle exécution a un autre GUID. --fail interrompt immédiatement avant CommitReview : sortie 1, Intention puis ExecutionFailed, aucun ActionCommitted pour ce GUID. Les actions antérieures restent présentes. --read attend un GUID existant ; remplacer la valeur de saisie par celle de l’exécution à examiner.

$executionId = Read-Host 'ExecutionId to inspect'
dotnet run --project demos/Demo420_SafeTelemetry/Demo420.App.csproj -c Release --no-build -- --db $journal --read $executionId

Sans --deterministic, le programme charge la connexion commune et appelle un vrai agent avec get_review_policy puis un reviewer natif. L’appel outil obligatoire est vérifié ; une panne ne déclenche aucune décision générée de secours. Exécuter uniquement avec le fournisseur configuré disponible ; les compteurs par requête peuvent rester null.

dotnet run --project demos/Demo420_SafeTelemetry/Demo420.App.csproj -c Release --no-build -- --db $journal

Vérifier la preuve, pas seulement la sortie

Dans un nouveau processus, relire le succès et vérifier ActionId avec HasAction. Relire aussi l’échec : son code de lecture peut être 0 malgré l’absence d’action, car toutes les actions présentes ont été vérifiées et il n’y en a aucune. Lire Kind et ActionId. Les tests contrôlent reprise, rejeu du même GUID, corrélation native, secrets exclus et usage manquant.

dotnet test tests/Maf.Observability.Tests/Maf.Observability.Tests.csproj -m:1 -c Release --no-build --no-restore
var input = usage?.InputTokenCount;
var output = usage?.OutputTokenCount;
long? derived = input.HasValue && output.HasValue ? checked(input.Value + output.Value) : null;
decimal? cost = rate is not null && input.HasValue && output.HasValue
    ? (input.Value * rate.InputPerMillion + output.Value * rate.OutputPerMillion) / 1_000_000m : null;
return new(input, output, usage?.TotalTokenCount, derived,
    contextCharacters.HasValue ? ((long)contextCharacters.Value + 3) / 4 : null,
    cost, rate?.Currency, rate?.Version);

shared/Maf.Observability/Consumption.cs · L16–L23 · 9a895c94534c

Code source · Maf.Observability · Dossier

Préserver la portée locale

Le commit local porte ReviewRequested ; il ne supprime, rembourse ou crée aucun effet distant. --erase supprime seulement les métadonnées de l’exécution choisie et n’est pas une annulation métier. Le journal n’est pas immuable. Une redirection de console est sous la responsabilité de son propriétaire ; aucun fichier brut n’est publié sur le site.

Suivre le code partagé

public static TracerProvider CreateProvider(Action<SafeSpan> write) => Sdk.CreateTracerProviderBuilder()
    .AddSource("Maf.Renovation", "Maf.NativeAgent", "Microsoft.Agents.AI*", "Microsoft.Extensions.AI*")
    .AddHttpClientInstrumentation()
    .AddProcessor(new SimpleActivityExportProcessor(new SafeExporter(write))).Build();

/// <summary>Adds the native MAF decorator with sensitive data explicitly disabled.</summary>
public static AIAgent Instrument(AIAgent agent) => agent.AsBuilder()
    .UseOpenTelemetry(sourceName: "Maf.NativeAgent", configure: options => options.EnableSensitiveData = false).Build();

shared/Maf.Observability/Telemetry.cs · L20–L27 · 9a895c94534c

Code source · Maf.Observability · Dossier

Prérequis

Pour poursuivre

Dossier complet de la démo · README

lot012-observability-1 · 2026-10-24 · 9a895c94534cd5fc6f3da883e37e5f7856e588c1