e-naxosMAF COURSE / COURS
Français

MICROSOFT AGENT FRAMEWORK · 0.16.0-rc.1

Integrated documented action

Carry eligible documentary evidence through an external decision to a unique SQLite effect after resumption.

Objectives

The final step of the main path

Demo470 joins the course mechanisms around a fixed question: Where can I export CSV in Reporting? The problem now goes beyond obtaining an answer. Show which passage supports it, which draft was presented, where the host decision enters and which row exists after restart. The main path ends here; Demo480 and Demo490 extend the discussion without being prerequisites for this manipulation.

From document to business row
  1. Corpus eligible on 23 October 2026 → SQLite vector retrieval
  2. AnswerGate → exact quotation → validated BacklogDraft
  3. ApprovalTicket → RequestPort → Waiting checkpoint
  4. External approve/reject command → resumption → business readback

Admit evidence before requesting a decision

Corpus policy filters sources by reference date, course scope and eligibility before ranking. Microsoft.Data.Sqlite stores dense vectors; exact cosine is computed in C#. The fixture uses controlled two-dimensional vectors and selects ACME-EXPORT. These are real vectors searched in SQLite with inputs chosen to teach the chain, without measuring embedding quality.

Console.WriteLine("Profile=fixture; controlled dense vectors and answer; no model qualification");
var manifest = IndexManifest.Create(corpus, "fixture", "fixture", "controlled-2d-v1", 2);
var chunks = CorpusPolicy.Chunks(corpus);
vectors.Rebuild(corpus, manifest, chunks.Select(c => c.Source.Id == "ACME-EXPORT"
    ? new float[] { 1, 0 } : new float[] { 0, 1 }).ToArray());
var hits = vectors.Search(corpus, manifest, [1, 0], asOf, "course");
var selected = hits.Single(h => h.Chunk.Source.Id == "ACME-EXPORT");
answer = AnswerGate.Validate(new(true, [new(args.Contains("--invalid-evidence")
    ? "INVENTED#0" : selected.Chunk.Id, selected.Chunk.Text)]), new(question, asOf, hits, null));

demos/Demo470_DocumentedApproval/Program.cs · L53–L61 · 9a895c94534c

Source code · Demo470 · Folder

AnswerGate requires an actionable proposal, evidence from eligible results and an exact quotation of at least twenty characters after Trim. Final text is rebuilt from identifier/quotation pairs; free paraphrase does not become evidence. --invalid-evidence replaces the identifier with INVENTED#0: rejection precedes approval registration. An authentic quotation proves its presence in the passage, not universal document truth or the correctness of every interpretation.

Freeze the proposal to be approved

if (!answer.Accepted) throw new InvalidOperationException(answer.Text);
var ticket = new ApprovalTicket(Guid.NewGuid().ToString("N"), new BacklogDraft(
    "Review Reporting CSV export", "Question", "medium", "Reporting", answer.Text, []));
if (ticket.Draft.Validate().Length != 0) throw new InvalidOperationException("Evidence exceeds the business contract.");
await using var run = await InProcessExecution.RunStreamingAsync(ApprovalWorkflow.Build(store), ticket,
    manager, cancellationToken: timeout.Token);
var receipt = await ApprovalDemo.CaptureWaitingAsync(run, ticket.OperationId, timeout.Token);
File.WriteAllText(Path.Combine(directory, "evidence.json"), JsonSerializer.Serialize(answer));
File.WriteAllText(receiptPath, JsonSerializer.Serialize(receipt));

demos/Demo470_DocumentedApproval/Program.cs · L63–L71 · 9a895c94534c

Source code · Demo470 · Folder

public void Register(ApprovalTicket ticket)
{
    if (string.IsNullOrWhiteSpace(ticket.OperationId) || ticket.Draft.Validate().Length != 0)
        throw new ArgumentException("A valid operation and actionable draft are required.");
    using var connection = Open();
    using var command = connection.CreateCommand();
    command.CommandText = "INSERT INTO Approvals VALUES ($id,$draft,NULL,'Waiting') ON CONFLICT DO NOTHING";
    command.Parameters.AddWithValue("$id", ticket.OperationId);
    command.Parameters.AddWithValue("$draft", JsonSerializer.Serialize(ticket.Draft));
    command.ExecuteNonQuery();
    if (JsonSerializer.Serialize(Read(ticket.OperationId).Draft) != JsonSerializer.Serialize(ticket.Draft))
        throw new InvalidOperationException("The operation key is already bound to another draft.");

shared/Maf.Durable/ApprovalStore.cs · L39–L50 · 9a895c94534c

Source code · Maf.Durable · Folder

The host creates OperationId then BacklogDraft with answer.Text in Summary. Validate protects the business contract before the graph. Register binds the key to the exact draft JSON and rejects reuse for different content. evidence.json remains a diagnostic copy: editing it does not rewrite Draft already registered in business.db. Immutability is a rule of this API over trusted host storage; it does not resist an administrator editing files.

The RequestPort suspends the graph without writing an approved item. waiting.json retains GraphVersion, SessionId, CheckpointId, OperationId and RequestId. These identify the same observed request rather than reconstructing an approximate proposal from the latest model prose. The external decision is an explicit operator command; this console verifies no approver identity or role.

Resume the graph and verify the effect

var saved = JsonSerializer.Deserialize<WaitingReceipt>(File.ReadAllText(receiptPath))!;
if (saved.GraphVersion != ApprovalWorkflow.Version) throw new InvalidOperationException("Graph version mismatch.");
if (args[0] == "resume")
{
    if (args.Length != 3 || args[2] is not ("approve" or "reject"))
        throw new ArgumentException("An explicit approve or reject decision is required.");
    var decision = new ApprovalDecision(saved.OperationId, args[2], "External business decision.");
    await using var run = await InProcessExecution.ResumeStreamingAsync(ApprovalWorkflow.Build(store),
        new CheckpointInfo(saved.SessionId, saved.CheckpointId), manager, timeout.Token);
    await ApprovalDemo.RespondAsync(run, store, saved.OperationId, saved.RequestId, decision, timeout.Token);
}
Print(store.Read(saved.OperationId));

demos/Demo470_DocumentedApproval/Program.cs · L77–L88 · 9a895c94534c

Source code · Demo470 · Folder

public ApprovalState Apply(ApprovalDecision decision)
{
    RecordDecision(decision);
    using var connection = Open();
    using var transaction = connection.BeginTransaction();
    using var command = connection.CreateCommand();
    command.Transaction = transaction;
    command.CommandText = """
        INSERT INTO ApprovedBacklogItems (OperationId,Draft,CreatedUtc)
        SELECT OperationId,Draft,$utc FROM Approvals WHERE OperationId=$id AND Status IN ('Approved','Completed')
        ON CONFLICT(OperationId) DO NOTHING;
        UPDATE Approvals SET Status='Completed' WHERE OperationId=$id AND Status='Approved';
        """;
    command.Parameters.AddWithValue("$id", decision.OperationId);
    command.Parameters.AddWithValue("$utc", DateTimeOffset.UtcNow.ToString("O"));
    command.ExecuteNonQuery();
    transaction.Commit();
    return Read(decision.OperationId);

shared/Maf.Durable/ApprovalStore.cs · L80–L97 · 9a895c94534c

Source code · Maf.Durable · Folder

A new process rebuilds the same graph version and restores its checkpoint. The response must match the expected operation and request. RecordDecision accepts approve or reject with a bounded comment; the first persisted decision wins and only its exact repetition is accepted. Rejection is not a pending state to convert into approval later: create a new proposal for a new decision.

Apply first records the decision, then a transaction inserts ApprovedBacklogItems from the persisted draft and marks Completed. UNIQUE(OperationId) prevents a second effect. If insertion fails, the transaction rolls back effect and completion while the decision can remain Approved and be retried. If the process fails after commit, replay returns the same row. Read ItemId, StoredItem and row count; workflow output alone is insufficient.

Attribute each proof to its mechanism

Persisted objects and responsibilities
MechanismScope
vectors.dbVector index; not a decision
business.dbDraft, first decision and business item
checkpoints + waiting.jsonNative graph resumption boundary
evidence.jsonDiagnostic; does not control resumption
host.lockProcess exclusion on this host

Each phase emits restricted traces. OperationId durably relates phases; it does not turn their traces into a continuous distributed trace. Demo470 does not produce Demo430’s transactional ActionCommitted journal. Its effect evidence is in business.db rows. Retrieval, checkpoint files and the business transaction do not form a single cross-module transaction.

What success leaves to decide

The fixture qualifies no model. --live rebuilds the index with the configured embedding provider then calls the native answer agent; refusal or failure remains visible without fixture fallback. The granite4:3b candidate/judge profile remains unqualified and independent human domain validation remains unestablished. This console publishes no HTTP route, Web form or authenticated approval service. Demo410 interfaces are a separate application.

Execute then extend

Prerequisites

Continue reading

Previous

lot013-integration-1 · 2026-10-24 · 9a895c94534cd5fc6f3da883e37e5f7856e588c1