e-naxosMAF COURSE / COURS
Français

MICROSOFT AGENT FRAMEWORK · 0.16.0-rc.1

Demo420 — Safe Telemetry

Observe safe spans and distinguish deterministic mode from actual requests.

Objectives

Prepare an isolated experiment

From BaseTechnique or the extracted repository root, build the Release solution. The App project calls ObservabilityDemo in Maf.Observability; Demo420 and Demo430 share this implementation. Documented --deterministic mode loads no model, embeddings or collector. A fresh database distinguishes this experiment’s actions.

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

Run without a model

$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

Record ExecutionId, TraceId and Database. Expect an accepted workflow followed by ActionCommitted and ExecutionSucceeded. Trace: lines contain SafeSpan JSON; Workflow event: lines describe progress. No model consumption is measured in this mode. Identifiers and durations change on every execution.

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

Source code · Maf.Observability · Folder

Inject a failure and read back

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

This new execution has another GUID. --fail interrupts immediately before CommitReview: exit 1, Intention then ExecutionFailed, no ActionCommitted for this GUID. Earlier actions remain. --read expects an existing GUID; enter the execution identifier to inspect.

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

Without --deterministic, the program loads the common connection and calls a real agent with get_review_policy followed by a native reviewer. The required tool call is checked; failure triggers no generated fallback decision. Run only with the configured provider available; request counters can remain null.

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

Check evidence beyond the exit code

In a new process, read the successful execution and verify ActionId with HasAction. Also read the failed execution: readback can exit 0 despite no action, because every present action was verified and none exists. Inspect Kind and ActionId. Tests cover restart, replay of the same GUID, native correlation, excluded secrets and missing usage.

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

Source code · Maf.Observability · Folder

Preserve local scope

The local commit records ReviewRequested; it performs no remote deletion, refund or other remote effect. --erase deletes only the chosen execution’s metadata and is not a business undo. The journal is not immutable. Redirected console output is its owner’s responsibility; no raw file is published on the site.

Follow shared code

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

Source code · Maf.Observability · Folder

Prerequisites

Continue reading

Complete demo folder · README

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