e-naxosMAF COURSE / COURS
Français

MICROSOFT AGENT FRAMEWORK · 0.16.0-rc.1

Proposed plans and controlled execution

Read a plan as a bounded proposal, then check what the host actually executes.

Objectives

A plan is data

The request “Add a CSV export to Reporting” may suggest create_backlog then respond. J2 already separated proposal from execution; that separation remains essential. A steps array describes intentions. The program must still decide whether each step is allowed, whether arguments are admissible and which effect it authorizes. All three programs in this progression print simulated execution: retrieve does not search SQLite and create_backlog creates no row.

From a C# type to a plan contract

Demo270 calls RunAsync<Plan> then iterates over Steps. The switch recognizes retrieve, create_backlog, ask_user and respond, and stops at the first unknown type. The prompt requests two to four steps; that request is not host validation of cardinality or consistency. A late unknown step can be discovered after earlier steps have already been printed. Planner sessions stay in-process.

AgentResponse<Plan> planResp = await planner.RunAsync<Plan>(input, session: session, serializerOptions: jsonOpts);
var plan = planResp.Result;

Console.WriteLine("\n[PLAN]");
int i = 1;
foreach (var s in plan.Steps)
    Console.WriteLine($"{i++}. {s.Type} ({s.Argument})");

Console.WriteLine("\n[EXECUTION SIMULÉE]");

demos/Demo270_Planning/Program.cs · L33–L41 · 9a895c94534c

Source code · Demo270 · Folder

Plan boundaries
  1. Request → model → JSON proposal
  2. Format control → host validation → deserialization
  3. Allowlisted interpreter → simulated steps
  4. A real effect would require additional authorization, business validation and stored evidence

Validate the whole plan before iterating steps

Demo280 obtains raw text, extracts a JSON object by optionally removing fences and selecting from the first opening brace to the last closing brace, then evaluates the schema. This extractor is limited cleanup, not a general parser of mixed responses. The schema forbids extra properties, bounds steps from one to four and restricts step types. When present, argument must contain one to 400 characters; it is required for ask_user, respond and create_backlog but optional for retrieve.

    // 3) Validation JSON Schema (+ retry unique si invalide)
    if (!ValidatePlanJson(jsonText, out var err))
    {
        Console.WriteLine("⚠️ Plan JSON invalide. Retry unique...");
        Console.WriteLine(err);

        var repairPrompt = $"""
Tu as renvoyé un JSON invalide ou non conforme.
Corrige-le et renvoie UNIQUEMENT un JSON valide, sans texte autour, conforme à ce schéma :

{PlanJsonSchema}

Demande utilisateur :
{input}
""";

        var rawResp2 = await planner.RunAsync(message: repairPrompt, session: session);
        var rawText2 = GetResponseText(rawResp2);
        jsonText = ExtractJsonObject(rawText2);

        if (!ValidatePlanJson(jsonText, out err))
        {
            Console.WriteLine("⛔ JSON toujours invalide après retry. Arrêt.");
            Console.WriteLine(err);
            Console.WriteLine();
            continue;
        }
    }

    // 4) Désérialisation une fois validé

demos/Demo280_ValidatedPlanning/Program.cs · L92–L121 · 9a895c94534c

Source code · Demo280 · Folder

A first schema failure triggers one repair call. A second failure prints rejection and continues to the next request without printing [EXECUTION SIMULÉE] for that plan. Deserialization follows whole-plan validation. This does not establish that an allowed sequence is sensible: two identical creations can satisfy the schema. Semantic rules and permissions must be defined before connecting real services.

Request the format and validate again

Demo290 compiles the schema once and reuses it. AgentRunOptions.ResponseFormat supplies ForJsonSchema at invocation, including the repair call. The response is only trimmed, without ExtractJsonObject. Host validation remains: requesting a format proves neither actual provider support nor business authorization. Earlier material called this variant ready for industrialization; here that describes stronger formatting without turning the simulation into a production service.

var compiledSchema = JsonSchema.FromText(PlanJsonSchema);

using var schemaDoc = JsonDocument.Parse(PlanJsonSchema);
JsonElement schemaElement = schemaDoc.RootElement.Clone();

// ResponseFormat explicite au moment de l'appel.
var runOptions = new AgentRunOptions
{
    ResponseFormat = ChatResponseFormat.ForJsonSchema(
        schemaElement,
        schemaName: "Plan",
        schemaDescription: "Short execution plan with 1 to 4 steps")

demos/Demo290_FormattedPlanning/Program.cs · L78–L89 · 9a895c94534c

Source code · Demo290 · Folder

A reproducibly rejected plan

In a working copy of Demo280, temporarily replace both model-derived jsonText assignments with the same JSON text {"steps":[{"type":"delete_all","argument":"Reporting"}]}. This teaching injection point is after the response and before ValidatePlanJson; it does not change the schema. Build the copy and submit a request. Expect two invalid evaluations, one repair call and no simulated execution for that request. Repeat with empty steps, five steps, then respond without argument. Never modify the canonical distribution for this exercise.

To isolate validation without a model, this lot’s local check extracts the schema and the actual ValidatePlanJson function into a private verification executable. It checks counterexamples and a valid plan. This check tests neither live generation nor the complete repair loop; retain that distinction in the report.

What conformance does not guarantee

None of the three programs opens a RAG index, invokes a write tool or suspends a workflow on ask_user. Each branch prints text. A future real interpreter must add business argument validation, access control, deadlines, failure handling and effect idempotency. Simulated output must never be presented as a created ticket or obtained approval.

Read the three variants

Prerequisites

Continue reading

lot009-workflows-1 · 2026-10-24 · 9a895c94534cd5fc6f3da883e37e5f7856e588c1