MICROSOFT AGENT FRAMEWORK · 0.16.0-rc.1
Demo430 — Business Audit
Run the workflow and read back the local effect, then compare an injected failure.
Objectives
- Reopen the separate business journal and distinguish effects from traces.
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 ReleaseRun without a model
$journal = Join-Path $env:TEMP ("maf-lot012-" + [guid]::NewGuid().ToString("N") + ".db")dotnet run --project demos/Demo430_BusinessAudit/Demo430.App.csproj -c Release --no-build -- --deterministic --db $journalRecord 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 long CommitReview(Guid executionId)
{
using var connection = Open();
using var transaction = connection.BeginTransaction();
using var command = connection.CreateCommand();
command.Transaction = transaction;
command.CommandText = "INSERT INTO RecordedDecisions(ExecutionId,Decision) VALUES($id,'ReviewRequested') ON CONFLICT DO NOTHING";
command.Parameters.AddWithValue("$id", executionId.ToString("N"));
bool created = command.ExecuteNonQuery() == 1;
command.CommandText = "SELECT Id FROM RecordedDecisions WHERE ExecutionId=$id";
long id = (long)command.ExecuteScalar()!;
if (created) Insert(connection, transaction, executionId, JournalKind.ActionCommitted, id);
transaction.Commit();
return id;
Inject a failure and read back
dotnet run --project demos/Demo430_BusinessAudit/Demo430.App.csproj -c Release --no-build -- --deterministic --fail --db $journalThis 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/Demo430_BusinessAudit/Demo430.App.csproj -c Release --no-build -- --db $journal --read $executionIdWithout --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/Demo430_BusinessAudit/Demo430.App.csproj -c Release --no-build -- --db $journalCheck 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-restorepublic bool HasAction(Guid executionId, long actionId)
{
using var connection = Open();
using var command = connection.CreateCommand();
command.CommandText = "SELECT COUNT(*) FROM RecordedDecisions WHERE ExecutionId=$id AND Id=$action";
command.Parameters.AddWithValue("$id", executionId.ToString("N"));
command.Parameters.AddWithValue("$action", actionId);
return (long)command.ExecuteScalar()! == 1;
Source code · Maf.Observability · Folder
[
{
"ActionId": null,
"ExecutionId": "50779844-cf13-4867-bce1-c4aa87657161",
"Id": 1,
"Kind": 0,
"TraceId": "cde643d10fdee1c7910ad01766baba4d",
"Utc": "2026-10-24T19:12:56.6041955+00:00"
},
{
"ActionId": null,
"ExecutionId": "50779844-cf13-4867-bce1-c4aa87657161",
"Id": 2,
"Kind": 1,
"TraceId": "cde643d10fdee1c7910ad01766baba4d",
"Utc": "2026-10-24T19:12:56.7815492+00:00"
},
{
"ActionId": 1,
"ExecutionId": "50779844-cf13-4867-bce1-c4aa87657161",
"Id": 3,
"Kind": 3,
"TraceId": "cde643d10fdee1c7910ad01766baba4d",
"Utc": "2026-10-24T19:12:56.8936463+00:00"
},
{
"ActionId": null,
"ExecutionId": "50779844-cf13-4867-bce1-c4aa87657161",
"Id": 4,
"Kind": 4,
"TraceId": "cde643d10fdee1c7910ad01766baba4d",
"Utc": "2026-10-24T19:12:56.9878252+00:00"
}
]
Output actually read back on 24 October 2026 without a model; isolated extracted sources match canonical code. The serializer retains numeric Kind: 0=RequestReceived, 1=Intention, 3=ActionCommitted, 4=ExecutionSucceeded. The checker also read RecordedDecisions from SQLite and verified the same ActionId. GUIDs, UTC timestamps and TraceId belong to this experiment; do not copy them into a new command.
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 long CommitReview(Guid executionId)
{
using var connection = Open();
using var transaction = connection.BeginTransaction();
using var command = connection.CreateCommand();
command.Transaction = transaction;
command.CommandText = "INSERT INTO RecordedDecisions(ExecutionId,Decision) VALUES($id,'ReviewRequested') ON CONFLICT DO NOTHING";
command.Parameters.AddWithValue("$id", executionId.ToString("N"));
bool created = command.ExecuteNonQuery() == 1;
command.CommandText = "SELECT Id FROM RecordedDecisions WHERE ExecutionId=$id";
long id = (long)command.ExecuteScalar()!;
if (created) Insert(connection, transaction, executionId, JournalKind.ActionCommitted, id);
transaction.Commit();
return id;
