<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>Educator Developer Blog articles</title>
    <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/bg-p/EducatorDeveloperBlog</link>
    <description>Educator Developer Blog articles</description>
    <pubDate>Tue, 01 Sep 2026 02:43:29 GMT</pubDate>
    <dc:creator>EducatorDeveloperBlog</dc:creator>
    <dc:date>2026-09-01T02:43:29Z</dc:date>
    <item>
      <title>Adding a Fallback Model to Hermes with Microsoft Foundry</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/adding-a-fallback-model-to-hermes-with-microsoft-foundry/ba-p/4541254</link>
      <description>&lt;P&gt;So the plan was simple. Leave the Bedrock configuration untouched, then wire Microsoft Foundry in behind it as a fallback, so Hermes always has somewhere else to go when the primary provider is not responding. A few other reasons pushed me towards Foundry in particular:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Redundancy that does not need me. If Bedrock is throttled or out of quota, I want Hermes to fail over on its own rather than waiting for me to notice.&lt;/LI&gt;
&lt;LI&gt;A catalogue I already pay for. Foundry puts the latest GPT models next to open-weight and partner models in one place, so I can pick a model that suits the task instead of settling for whatever a single provider happens to offer.&lt;/LI&gt;
&lt;LI&gt;Enterprise controls out of the box. Region pinning, private networking, content filters and per-deployment quota all sit in the same portal, which makes the setup far easier to defend to a security reviewer.&lt;/LI&gt;
&lt;LI&gt;Learning the mechanics before I need them. Working out how Hermes handles a provider chain is much nicer on a quiet Tuesday than during a live outage.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Here is the short version, if you are deciding whether to read on. Time: about thirty minutes if nothing goes wrong. Cost: pay-as-you-go tokens only, and none at all while the fallback sits idle. Result: an assistant that keeps answering when your primary provider stops.&lt;/P&gt;
&lt;P&gt;Before you start, you will need three things: a machine with Hermes already installed and a working primary provider configured, an Azure subscription with access to Microsoft Foundry in a region you can actually deploy into, and enough quota in that region to create a deployment.&lt;/P&gt;
&lt;P&gt;One thing that made this easy to justify: Foundry deployments bill per token on the standard pay-as-you-go tier. A fallback provider that never gets invoked costs nothing beyond the requests it actually serves, so the insurance is close to free until the day you need it.&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table class="lia-border-style-solid" border="1" style="width: 1052px; height: 63px; border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P class="lia-align-center"&gt;Chat surface&lt;/P&gt;
&lt;P&gt;(CLI, messaging)&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;→&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Hermes Gateway&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;→&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Primary&lt;/P&gt;
&lt;P&gt;Amazon Bedrock&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;→&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Fallback&lt;/P&gt;
&lt;P&gt;Microsoft Foundry&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;colgroup&gt;&lt;col style="width: 14.29%" /&gt;&lt;col style="width: 14.29%" /&gt;&lt;col style="width: 14.29%" /&gt;&lt;col style="width: 14.29%" /&gt;&lt;col style="width: 14.29%" /&gt;&lt;col style="width: 14.29%" /&gt;&lt;col style="width: 14.29%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;EM&gt;Figure 1: Where the fallback sits. Every request goes through the Hermes gateway to the primary provider; only when that provider is unavailable does the chain continue to Microsoft Foundry.&lt;/EM&gt;&lt;/P&gt;
&lt;H2&gt;Part 1: Deploying a Model on Microsoft Foundry&lt;/H2&gt;
&lt;P&gt;The first half of this job happens entirely inside the Microsoft Foundry portal and has nothing to do with Hermes yet. All you are really doing here is making sure your Azure subscription can serve a model, and that you hold an endpoint and key Hermes can authenticate with later.&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table class="lia-border-style-solid" border="1" style="width: 1069px; height: 27px; border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;1. Deploy model in Foundry&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;→&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;2. Copy endpoint + key&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;→&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;3. hermes fallback add&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;→&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;4. Authenticate&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;→&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;5. Select models, test&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;colgroup&gt;&lt;col style="width: 11.11%" /&gt;&lt;col style="width: 11.11%" /&gt;&lt;col style="width: 11.11%" /&gt;&lt;col style="width: 11.11%" /&gt;&lt;col style="width: 11.11%" /&gt;&lt;col style="width: 11.11%" /&gt;&lt;col style="width: 11.11%" /&gt;&lt;col style="width: 11.11%" /&gt;&lt;col style="width: 11.11%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;EM&gt;Figure 2: The whole setup in five moves. The first two happen in the Microsoft Foundry portal (orange); the rest happen on the Hermes machine (blue).&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Go to Microsoft Foundry &amp;gt; Build &amp;gt; Models &amp;gt; Deploy &amp;gt; Deploy a base model. You can deploy a fine-tuned model instead if you already have one, which works just as well with Hermes. Check the region shown at the top of the portal before you commit, because both model availability and deployment quota differ from one region to the next. Then deploy the model you have selected:&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;In this case I deployed gpt-5.6-sol, which is the model Hermes will fall back to.&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;The choice was deliberate rather than exciting. My primary model on Bedrock is a general-purpose chat model, and a fallback is only useful if the answers it gives feel like a continuation of the same conversation rather than a different assistant wearing the same name. The gpt-5.6-sol deployment matches that behaviour closely, it was available in the region I wanted to pin, and the quota I was granted comfortably covers a day of normal use. If a fallback surprises you the first time it fires, it is the wrong fallback.&lt;/P&gt;
&lt;P&gt;Once the deployment finishes, open it and take note of two values: the target endpoint URI and the API key. Copy both somewhere safe now, because you will be pasting them into Hermes in the next part. If your organisation rotates keys on a schedule, use a key with the longest life you are allowed, since a fallback secured with a credential that expires quietly stops being a fallback.&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table class="lia-border-style-solid" border="1" style="width: 76.5741%; height: 210px; border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;What to copy&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;Where it lives in the portal&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;Where Hermes asks for it&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Target endpoint URI&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Deployment &amp;gt; Endpoint &amp;gt; Target URI&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;"Endpoint" prompt in hermes fallback add&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;API key&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Deployment &amp;gt; Endpoint &amp;gt; Key&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;"API key" prompt, or choose Entra ID instead&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Deployment name&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Deployment &amp;gt; Details &amp;gt; Name&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Shown in the model list Hermes returns&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Region&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Top of the portal, next to the resource&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Must match the region you deployed into&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 33.33%" /&gt;&lt;col style="width: 33.33%" /&gt;&lt;col style="width: 33.33%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;EM&gt;Figure 3: Everything Hermes will ask for, and where to find each value before you leave the portal.&lt;/EM&gt;&lt;/P&gt;
&lt;H2&gt;Part 2: Adding Foundry to Hermes as a Fallback&lt;/H2&gt;
&lt;P&gt;With the Foundry side sorted, everything from here happens in the Hermes CLI. One thing worth knowing before you start: this is the fallback command, not the primary model command, so your existing Bedrock configuration is left completely alone. Nothing in this section can break what is already working, which makes it a good one to try on a live setup.&lt;/P&gt;
&lt;P&gt;Run the Hermes fallback command:&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;When Hermes asks which provider to add, choose Azure Foundry. The picker still carries the old name; it is the same service that the portal now calls Microsoft Foundry.&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;Paste the target endpoint URI from your deployment, then authenticate with the API key you copied earlier. Hermes also offers Microsoft Entra ID at this prompt, which is the better option if your organisation would rather not have a static key sitting on the machine. If authentication fails here, check the endpoint before you start suspecting the key. In my experience the endpoint is wrong far more often than the credential is, usually because the deployment name at the end of the URI does not match the deployment you actually created.&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;Once authentication succeeds, Hermes lists the deployments your Foundry resource exposes and asks which ones you want to use. You can select more than one, and the order is not cosmetic: Hermes walks down the chain from top to bottom whenever the provider above is unavailable. Treat that list as a priority order, not a shopping basket.&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table class="lia-border-style-solid" border="1" style="width: 81.6667%; height: 285px; border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;What happens to the primary&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;What Hermes does&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;What you see in the chat&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Responds normally&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Routes every request to the primary and never touches the chain&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Nothing. The fallback stays idle&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Throttled or out of quota&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Retries the next provider down the chain on the same request&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;A reply, served by the fallback model&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Endpoint unreachable&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Keeps failing over on each new request until the primary recovers&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Slightly different tone and latency, but a working assistant&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Every provider fails&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Returns the error rather than hanging&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;An error worth chasing with hermes status&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 33.33%" /&gt;&lt;col style="width: 33.33%" /&gt;&lt;col style="width: 33.33%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;EM&gt;Figure 4: The chain in practice. The fallback only earns its keep in the middle two rows, which is exactly why it is easy to forget you configured it.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Part 3: Promoting Foundry to the Primary Model&lt;/H2&gt;
&lt;P&gt;At this stage Foundry is sitting in the back seat as a backup. I wanted to reverse the arrangement and make Foundry the primary while Bedrock slides down into the fallback slot, partly because I preferred keeping day-to-day traffic inside my Azure subscription, and partly because I wanted proof the chain works in both directions.&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table class="lia-border-style-none" border="1" style="width: 638px; height: 89px; border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;Before promotion&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td style="border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;&amp;nbsp;&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;After promotion&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Primary: Amazon Bedrock&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;→&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Primary: Microsoft Foundry&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Fallback: Microsoft Foundry&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;→&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="border-width: 1px;"&gt;
&lt;P&gt;Fallback: Amazon Bedrock&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 33.33%" /&gt;&lt;col style="width: 33.33%" /&gt;&lt;col style="width: 33.33%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;EM&gt;Figure 5: The promotion, in effect. Nothing is added or removed; the two providers simply trade places in the chain.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;There is no dedicated "promote" command in Hermes, so the manual route is a short sequence of steps rather than a single instruction:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Select the fallback provider/model as the new primary: hermes model&lt;/LI&gt;
&lt;LI&gt;Remove the now-duplicate model from the fallback chain: hermes fallback remove&lt;/LI&gt;
&lt;LI&gt;Optionally add the old primary model as a fallback: hermes fallback add&lt;/LI&gt;
&lt;LI&gt;Restart the messaging gateway: hermes gateway restart&lt;/LI&gt;
&lt;LI&gt;Verify the result: hermes status&amp;nbsp; /&amp;nbsp; hermes fallback list&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;That sequence works, and it is good to know what is happening underneath. But since I already had a working provider configured, I would rather just ask Hermes to rearrange itself. This is the part I genuinely enjoy about the tool: the configuration is something you can talk to, not only something you type commands at.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;Prompt: Okay now please make the model I configured on Microsoft Foundry into the main model, and make the Bedrock one the fallback model!&lt;/EM&gt;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Hermes rewrites the provider chain on its own and confirms the swap once it is done, which is a great deal less error-prone than running the five commands by hand.&lt;/P&gt;
&lt;H2&gt;Part 4: Testing the Switch&lt;/H2&gt;
&lt;P&gt;Configuration you have not tested is just an assumption with extra steps, so the next thing is to confirm Hermes really is talking to Foundry.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Type /model when running Hermes to bring up the model picker.&lt;BR /&gt;&lt;img /&gt;&lt;/LI&gt;
&lt;LI&gt;You will be prompted to select a provider first. Pick the Microsoft Foundry entry, then choose the specific deployment from the list underneath it.&lt;/LI&gt;
&lt;/UL&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The active model should switch straight away. Send it a plain "Hello" to check that the deployment actually responds, rather than just looking correct in the menu. Appearing in a dropdown and serving a request are two very different things.&lt;/LI&gt;
&lt;/UL&gt;
&lt;img /&gt;
&lt;P&gt;A second test is worth the thirty seconds it costs: run hermes status to confirm which provider is live, then hermes fallback list to confirm the chain is ordered the way you intended. The picker tells you what you selected; those two commands tell you what Hermes will actually do at three in the morning.&lt;/P&gt;
&lt;H2&gt;Part 5: The Obstacle, and What It Actually Taught Me&lt;/H2&gt;
&lt;P&gt;Every walkthrough has the part the author quietly leaves out. Here is mine: the wrinkle was not the model, it was capacity. My first attempt deployed into the region closest to me out of habit, and the portal turned it down because there was no capacity left for that model at the tier I asked for. The model was clearly listed in the catalogue; being listed and being deployable in your region, on your subscription, at your quota, are three separate questions.&lt;/P&gt;
&lt;P&gt;Redeploying in a different region fixed it in a couple of minutes, but it meant the endpoint URI changed, which in turn meant the value I had already pasted into Hermes was stale. Re-running hermes fallback add against the new endpoint sorted it out.&lt;/P&gt;
&lt;P&gt;The lesson is cheap enough to hand over for free: check quota and regional capacity for your specific subscription before you design a walkthrough, a demo or a production fallback around one deployment. In the Foundry portal, Management then Quota shows exactly what you have been granted per region and per model family, which is the only list that matters.&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table class="lia-border-style-solid" border="1" style="width: 78.6111%; height: 387px; border-width: 1px;"&gt;&lt;thead&gt;&lt;tr style="height: 39px;"&gt;&lt;td class="lia-align-center" style="height: 39px; border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;Symptom&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="height: 39px; border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;Likely cause&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="height: 39px; border-width: 1px;"&gt;
&lt;P&gt;&lt;STRONG&gt;Fix&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr style="height: 95px;"&gt;&lt;td class="lia-align-center" style="height: 95px; border-width: 1px;"&gt;
&lt;P&gt;Deployment rejected in the portal&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="height: 95px; border-width: 1px;"&gt;
&lt;P&gt;No capacity for that model at the tier you asked for, in that region&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="height: 95px; border-width: 1px;"&gt;
&lt;P&gt;Deploy in another region, or drop to a smaller tier&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 95px;"&gt;&lt;td class="lia-align-center" style="height: 95px; border-width: 1px;"&gt;
&lt;P&gt;Hermes rejects the credential&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="height: 95px; border-width: 1px;"&gt;
&lt;P&gt;Endpoint URI does not match the deployment you created&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="height: 95px; border-width: 1px;"&gt;
&lt;P&gt;Re-copy the target URI from the deployment, not the resource&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 95px;"&gt;&lt;td class="lia-align-center" style="height: 95px; border-width: 1px;"&gt;
&lt;P&gt;Provider authenticates but lists nothing&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="height: 95px; border-width: 1px;"&gt;
&lt;P&gt;Key belongs to a different Foundry resource&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="height: 95px; border-width: 1px;"&gt;
&lt;P&gt;Check you are in the right resource, then re-run hermes fallback add&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr style="height: 67px;"&gt;&lt;td class="lia-align-center" style="height: 67px; border-width: 1px;"&gt;
&lt;P&gt;Fallback never fires&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="height: 67px; border-width: 1px;"&gt;
&lt;P&gt;Chain ordered the wrong way round&lt;/P&gt;
&lt;/td&gt;&lt;td class="lia-align-center" style="height: 67px; border-width: 1px;"&gt;
&lt;P&gt;hermes fallback list, then reorder&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 33.33%" /&gt;&lt;col style="width: 33.33%" /&gt;&lt;col style="width: 33.33%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;EM&gt;Figure 6: The four things that went wrong, or nearly did, and what fixed each one.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;There is a silver lining worth stating plainly. Because the fallback chain was already in place, a deployment that refused to come up did not take the assistant down with it. That is precisely the scenario this whole exercise was meant to cover, and it turned up on day one without me having to simulate it.&lt;/P&gt;
&lt;H2&gt;Command Cheat Sheet&lt;/H2&gt;
&lt;P&gt;Everything used in this walkthrough, collected in one place:&lt;/P&gt;
&lt;LI-CODE lang=""&gt;hermes fallback add: attach a provider to the fallback chain
hermes fallback remove: drop a provider from the chain
hermes fallback list: show the chain in priority order
hermes model: set the primary model
hermes gateway restart: restart the messaging gateway after a change
hermes status: confirm which provider is currently live
/model: switch models from inside a running session&lt;/LI-CODE&gt;
&lt;H2&gt;Conclusion&lt;/H2&gt;
&lt;P&gt;Adding Microsoft Foundry as a fallback behind my existing Bedrock setup took an afternoon, and most of that was spent recovering from a regional capacity limit I should have checked first. The work itself is small: deploy a model, copy the endpoint and key, run hermes fallback add, authenticate, pick your deployments. The payoff is that Hermes no longer depends on one provider staying healthy.&lt;/P&gt;
&lt;P&gt;Three things are worth carrying away from this:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Check quota, not just the catalogue. The Foundry catalogue shows what Microsoft offers. It does not show what your subscription and region can actually deploy today. Confirm that first, before you build anything on top of a specific deployment.&lt;/LI&gt;
&lt;LI&gt;Order your fallback chain deliberately. Hermes works down the list from top to bottom, so the sequence you choose during setup is the failover policy you are going to live with. Put the model you actually trust at the top.&lt;/LI&gt;
&lt;LI&gt;Treat the endpoint as part of the credential. Redeploying in a new region changes the endpoint URI, and a fallback pointed at an endpoint that no longer exists is not a fallback. Re-run the setup whenever the deployment moves.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The switch from Bedrock primary to Foundry primary also proved the chain runs in both directions, which is the real point. Provider redundancy is only useful if you have watched it work. Next on my list is deliberately breaking the primary provider to confirm the failover triggers on its own, without me typing a single command.&lt;/P&gt;
&lt;P&gt;If you run this against a different model, region or provider pairing, I would genuinely like to know how it went, particularly if your quota experience was better than mine. Drop it in the comments.&lt;/P&gt;</description>
      <pubDate>Thu, 27 Aug 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/adding-a-fallback-model-to-hermes-with-microsoft-foundry/ba-p/4541254</guid>
      <dc:creator>suzarilshah</dc:creator>
      <dc:date>2026-08-27T07:00:00Z</dc:date>
    </item>
    <item>
      <title>Agent Governance Toolkit: Giving AI Agents Rules of the Road</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/agent-governance-toolkit-giving-ai-agents-rules-of-the-road/ba-p/4549185</link>
      <description>&lt;P data-path-to-node="3"&gt;Organizations are increasingly deploying autonomous AI agents directly to production environments. These agents ingest customer support tickets, query database states, and execute automated refund transactions. Operating with high throughput and minimal latency, they frequently hold service principal credentials scoped with write access to core infrastructure.&lt;/P&gt;
&lt;P data-path-to-node="4"&gt;This architecture introduces a critical security boundary question: &lt;EM&gt;What prevents an autonomous agent from executing an unauthorized transaction or destructive operation?&lt;/EM&gt;&lt;/P&gt;
&lt;P data-path-to-node="5"&gt;Without strict guardrails, an agent processing unmanaged user inputs remains vulnerable to adversarial indirect prompt injections hidden within customer attachments or support tickets. Furthermore, LLM non-determinism means a tool-calling sequence can hallucinate invalid or destructive parameter arguments during execution.&lt;/P&gt;
&lt;P data-path-to-node="6"&gt;Relying solely on system prompt instructions and base model safety fine-tuning leaves a system without a true security perimeter. System prompts represent soft boundaries; production-grade agent governance requires deterministic enforcement and explicit policy execution.&lt;/P&gt;
&lt;P data-path-to-node="6"&gt;To address these security boundaries, Microsoft open-sourced the &lt;A class="lia-external-url" href="https://microsoft.github.io/agent-governance-toolkit/" target="_blank"&gt;Agent Governance Toolkit (AGT)&lt;/A&gt; in April 2026. This post examines the architectural significance of AGT across both technical implementation and resource allocation perspectives, followed by a hands-on walkthrough demonstrating real-time policy enforcement within a 15-minute deployment sequence.&lt;/P&gt;
&lt;H6 data-path-to-node="2"&gt;&lt;STRONG data-path-to-node="2" data-index-in-node="0"&gt;Why "Trust the Prompt" Was Never a Robust Security Model&lt;/STRONG&gt;&lt;/H6&gt;
&lt;P data-path-to-node="3"&gt;Most engineering teams initially attempt to govern AI agents using standard application security patterns: OAuth scopes and Identity and Access Management (IAM) policies dictate system connectivity. While foundational, perimeter-level authorization is inherently insufficient for autonomous runtimes. Once an agent receives valid authentication tokens for a downstream CRM, vector database, or file system, OAuth provides zero introspection into downstream intent.&lt;/P&gt;
&lt;P data-path-to-node="3"&gt;The decision between executing an idempotent read operation versus issuing a destructive bulk-deletion payload occurs entirely within the model's intermediate reasoning trace. Because that execution loop relies on non-deterministic language models, it remains vulnerable to semantic manipulation, context degradation, and hallucinated logic paths.&lt;/P&gt;
&lt;P data-path-to-node="3"&gt;&amp;nbsp;&lt;/P&gt;
&lt;img&gt;AGT : Traditional Model&lt;/img&gt;&lt;img&gt;AGT: Governance Model&lt;/img&gt;
&lt;P&gt;Directives embedded within system prompts—such as &lt;EM data-path-to-node="6" data-index-in-node="50"&gt;"do not execute destructive actions"&lt;/EM&gt;—function as probabilistic heuristics rather than deterministic controls. The architectural philosophy behind modern governance frameworks, including the Agent Governance Toolkit, establishes that unauthorized operations must be rendered structurally impossible. Enforcement is decoupled from the model's inference loop and applied deterministically via pre-execution interceptors before any underlying tool call executes.&lt;/P&gt;
&lt;P&gt;This shift reflects an evolving threat landscape. The &lt;A class="lia-external-url" href="https://microsoft.github.io/agent-governance-toolkit/compliance/owasp-agentic-top10-architecture/" target="_blank"&gt;OWASP Top 10 for Agentic AI&lt;/A&gt; categorizes vulnerabilities specific to autonomous runtimes, including goal hijacking, unmanaged parameter poisoning, and cascading failures across multi-agent graphs. Simultaneously, regulatory compliance frameworks such as the phased enforcement milestones of the EU AI Act for high-risk autonomous systems mandate verifiable guardrails, auditability, and execution constraints. In this environment, deterministic governance shifts from an architectural best practice to a critical compliance requirement for enterprise deployments. Governance isn't a "&lt;EM&gt;nice to have&lt;/EM&gt;" anymore for teams shipping agents into production; it's becoming table stakes for compliance conversations.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;What is Agent Governance Toolkit ?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Think of AGT as a set of traffic laws and a black-box flight recorder for your AI agents, sitting between "the agent decided to do something" and "the something actually happened.", At an architectural level, the Agent Governance Toolkit (AGT) functions as an inline interception layer and immutable audit engine positioned directly between the LLM's action generation phase and actual tool execution.&lt;/P&gt;
&lt;P data-path-to-node="4"&gt;Rather than modifying underlying model weights or prompt logic, AGT introduces deterministic policy enforcement through established principles derived from Application Security (AppSec) and Site Reliability Engineering (SRE):&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="5,0,0" data-index-in-node="0"&gt;Policy Enforcement Engine:&lt;/STRONG&gt; Declarative rules defined in standard YAML schemas that establish explicit boundaries for tool parameters and runtime actions without requiring imperative custom logic.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="5,1,0" data-index-in-node="0"&gt;Cryptographic Identity (Trust Layer):&lt;/STRONG&gt; Strong workload identity for autonomous agents using open standards such as SPIFFE (Secure Production Identity Framework for Everyone) and Decentralized Identifiers (DIDs), eliminating shared credentials and enabling verifiable agent attribution across multi-agent graphs.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="5,2,0" data-index-in-node="0"&gt;Runtime Isolation &amp;amp; Control:&lt;/STRONG&gt; A sandboxed execution environment featuring privilege ring boundaries to limit system access, paired with programmatic kill-switch mechanisms for real-time containment during anomalous behavior.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="5,3,0" data-index-in-node="0"&gt;Tamper-Evident Evidence Logging:&lt;/STRONG&gt; Cryptographically signed execution trails that log every policy evaluation, parameter validation, and interception decision for compliance and forensic auditing.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="5,4,0" data-index-in-node="0"&gt;Protocol Governance:&lt;/STRONG&gt; Granular control over inter-agent communications and external tool interactions over modern agent communication protocols, including the Model Context Protocol (MCP).&lt;/LI&gt;
&lt;/UL&gt;
&lt;img&gt;AGT: Architecture&lt;/img&gt;
&lt;P class="lia-clear-both"&gt;The Agent Governance Toolkit operates as a modular, sub-millisecond control plane that decouples policy enforcement and zero-trust identity from underlying agent frameworks. By pairing a deterministic OS engine and sandboxed runtime with cryptographically signed delegation chains, AGT intercepts tool invocations, enforces SRE guardrails, and maintains Merkle-anchored audit logs before any action reaches external infrastructure.&lt;/P&gt;
&lt;LI-CODE lang="markdown"&gt;╔══════════════════════════════════════════════════════════════════════════╗
║                    AGENT GOVERNANCE TOOLKIT  v5.0.0                      ║
║               pip install agent-governance-toolkit[full]                 ║
║                                                                          ║
║  Agent Action ──► POLICY CHECK ──► Allow / Deny    (&amp;lt; 0.1 ms)            ║
║                                                                          ║
║  ┌──────────────────────────┐     ┌──────────────────────────────┐       ║
║  │      AGENT OS ENGINE     │◄───►│          AGENTMESH           │       ║
║  │                          │     │                              │       ║
║  │  ● Policy Engine         │     │  ● Zero-Trust Identity       │       ║
║  │  ● Capability Model      │     │  ● Ed25519 / SPIFFE Certs    │       ║
║  │  ● Governance Gate       │     │  ● Trust Scoring (0-1000)    │       ║
║  │  ● GovernanceEventSink   │     │  ● Wire Protocol (A2A/MCP)   │       ║
║  │  ● Decision BOM          │     │  ● Delegation Chains         │       ║
║  └────────────┬─────────────┘     └───────────────┬──────────────┘       ║
║               │                                   │                      ║
║               ▼                                   ▼                      ║
║  ┌──────────────────────────┐     ┌──────────────────────────────┐       ║
║  │      AGENT RUNTIME       │     │          AGENT SRE           │       ║
║  │                          │     │                              │       ║
║  │  ● Execution Rings (0-3) │     │  ● SLO Engine + Error Budgets│       ║
║  │  ● Resource Limits       │     │  ● Replay &amp;amp; Chaos Testing    │       ║
║  │  ● Runtime Sandboxing    │     │  ● Progressive Delivery      │       ║
║  │  ● Termination Control   │     │  ● Circuit Breakers          │       ║
║  └──────────────────────────┘     └──────────────────────────────┘       ║
║                                                                          ║
║  ┌──────────────────────────┐     ┌──────────────────────────────┐       ║
║  │     AGENT HYPERVISOR     │     │       AGENT LIGHTNING        │       ║
║  │                          │     │                              │       ║
║  │  ● Execution Audit       │     │  ● RL Training Governance    │       ║
║  │  ● Delta Engine          │     │  ● Violation Penalties       │       ║
║  │  ● Commitment Anchoring  │     │  ● Reward Shaping            │       ║
║  │  ● Merkle Chain Logs     │     │  ● Training Checkpoints      │       ║
║  └──────────────────────────┘     └──────────────────────────────┘       ║
║                                                                          ║
║  ┌──────────────────────────┐     ┌──────────────────────────────┐       ║
║  │     AGENT MARKETPLACE    │     │    MCP SECURITY GATEWAY      │       ║
║  │                          │     │                              │       ║
║  │  ● Plugin Discovery      │     │  ● Tool-Call Policy Checks   │       ║
║  │  ● Signing &amp;amp; Verification│     │  ● Trust Verification        │       ║
║  │  ● Trust Scoring         │     │  ● Rate Limiting             │       ║
║  └──────────────────────────┘     └──────────────────────────────┘       ║
║                                                                          ║
║  ┌──────────────────────────────────────────────────────────────┐        ║
║  │                      FRAMEWORK ADAPTERS                      │        ║
║  │  LangChain · CrewAI · AutoGen · OpenAI · ADK · smolagents    │        ║
║  └──────────────────────────────────────────────────────────────┘        ║
║                                                                          ║
╚══════════════════════════════════════════════════════════════════════════╝&lt;/LI-CODE&gt;
&lt;P class="lia-clear-both"&gt;AGT provides native SDK support across mainstream development stacks including Python, TypeScript, .NET, Rust, and Go and offers pluggable adapters for major agentic frameworks. This architecture allows organizations to retrofit existing multi-agent pipelines by wrapping critical tool interfaces rather than re-architecting underlying workflows.&lt;/P&gt;
&lt;H6 data-path-to-node="2"&gt;&lt;STRONG&gt;Hands-On Implementation: Enforcing Runtime Policies in Python&lt;/STRONG&gt;&lt;/H6&gt;
&lt;P data-path-to-node="3"&gt;To demonstrate real-time interception, the following exercise configures a deterministic guardrail using the Python SDK. The setup simulates a scenario where an agent attempts an unauthorized, high-value tool call.&lt;/P&gt;
&lt;P data-path-to-node="4"&gt;The core mechanics—defining declarative policy schemas, initializing pre-call interceptors, and handling violation exceptions—remain consistent across all supported SDK runtimes.&lt;/P&gt;
&lt;P data-path-to-node="4"&gt;&lt;STRONG&gt;Prerequisites&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL data-path-to-node="6"&gt;
&lt;LI&gt;Environment: Python 3.10 or higher&lt;/LI&gt;
&lt;LI&gt;Dependencies&lt;STRONG data-path-to-node="6,1,0" data-index-in-node="0"&gt;:&lt;/STRONG&gt; agent-governance-toolkit installed via pip&lt;/LI&gt;
&lt;/UL&gt;
&lt;PRE data-path-to-node="7"&gt;&lt;STRONG&gt;Step 1: Install the Toolkit&lt;/STRONG&gt;&lt;/PRE&gt;
&lt;P data-path-to-node="8"&gt;Initialize a clean virtual environment on a code editor and install the governance package within the virtual environment:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;pip install agent-governance-toolkit[full]&lt;/LI-CODE&gt;
&lt;PRE&gt;&lt;STRONG&gt;Step 2: Write a policy&lt;BR /&gt;&lt;/STRONG&gt;&lt;/PRE&gt;
&lt;P&gt;Governance rules live in plain YAML, not scattered across the codebase. Create a folder called &lt;EM&gt;policies &lt;/EM&gt;and add &lt;EM&gt;policy.yaml,&lt;/EM&gt;&lt;/P&gt;
&lt;LI-CODE lang="yaml"&gt;apiVersion: governance.toolkit/v1
name: file-agent-policy
version: "1.0"
default_action: allow
rules:
  - name: block-destructive
    condition: "action.type in ['drop', 'delete', 'truncate']"
    action: deny
    description: "Destructive operations require human approval"
&lt;/LI-CODE&gt;
&lt;P&gt;In very simple terms, the above YAML defines and allows everything by default, except any action typed as drop, delete, or truncate those get denied outright.&lt;/P&gt;
&lt;PRE&gt;&lt;STRONG&gt;Step3: Lint it&lt;BR /&gt;&lt;BR /&gt;&lt;/STRONG&gt;Before trusting a policy, lets validate it with the Toolkit, In the terminal type the following,&lt;/PRE&gt;
&lt;LI-CODE lang="bash"&gt;agt lint-policy policies/ &lt;/LI-CODE&gt;
&lt;P&gt;In response, it displays "No issues Found" incase all the definitions are valid.&lt;/P&gt;
&lt;img&gt;AGT: agt lint response&lt;/img&gt;
&lt;PRE&gt;&lt;STRONG&gt;Step 4: Wrap your tool in two lines&lt;BR /&gt;&lt;BR /&gt;&lt;/STRONG&gt;&lt;/PRE&gt;
&lt;P&gt;Integrating deterministic governance does not require refactoring an agent's core orchestration logic or LLM prompting loops. Instead, AGT hooks directly into the execution path by wrapping the individual tool functions exposed to the agent. Here's a simple file-handling tool, governed,&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;from agentmesh.governance import govern, GovernanceDenied
 
def file_tool(action, path):
    return f"Executed '{action}' on {path}"
 
safe_tool = govern(file_tool, policy="policies/policy.yaml", agent_id="demo-agent")
 
# Case 1: benign read action
print("Read call  -&amp;gt;", safe_tool(action="read", path="report.txt"))
 
# Case 2: destructive action the policy should block
try:
    safe_tool(action="delete", path="report.txt")
except GovernanceDenied as e:
    print("Delete call -&amp;gt; BLOCKED:", e)
&lt;/LI-CODE&gt;
&lt;PRE&gt;&lt;STRONG&gt;Step 5: Run it and watch the policy do the job&lt;/STRONG&gt;&lt;STRONG&gt;&lt;BR /&gt;&lt;/STRONG&gt;&lt;/PRE&gt;
&lt;P&gt;Save the above file with a name of choice and execute the following in the terminal,&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;python &amp;lt;name of the file&amp;gt;.py&lt;/LI-CODE&gt;&lt;img&gt;AGT:Output&lt;/img&gt;
&lt;P&gt;That's it. The read call sailed through under the default-allow rule; the delete call was intercepted and stopped&lt;EM&gt; &lt;/EM&gt;before it ever reached the function, no model judgment call involved, no reliance on the agent "choosing" to behave. That's what "structurally impossible" looks like in practice.&lt;/P&gt;
&lt;PRE&gt;&lt;STRONG&gt;Step 6: Check your compliance posture&lt;BR /&gt;&lt;/STRONG&gt;&lt;/PRE&gt;
&lt;P&gt;One more command worth knowing, especially if ever needed to show a security or compliance team that all the agents are governed, Type the following command in the terminal,&lt;/P&gt;
&lt;LI-CODE lang="bash"&gt;agt verify&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img&gt;AGT: Verify&lt;/img&gt;
&lt;P&gt;This generates a report&amp;nbsp; and a badge can be dropped straight into any repo&amp;nbsp; mapped against the OWASP Agentic Security Initiative's ten risk categories. For a technical reviewer, that's a checklist. For a decision-maker signing off on an AI rollout, that's evidence.&lt;/P&gt;
&lt;H6 data-path-to-node="2"&gt;&lt;STRONG&gt;Strategic and Risk Governance Implications&lt;/STRONG&gt;&lt;/H6&gt;
&lt;P data-path-to-node="3"&gt;From an executive, risk, and compliance perspective, the Agent Governance Toolkit does not aim to improve model intelligence or rely on probabilistic prompt alignment. Instead, it introduces a deterministic, application-layer checkpoint directly in front of every agentic invocation. As a result, critical failure modes such as an unauthorized database deletion or invalid financial transaction are transformed from uncontained operational incidents into pre-defined policy violations that are deterministically blocked and logged.&lt;/P&gt;
&lt;P data-path-to-node="4"&gt;Organizations implementing AGT can evaluate their agent governance maturity around three core operational artifacts:&lt;/P&gt;
&lt;UL data-path-to-node="5"&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="5,0,0" data-index-in-node="0"&gt;Audit Traceability:&lt;/STRONG&gt; The ability to generate an immutable, cryptographically verifiable audit trail of every governed decision and parameter validation on demand via AGT's evidence layer.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="5,1,0" data-index-in-node="0"&gt;Workload Identity Attribution:&lt;/STRONG&gt; Explicit agent-level identity tracking through AgentMesh standards (SPIFFE/DIDs), eliminating ambiguous shared service credentials in multi-agent environments.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="5,2,0" data-index-in-node="0"&gt;Compliance Framework Mapping:&lt;/STRONG&gt; Deployment validation reports generated via &lt;EM&gt;agt verify&lt;/EM&gt;, providing a direct pass/fail audit mapped against the OWASP Top 10 for Agentic Applications for regulatory and vendor risk reviews.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P data-path-to-node="6"&gt;Establishing these control capabilities requires no modifications to business logic, relying instead on standardized CLI reporting and declarative policy enforcement.&lt;/P&gt;
&lt;P data-path-to-node="6"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P data-path-to-node="6"&gt;&lt;STRONG&gt;Advanced Capability Extensions &amp;amp; Ecosystem Integration&lt;/STRONG&gt;&lt;/P&gt;
&lt;P data-path-to-node="3"&gt;The single-rule policy example demonstrates the baseline execution pattern of the Agent Governance Toolkit, but enterprise deployments extend into broader architectural patterns. The framework provides comprehensive controls for complex production environments:&lt;/P&gt;
&lt;UL data-path-to-node="4"&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="4,0,0" data-index-in-node="0"&gt;Human-in-the-Loop Orchestration:&lt;/STRONG&gt; Declarative&lt;EM&gt; require_approval&lt;/EM&gt; workflows that automatically intercept high-risk operations and route tool payloads to human authorization gates before execution.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="4,1,0" data-index-in-node="0"&gt;Privilege Ring Isolation:&lt;/STRONG&gt; Runtime sandboxing mechanisms that restrict system access levels based on assigned agent capabilities.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="4,2,0" data-index-in-node="0"&gt;Multi-Agent Identity Federation:&lt;/STRONG&gt; Cryptographic agent identity verification designed to secure delegation chains and inter-agent communication in multi-agent architectures.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="4,3,0" data-index-in-node="0"&gt;Native Framework Adapters:&lt;/STRONG&gt; Pluggable middleware integration for existing orchestration stacks, enabling direct governance injection into frameworks like LangGraph, AutoGen, and Semantic Kernel without requiring pipeline refactoring.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P data-path-to-node="5"&gt;For full end-to-end integration patterns including wrapping multi-node LangGraph workflows with deterministic policy gates refer to the official &lt;A class="lia-external-url" href="https://microsoft.github.io/agent-governance-toolkit/quickstart/" target="_blank"&gt;Microsoft Agent Governance Toolkit&lt;/A&gt; documentation and architecture blueprints.&lt;/P&gt;
&lt;H6 data-path-to-node="0"&gt;&lt;STRONG&gt;Production-Grade Governance as the Baseline for Autonomous AI&lt;/STRONG&gt;&lt;/H6&gt;
&lt;P data-path-to-node="1"&gt;As AI agents transition from experimental sandboxes to enterprise production environments, reliance on soft safety guidelines and system prompt instructions is no longer a viable security posture. Autonomous systems holding write access to critical data sources demand the same deterministic controls, zero-trust identity boundaries, and immutable audit trails long expected of human operators and microservice architectures.&lt;/P&gt;
&lt;P data-path-to-node="2"&gt;&lt;A class="lia-external-url" href="https://github.com/microsoft/agent-governance-toolkit" target="_blank"&gt;Agent Governance Toolkit&lt;/A&gt; establishes a clear paradigm: governance is not an afterthought appended to post-hoc incident response, but an inline, sub-millisecond control plane built directly into the runtime execution path. By decoupling policy enforcement from model reasoning, organizations can safely accelerate agentic adoption ensuring every autonomous action remains strictly bounded, fully traceable, and compliance-ready.&lt;/P&gt;
&lt;P data-path-to-node="2"&gt;References:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Docs &amp;amp; quickstart: &lt;A href="https://microsoft.github.io/agent-governance-toolkit/" target="_blank"&gt;microsoft.github.io/agent-governance-toolkit&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;Source &amp;amp; examples: &lt;A href="https://github.com/microsoft/agent-governance-toolkit" target="_blank"&gt;github.com/microsoft/agent-governance-toolkit&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;Announcement post: &lt;A href="https://opensource.microsoft.com/blog/2026/04/02/introducing-the-agent-governance-toolkit-open-source-runtime-security-for-ai-agents/" target="_blank"&gt;Introducing the Agent Governance Toolkit — Microsoft Open Source Blog&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;Architecture deep dive: &lt;A href="https://techcommunity.microsoft.com/blog/linuxandopensourceblog/agent-governance-toolkit-architecture-deep-dive-policy-engines-trust-and-sre-for/4510105" target="_blank"&gt;Agent Governance Toolkit: Architecture Deep Dive — Microsoft Tech Community&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P data-path-to-node="5"&gt;&amp;nbsp;&lt;/P&gt;
&lt;H6&gt;&amp;nbsp;&lt;/H6&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;STRONG&gt;&amp;nbsp;&lt;/STRONG&gt;&lt;/PRE&gt;
&lt;PRE&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;STRONG&gt;&amp;nbsp;&lt;/STRONG&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 25 Aug 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/agent-governance-toolkit-giving-ai-agents-rules-of-the-road/ba-p/4549185</guid>
      <dc:creator>shreyanfern</dc:creator>
      <dc:date>2026-08-25T07:00:00Z</dc:date>
    </item>
    <item>
      <title>Understanding Harnesses: The Concept That Changes How You Build Agents in Copilot Studio</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/understanding-harnesses-the-concept-that-changes-how-you-build/ba-p/4545149</link>
      <description>&lt;P&gt;That changed on August 3, 2026, when Microsoft made the GitHub Copilot harness generally available. Copilot Studio now ships three harnesses, and choosing between them is the first real architecture decision you make when starting a new agent.&lt;/P&gt;
&lt;P&gt;This is a good problem to have. It means the platform stopped assuming every agent is the same kind of thing. But "harness" is a genuinely new word for most makers, so let's start there.&lt;/P&gt;
&lt;H2&gt;What a harness is&lt;/H2&gt;
&lt;P&gt;Microsoft defines a harness as the runtime layer between the language model and your agent's configuration. It decides what context reaches the model, when tools get invoked, how responses are interpreted, and how the agent moves through a task toward completion.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;FIGURE&gt;&lt;IMG src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/images/copilot-studio-harness-diagram.svg" alt="Diagram showing the harness layer between the agent configuration above and the language model below" loading="lazy" /&gt;
&lt;FIGCAPTION&gt;&lt;BR /&gt;The harness sits between what you configure and the model that reasons over it.&lt;/FIGCAPTION&gt;
&lt;/FIGURE&gt;
&lt;P&gt;The analogy &lt;A class="lia-external-url" href="https://youtu.be/TikbZYsY7nU?t=299" target="_blank" rel="noopener"&gt;Lisa Crosbie&lt;/A&gt; uses is the best one I have heard: the model is a newly hired employee, arriving with knowledge, language, and reasoning ability. The harness is everything you give them afterward: the laptop, the system access, the team around them, the policies, the tools. You hired the brain. The harness is what lets the brain do your work.&lt;/P&gt;
&lt;P&gt;Before this release, that layer was invisible, because it was singular. Now it is a deliberate choice, which is a meaningful step toward Copilot Studio being an agent engineering environment rather than a chatbot builder.&lt;/P&gt;
&lt;H3&gt;The three harnesses&lt;/H3&gt;
&lt;P&gt;&lt;IMG style="width: 100%; max-width: 900px; height: auto;" src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/images/table-harnesses.svg" alt="Comparison of the three Copilot Studio harnesses: Copilot Chat, Standard, and GitHub Copilot" loading="lazy" /&gt;&lt;/P&gt;
&lt;H2&gt;Model choice is the headline&lt;/H2&gt;
&lt;P&gt;Here is the part I would lead with if I only had one sentence: the GitHub Copilot harness is model-agnostic, and the model you choose is the agent's main brain.&lt;/P&gt;
&lt;P&gt;This is different from what came before. Previously, you could bring a Foundry model into a specific prompt, useful but scoped. Now frontier reasoning models like Opus 5, GPT-5.6, and Fable 5 can run the whole agent. Microsoft's own framing, from &lt;A href="https://www.youtube.com/watch?v=v7IA56HJU2E&amp;amp;t=3s" target="_blank" rel="noopener"&gt;Ryan Cunningham's&lt;/A&gt; launch walkthrough, is that the harness hosts an advanced reasoning model in its own computing environment with a set of tools and skills, and lets it loop over hard problems.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;FIGURE&gt;&lt;IMG src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/gifs/model%20choice.gif" alt="Model picker in Copilot Studio showing available models" loading="lazy" /&gt;
&lt;FIGCAPTION&gt;&lt;BR /&gt;Available models depend on what your organization has enabled.&lt;/FIGCAPTION&gt;
&lt;/FIGURE&gt;
&lt;P&gt;Two practical notes. Your organization controls which models are enabled, so what you see in the picker depends on admin configuration. And model availability varies by region; some regions cannot use certain providers. Check what is actually available in your tenant before designing around a specific model.&lt;/P&gt;
&lt;P&gt;If you have been building agents for a while, this is the change that most alters what is possible. The Standard harness could not reach these capabilities. That gap is why the new harness exists.&lt;/P&gt;
&lt;H2&gt;Standard harness: explicit construction&lt;/H2&gt;
&lt;P&gt;The Standard harness is the model most of us learned on. You author topics. You define triggers. You build branching paths and route into flows. Behavior is constructed explicitly, step by step.&lt;/P&gt;
&lt;P&gt;It remains fully supported, and it is still an excellent fit for real work. A service desk agent answering a known set of questions, a scheduling assistant routing into a defined flow, an onboarding agent walking a new hire through a fixed sequence, you want these predictable, and explicit construction gives you that. Some conversational patterns genuinely need a scripted path.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;FIGURE&gt;&lt;IMG src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/images/copilot-studio-topic-canvas.svg" alt="Topic canvas with visible branching in the classic Copilot Studio interface" loading="lazy" /&gt;
&lt;FIGCAPTION&gt;&lt;BR /&gt;Explicit construction makes control flow visible; you can see exactly why the agent did what it did.&lt;/FIGCAPTION&gt;
&lt;/FIGURE&gt;
&lt;P&gt;If you are learning agent development, this harness teaches you something valuable: it makes control flow visible. You can see exactly why the agent did what it did, because you drew the path.&lt;/P&gt;
&lt;P&gt;Two things to know. Existing Standard harness agents keep running exactly as they are; nothing breaks. But to edit them, you work in the classic interface. The two experiences are separate surfaces.&lt;/P&gt;
&lt;H2&gt;GitHub Copilot harness: goal-directed reasoning&lt;/H2&gt;
&lt;P&gt;The new harness takes a different approach. Rather than authoring conversation paths, you describe the agent in natural language, and the orchestration runtime interprets those instructions at runtime.&lt;/P&gt;
&lt;P&gt;The shape of the reasoning changed too. The older orchestrator worked in a fairly linear pattern: take the input, make a plan, collect what it needed, execute. The new one runs a continuous loop: evaluate the goal, plan, call tools, examine results, adjust, continue until the objective is met. That loop is what lets it handle ambiguity, recover from a step that did not work, and stay on track through multi-stage problems.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;The older orchestrator made a plan and executed it. The new one keeps thinking.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Microsoft's published comparison figures show meaningful gains, multi-tool use improving from 87 percent to 98 percent, with reported improvements in file analysis, code analysis, and knowledge work. Worth verifying in the current documentation, since these are the kind of numbers that get updated.&lt;/P&gt;
&lt;P&gt;What comes with it:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Skills&lt;/STRONG&gt;: reusable Markdown instruction sets, attachable across agents, exportable as files. They can bundle artifacts too, including documents and Python.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Memory&lt;/STRONG&gt;: persistent context across interactions, including user preferences.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Connected agents&lt;/STRONG&gt;: a front-door agent routing to specialists, each owned separately.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Sandboxed execution&lt;/STRONG&gt; with large file processing and native Word, Excel, PowerPoint, and PDF generation.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Build, Preview, Evaluate, Monitor&lt;/STRONG&gt;: four tabs, consolidated from nine.&lt;/LI&gt;
&lt;/UL&gt;
&lt;FIGURE&gt;&lt;IMG src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/screenshots/classic-tabs.png" alt="Classic Copilot Studio interface showing the full set of configuration tabs" loading="lazy" /&gt;
&lt;FIGCAPTION&gt;&lt;BR /&gt;The classic interface had nine tabs: Overview, Knowledge, Tools, Agents, Topics, Activity, Evaluation, Monitor, and Channels.&lt;/FIGCAPTION&gt;
&lt;/FIGURE&gt;
&lt;FIGURE&gt;&lt;IMG src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/screenshots/new-monitor-tab.png" alt="New Copilot Studio interface showing the consolidated four-tab authoring surface" loading="lazy" /&gt;
&lt;FIGCAPTION&gt;&lt;BR /&gt;The new GitHub Copilot harness consolidates everything into four tabs: Build, Preview, Evaluate, Monitor.&lt;/FIGCAPTION&gt;
&lt;/FIGURE&gt;
&lt;P&gt;That Evaluate tab deserves its own mention. &lt;A class="lia-external-url" href="https://youtu.be/v7IA56HJU2E?t=145" target="_blank" rel="noopener"&gt;Cunningham's&lt;/A&gt; framing is that evaluation matters more than ever, giving agents a hard set of problems and scoring how they perform as you refine instructions and skills. Evaluation moving into the primary authoring surface rather than a separate tool is a real signal about where agent development is heading. If you are a student building agents now, getting comfortable with evaluation early will serve you well.&lt;/P&gt;
&lt;H2&gt;Topics are gone. Skills replaced them.&lt;/H2&gt;
&lt;P&gt;In the new harness, topics do not exist. This surprised a lot of makers, so it is worth understanding why rather than just noting it.&lt;/P&gt;
&lt;P&gt;Topics were a way to script a conversation, useful when the path must go a certain way, but not how frontier models think. Skills are the replacement, and they work differently: a Markdown file containing a set of instructions the agent can pull in on demand, at the moment it is relevant, rather than one enormous instruction block covering every case.&lt;/P&gt;
&lt;P&gt;This solves a problem anyone who has written long agent instructions will recognize. Instead of bloating a single instruction set, you decompose behavior into procedure manuals the agent reaches for as needed.&lt;/P&gt;
&lt;FIGURE&gt;&lt;IMG src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/images/copilot-studio-skill-file.svg" alt="A skill file open in an editor, showing the raw Markdown" loading="lazy" /&gt;&lt;/FIGURE&gt;
&lt;P&gt;A skill is a procedure manual the agent picks up when it needs it&lt;/P&gt;
&lt;P&gt;The reusability is the interesting part. Author a skill once, attach it to several agents, export it, share it. And the format is spreading; skills are appearing in Cowork, PowerPoint, Word, and across GitHub Copilot. That makes a skill file a portable, human-readable, version-controllable unit of agent behavior.&lt;/P&gt;
&lt;P&gt;For anyone teaching this material, that is a genuinely good pedagogical object. A skill file is small enough to read in a class session and real enough to ship. If you experiment with one thing this month, make it authoring a skill by hand and attaching it to more than one agent.&lt;/P&gt;
&lt;H2&gt;Agents and workflows are now two equal pillars&lt;/H2&gt;
&lt;P&gt;This is the structural change people are underrating.&lt;/P&gt;
&lt;P&gt;&lt;IMG style="width: 100%; max-width: 900px; height: auto;" src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/images/table-agent-vs-workflow.svg" alt="Comparison of agents and workflows across behavior, path, best fit, and credit cost" loading="lazy" /&gt;&lt;/P&gt;
&lt;P&gt;Neither is the "advanced" option. They compose. An agent reasoning through a problem can call a workflow when it needs a reliable sequence. A workflow running its steps can invoke an agent at the step that requires judgment. &lt;A class="lia-external-url" href="https://youtu.be/v7IA56HJU2E?t=179" target="_blank" rel="noopener"&gt;Cunningham&lt;/A&gt; makes a point worth repeating: structuring work this way is also more credit-efficient, because you spend model reasoning only where it adds value.&lt;/P&gt;
&lt;P&gt;The workflow designer was rebuilt for this: horizontal canvas, agents embeddable as nodes, and node-by-node testing so you validate each step as you build rather than running the whole thing and hoping.&lt;/P&gt;
&lt;FIGURE&gt;&lt;IMG src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/screenshots/workflow.png" alt="The horizontal workflow designer with an agent node in the sequence" loading="lazy" /&gt;
&lt;FIGCAPTION&gt;&lt;BR /&gt;Agents drop into workflows as nodes. Node-by-node testing means you validate as you build.&lt;/FIGCAPTION&gt;
&lt;/FIGURE&gt;
&lt;P&gt;For municipal work, this maps cleanly. A permit intake might reason over an ambiguous description to decide which department owns it, then hand it to a deterministic workflow for notification, record creation, and routing. Reasoning where reasoning is needed; predictable steps everywhere else.&lt;/P&gt;
&lt;H2&gt;How to choose&lt;/H2&gt;
&lt;P&gt;The question I ask at the start of every build:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Is the hard part of this agent the retrieval, or the reasoning?&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;IMG style="width: 100%; max-width: 900px; height: auto;" src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/images/table-how-to-choose.svg" alt="Decision table: retrieval points to Standard harness, reasoning points to GitHub Copilot harness, pure repetition points to a workflow" loading="lazy" /&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If the hard part is retrieval, ground it well and keep behavior predictable and the maintenance surface small. You are not missing out, you are matching the tool to the problem.&lt;/P&gt;
&lt;P&gt;I build Power Platform solutions for local government, so my examples come from there: a grant eligibility screen reading a federal notice against a city's programs, a code compliance review spanning several ordinances, an intake deciding which of six departments owns a request. Every one is reasoning work. Under the old model I was fighting the platform to express them.&lt;/P&gt;
&lt;P&gt;Your domain has its own version of that list. The sorting question is the same. The documentation includes a comparison table with reasons for and against each harness, worth reading before your next build.&lt;/P&gt;
&lt;H2&gt;Two things to know before you start&lt;/H2&gt;
&lt;P&gt;&lt;STRONG&gt;Harness choice is set at creation.&lt;/STRONG&gt; Agents cannot be converted between harnesses in either direction. Different architectures, different runtimes. Existing agents keep running. Know this up front so you choose consciously; ask the retrieval-or-reasoning question during design, not after.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Billing works differently on the new harness.&lt;/STRONG&gt; Agents powered by the GitHub Copilot harness use Copilot Credits, and per Microsoft's documentation, that applies to using, building, testing, and evaluating. Authoring an agent through natural language consumes credits. The Copilot Chat and Standard harnesses continue on the existing rate card, and Standard harness agents remain included for licensed users when deployed to Teams or Microsoft 365 Copilot.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="width: 100%; max-width: 900px; height: auto;" src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/images/table-credits.svg" alt="Approximate Copilot Credit costs: lighter conversation 100 to 300 credits, heavier multi-step work 500 or more" loading="lazy" /&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;A credit is roughly one US cent. Those figures come from Microsoft's published examples and are worth confirming against the current credits guide, but the useful point is that the cost is knowable rather than mysterious.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;FIGURE&gt;&lt;IMG src="https://raw.githubusercontent.com/JonEricEubanks/public-assets/main/images/copilot-studio-credits.svg" alt="Credit consumption view in the Power Platform admin center" loading="lazy" /&gt;
&lt;FIGCAPTION&gt;&lt;BR /&gt;Administrators can allocate credits per environment and review consumption.&lt;/FIGCAPTION&gt;
&lt;/FIGURE&gt;
&lt;P&gt;For students and educators: check what your tenant or lab environment provides before building. For anyone deploying at scale, the pre-purchase plan offers a discount and its credits are consumed over twelve months rather than resetting monthly, which gives room to experiment.&lt;/P&gt;
&lt;P&gt;The honest framing is &lt;A class="lia-external-url" href="https://youtu.be/TikbZYsY7nU?t=956" target="_blank" rel="noopener"&gt;Crosbie's&lt;/A&gt;: the costs are not trivial, but the capability is substantial, and the skill worth building now is evaluating cost against value rather than avoiding the question.&lt;/P&gt;
&lt;H2&gt;Getting started&lt;/H2&gt;
&lt;P&gt;Create a new agent from the Copilot Studio homepage, and you will choose a harness. Build something small and real on the GitHub Copilot harness, a task from your own work or coursework, scoped to three sentences. Watch the Preview and Evaluate tabs as you iterate. Note what the credit consumption actually looks like on your own tenant. You will learn more in an afternoon than from any writeup, including this one.&lt;/P&gt;
&lt;P&gt;Then revisit something you have already built and ask the retrieval-or-reasoning question. Some of your existing agents are in exactly the right place. Knowing which ones is its own kind of progress.&lt;/P&gt;
&lt;H2&gt;What is still rolling out&lt;/H2&gt;
&lt;P&gt;The GitHub Copilot harness reached GA on August 3, 2026, so production experience across the community is still accumulating, mine included. The knowledge source options in the new experience are currently a somewhat reduced set compared to the classic interface and will expand. Parts of the wider rebuild remain in preview.&lt;/P&gt;
&lt;P&gt;Benchmark figures, model availability, and credit costs are best confirmed directly in Microsoft Learn rather than from secondary coverage, including mine. If you build for regulated or government environments, confirm feature availability in your specific cloud before designing around it.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Learn more:&lt;/STRONG&gt; &lt;A href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/agents-experience/overview" target="_blank" rel="noopener"&gt;Agents overview, GitHub Copilot harness&lt;/A&gt; · &lt;A href="https://learn.microsoft.com/en-us/microsoft-copilot-studio/whats-new" target="_blank" rel="noopener"&gt;What's new in Copilot Studio&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Mon, 24 Aug 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/understanding-harnesses-the-concept-that-changes-how-you-build/ba-p/4545149</guid>
      <dc:creator>JonEricEubanks</dc:creator>
      <dc:date>2026-08-24T07:00:00Z</dc:date>
    </item>
    <item>
      <title>Build AI agents without leaving VS Code, join our 3-part Reactor Series</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/build-ai-agents-without-leaving-vs-code-join-our-3-part-reactor/ba-p/4548177</link>
      <description>&lt;P&gt;Starting August 25, we're running a free three-part live series on Microsoft Reactor that takes you from "what is a hosted agent?" to a deployed, orchestrated multi-agent application, all built in VS Code with the Microsoft Foundry Toolkit.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;👉 &lt;A href="https://developer.microsoft.com/en-us/reactor/series/S-1707/" target="_blank" rel="noopener"&gt;Register for the series&lt;/A&gt;&lt;/P&gt;
&lt;H2&gt;Building agents, without leaving your IDE.&lt;/H2&gt;
&lt;P&gt;Building an AI agent usually means context-switching between a portal, a terminal, a notebook, and three browser tabs of documentation. You write some instructions, deploy, wait, test in a playground, discover the agent hallucinated a policy that doesn't exist, and start over. The feedback loop is measured in minutes, not seconds.&lt;/P&gt;
&lt;P&gt;The Microsoft Foundry Toolkit for VS Code collapses that loop. You generate an agent from extension using the Command Palette, configure the model and instructions, debug it locally against Agent Inspector, and deploy to Microsoft Foundry Agent Service.&lt;/P&gt;
&lt;H2&gt;What you will Build&lt;/H2&gt;
&lt;img /&gt;
&lt;H3&gt;Explain like I am an Executive agent&lt;/H3&gt;
&lt;P&gt;We've all written the perfect post-mortem, root cause, timeline, remediation, only to get back: "So… is the website down or not?"&lt;/P&gt;
&lt;P&gt;&lt;A href="https://developer.microsoft.com/en-us/reactor/events/27523/" target="_blank" rel="noopener"&gt;Session 2&lt;/A&gt; builds a single-purpose agent that takes this:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;"The API latency increased due to thread pool exhaustion caused by synchronous calls introduced in v3.2."&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;…and returns this:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Executive Summary:&lt;/P&gt;
&lt;P&gt;- What happened: After the latest release, the system slowed down.&lt;/P&gt;
&lt;P&gt;- Business impact: Some users experienced delays while using the service.&lt;/P&gt;
&lt;P&gt;- Next step: The change has been rolled back and a fix is being prepared before redeployment.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;img /&gt;
&lt;H3&gt;The Resume → Job Fit Evaluator&lt;/H3&gt;
&lt;P&gt;&lt;A href="https://developer.microsoft.com/en-us/reactor/events/27524/" target="_blank" rel="noopener"&gt;Session 3&lt;/A&gt; steps up to a multi-agent workflow: four agents that collaborate to parse a résumé and a job description, extract the real requirements, score alignment, identify gaps, and generate a personalized learning roadmap backed by Microsoft Learn resources.&lt;/P&gt;
&lt;P&gt;This is where you see orchestration patterns, agent-to-agent handoffs, and how to keep a multi-agent system debuggable .&lt;/P&gt;
&lt;H2&gt;The sessions&lt;/H2&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Title&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Description&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Date and Time&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Speaker&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;A href="https://developer.microsoft.com/en-us/reactor/events/27522/" target="_blank" rel="noopener"&gt;1️⃣ What Is Microsoft Foundry Toolkit for VS Code? What's New and How to Get Started&lt;/A&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Foundation session touring the toolkit's workflow: agent creation, model configuration, local debugging with Agent Inspector, and deployment to Microsoft Foundry Agent Service.&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Tuesday, August 25&lt;/P&gt;
&lt;P&gt;12:00 PM UTC&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Junjie Li&lt;/P&gt;
&lt;P&gt;Senior Product Manager, DevDiv, Microsoft&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;A href="https://developer.microsoft.com/en-us/reactor/events/27523/" target="_blank" rel="noopener"&gt;2️⃣ Build Your First Microsoft Foundry Agent: Executive Briefings from Technical Updates&lt;/A&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Hands-on build session creating a Python hosted agent, authoring instructions, testing safety boundaries in Agent Inspector, and deploying to the cloud.&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Tuesday, September 1 2:00 PM UTC&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Bethany Jepchumba&lt;/P&gt;
&lt;P&gt;Cloud Advocate, Microsoft&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;A href="https://developer.microsoft.com/en-us/reactor/events/27524/" target="_blank" rel="noopener"&gt;3️⃣ Build a Multi-Agent Career Copilot: Resume-to-Job Fit Analysis&lt;/A&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Orchestration session building a 4-agent collaborative team that parses résumés and job descriptions, scores alignment, finds gaps, and generates learning roadmaps.&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Thursday, September 3 3:00 PM UTC&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Shivam Goyal&lt;/P&gt;
&lt;P&gt;Microsoft MVP (AI)&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 25.00%" /&gt;&lt;col style="width: 25.00%" /&gt;&lt;col style="width: 25.00%" /&gt;&lt;col style="width: 25.00%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H2&gt;Follow along on GitHub....&lt;/H2&gt;
&lt;P&gt;Every session maps to our workshop in the companion repo with 50+ languages supported, so you can build alongside us or catch up afterward:&lt;/P&gt;
&lt;P&gt;👉 &lt;A class="lia-external-url" href="https://github.com/microsoft-foundry/Foundry_Toolkit_for_VSCode_Lab/" target="_blank" rel="noopener"&gt;Check out the repo&lt;/A&gt;&lt;/P&gt;
&lt;H2&gt;Save your seat and see you there&lt;/H2&gt;
&lt;P&gt;Sessions run on August 25, September 1, and September 3. Register once for the series and you're in for all three, and you'll get the recordings even if you can't make it live.&lt;/P&gt;
&lt;H3&gt;👉 &lt;A href="https://developer.microsoft.com/en-us/reactor/series/S-1707/" target="_blank" rel="noopener"&gt;Register for the full series&lt;/A&gt;&lt;/H3&gt;
&lt;P&gt;Bring your questions and see you there. 🚀&lt;/P&gt;</description>
      <pubDate>Sun, 23 Aug 2026 07:46:38 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/build-ai-agents-without-leaving-vs-code-join-our-3-part-reactor/ba-p/4548177</guid>
      <dc:creator>bethanyjep</dc:creator>
      <dc:date>2026-08-23T07:46:38Z</dc:date>
    </item>
    <item>
      <title>CivicGrant IQ: The Five-Agent AI That Reads Federal Grants So Cities Don't Have To</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/civicgrant-iq-the-five-agent-ai-that-reads-federal-grants-so/ba-p/4542419</link>
      <description>&lt;P&gt;&lt;IMG class="blog" src="https://cdn.jsdelivr.net/gh/JonEricEubanks/CivicGrant-IQ@main/docs/hero.svg" alt="CivicGrant IQ — five-agent fleet, six-step reasoning, GraphRAG-cited, never down" /&gt;&lt;/P&gt;
&lt;P&gt;Guest post by &lt;A class="lia-external-url" href="https://www.linkedin.com/in/joneric-eubanks-pmp-developer" target="_blank"&gt;JonEric Eubanks&lt;/A&gt; winner of Best use of Microsoft IQ series for Agents League 2026 Hackathon.&lt;/P&gt;
&lt;H3&gt;The meeting that started this&lt;/H3&gt;
&lt;P&gt;Every city has the same meeting. Finance finds a federal grant that looks relevant. A department director, a project manager, and a grants coordinator gather around an 80-page Notice of Funding Opportunity (NOFO) and spend two hours trying to answer three questions: &lt;EM&gt;Do we qualify? Which of our projects fits? Is it worth the effort?&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Nobody has a good answer by the end. The NOFO is written for federal program officers, not city staff. So most of the time the city does nothing, the deadline passes, and real, appropriated money goes unclaimed.&lt;/P&gt;
&lt;P&gt;I've built production tools for local government for years, including an app that won Microsoft's global Best in Automation award. The single biggest gap I keep seeing is the grant lifecycle: finding the right opportunity, proving you qualify, drafting the application, and tracking compliance is slow, fragmented work. A city of 40,000 might have one part-time person responsible for all of it, and asking them to spend 80–200 hours on an uncertain application means deprioritizing everything else.&lt;/P&gt;
&lt;P&gt;So for the hackathon, I built the analyst that actually has the answers.&lt;/P&gt;
&lt;H3&gt;What it does&lt;/H3&gt;
&lt;P&gt;Paste a federal NOFO, or a URL, or just a description, and CivicGrant IQ streams a six-step reasoning chain to the screen in under 60 seconds:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Parse&lt;/STRONG&gt; the grant's requirements, award ceiling, deadline, and eligibility rules&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Match&lt;/STRONG&gt; the city's Capital Improvement Plan projects and past applications against them&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Verify&lt;/STRONG&gt; cost-share capacity against the city's live financial profile&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Score&lt;/STRONG&gt; every gap by severity, with a specific strategy to close each&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Draft&lt;/STRONG&gt; a 150–200 word narrative anchored in the city's closest winning application&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Plan&lt;/STRONG&gt; a four-week action calendar with department owners&lt;/LI&gt;
&lt;/OL&gt;
&lt;!-- ═══ IMAGE 2 · demo-flow ═══ --&gt;
&lt;P&gt;&lt;IMG class="blog" src="https://cdn.jsdelivr.net/gh/JonEricEubanks/CivicGrant-IQ@main/docs/demo-flow.svg" alt="Six-step reasoning chain, from pasted NOFO to submission-ready dashboard" /&gt;&lt;/P&gt;
&lt;P&gt;While that runs, two more agents work in parallel: &lt;STRONG&gt;Competitive Intel&lt;/STRONG&gt; maps the likely field, and a &lt;STRONG&gt;Red Team GS-14 Reviewer&lt;/STRONG&gt; scores the draft like a skeptical senior federal reviewer. When it's done, a live dashboard renders inline, match gauge, gap cards, timeline, and &lt;STRONG&gt;every figure traces to a cited source document.&lt;/STRONG&gt;&lt;/P&gt;
&lt;!-- ═══ IMAGE 3 · multi-agent ═══ --&gt;
&lt;P&gt;&lt;IMG class="blog" src="https://cdn.jsdelivr.net/gh/JonEricEubanks/CivicGrant-IQ@main/docs/multi-agent.svg" alt="Five specialist agents: Main Analyst, Competitive Intel, Red Team GS-14 Reviewer, Portfolio Scanner, Narrative Refinement" /&gt;&lt;/P&gt;
&lt;H3&gt;The architecture&lt;/H3&gt;
&lt;P&gt;Four Microsoft IQ layers, plus a GraphRAG reasoning layer, all load-bearing:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Foundry IQ&lt;/STRONG&gt; (Azure AI Search) grounds every city-specific claim in real documents. The model can't invent a strength it can't source.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Work IQ&lt;/STRONG&gt; pulls four live Microsoft 365 signals at query time, calendar deadlines, flagged grant emails, SharePoint project docs, Teams context, so the agent knows what the city is working on &lt;EM&gt;now&lt;/EM&gt;.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Fabric IQ&lt;/STRONG&gt; connects to a live Microsoft Fabric lakehouse for real disbursement rates and compliance status. "100% compliance" is a live SQL query, not a cached claim.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Web IQ&lt;/STRONG&gt; pulls the &lt;STRONG&gt;live Grants.gov feed&lt;/STRONG&gt; for real-time open programs and award ceilings, ranked by fit and refreshed daily, so the opportunity list is never stale.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;GraphRAG&lt;/STRONG&gt; traverses a typed entity graph so every reasoning hop carries its own citation, not just the final answer.&lt;/LI&gt;
&lt;/UL&gt;
&lt;!-- ═══ IMAGE 4 · iq-layers ═══ --&gt;
&lt;P&gt;&lt;IMG class="blog" src="https://cdn.jsdelivr.net/gh/JonEricEubanks/CivicGrant-IQ@main/docs/iq-layers.svg" alt="Four IQ layers — Foundry IQ, Work IQ, Fabric IQ, Web IQ — all load-bearing" /&gt;&lt;/P&gt;
&lt;P&gt;Under the hood: Azure OpenAI (gpt-4o-mini) via the Assistants API, an Express/TypeScript backend streaming SSE events step-by-step, and a React 18 frontend that renders the reasoning chain and dashboard live as they stream.&lt;/P&gt;
&lt;H3&gt;Two patterns worth stealing&lt;/H3&gt;
&lt;P&gt;&lt;STRONG&gt;The widget protocol.&lt;/STRONG&gt; A chat streams text, but a grant tool needs a dashboard. Instead of building two UIs, the agent embeds a JSON block in its response. The server strips it from the display text and fires it as a separate event:&lt;/P&gt;
&lt;LI-CODE lang="javascript"&gt;// Strip the ```widget block from the text the user sees…
const WIDGET = /```widget\s*([\s\S]*?)```/;
const clean = text.replace(/```widget[\s\S]*?```/g, "").trim();

// …then emit the parsed JSON as its own SSE event.
const match = text.match(WIDGET);
if (match) {
  try { send("widget", JSON.parse(match[1])); }
  catch { /* malformed → the text answer is still complete */ }
}&lt;/LI-CODE&gt;
&lt;P&gt;The frontend renders a live dashboard inline. If the JSON is malformed, the component just doesn't mount, the text answer is still complete.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The three-tier fallback.&lt;/STRONG&gt; Every API fails at the worst moment, usually mid-demo. Tier 1 is the Assistants API with Foundry IQ. If it fails, Tier 2 rebuilds the same prompt as a Chat Completions call. If both are down, Tier 3 serves deterministic results with no API calls. Result: zero failures across twelve demo runs, two of them on conference Wi-Fi.&lt;/P&gt;
&lt;!-- ═══ IMAGE 5 · fallback-pipeline ═══ --&gt;
&lt;P&gt;&lt;IMG class="blog" src="https://cdn.jsdelivr.net/gh/JonEricEubanks/CivicGrant-IQ@main/docs/fallback-pipeline.svg" alt="Three-tier never-down fallback: Assistants API → Chat Completions → deterministic mock engine" /&gt;&lt;/P&gt;
&lt;H3&gt;Results&lt;/H3&gt;
&lt;!-- ═══ IMAGE 6 · stats-banner ═══ --&gt;
&lt;P&gt;&lt;IMG class="blog" src="https://cdn.jsdelivr.net/gh/JonEricEubanks/CivicGrant-IQ@main/docs/stats-banner.svg" alt="$1.25B matched · 91% BRIC match · three drafts in 90s each · Best IQ Agent" /&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;$1.25B&lt;/STRONG&gt; in verified open federal funding matched across 10 programs for one mid-sized city&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;91% match score&lt;/STRONG&gt; for FEMA BRIC, grounded in the city's real CRS rating and 2025 application&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Three submission-ready drafts&lt;/STRONG&gt; generated from precedent in under 90 seconds each&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Named Best IQ Agent&lt;/STRONG&gt; from a field of nearly 5,000 contestants&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The metric I care about most: a grants coordinator can now make a real go/no-go decision in under an hour. It used to take a week.&lt;/P&gt;
&lt;H3&gt;What I learned&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Make the reasoning visible.&lt;/STRONG&gt; A streamed, sourced six-step chain is evidence. An opaque score is just a claim.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Real data beats a curated demo.&lt;/STRONG&gt; Judges could open Grants.gov and verify the numbers on the spot. That moment is worth more than any diagram.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Grounding is a discipline, not a feature.&lt;/STRONG&gt; A model that can't invent strengths is a better analyst than one that can.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;The fallback is the product.&lt;/STRONG&gt; Government staff will run this mid-presentation. It can't fail.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;Try it or build on it&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Live app:&lt;/STRONG&gt; &lt;A href="https://proud-field-00978990f.7.azurestaticapps.net" target="_blank" rel="noopener"&gt;https://proud-field-00978990f.7.azurestaticapps.net&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Demo (5 min):&lt;/STRONG&gt; &lt;A href="https://youtu.be/dTRjA8eKwgQ" target="_blank" rel="noopener"&gt;https://youtu.be/dTRjA8eKwgQ&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;GitHub:&lt;/STRONG&gt; &lt;A href="https://github.com/JonEricEubanks/CivicGrant-IQ" target="_blank" rel="noopener"&gt;https://github.com/JonEricEubanks/CivicGrant-IQ&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The patterns transfer anywhere you have a dense document corpus, a user without time to search it, and a need for cited, real-time analysis,&amp;nbsp; procurement, compliance, and nonprofit grants. Every year, billions in federal grants go unclaimed by the cities they were built for. Not because they don't qualify,&amp;nbsp; because knowing they qualify is invisible work done by people already doing three other jobs. That's solvable.&lt;/P&gt;</description>
      <pubDate>Fri, 31 Jul 2026 07:14:35 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/civicgrant-iq-the-five-agent-ai-that-reads-federal-grants-so/ba-p/4542419</guid>
      <dc:creator>JonEricEubanks</dc:creator>
      <dc:date>2026-07-31T07:14:35Z</dc:date>
    </item>
    <item>
      <title>ARGUS: Compliance Infrastructure That Believes Financial Access Is a Human Right</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/argus-compliance-infrastructure-that-believes-financial-access/ba-p/4539074</link>
      <description>&lt;P data-line="5"&gt;Guest post by &lt;A href="https://www.linkedin.com/in/iarjunganesh/" target="_blank"&gt;𝐀𝐫𝐣𝐮𝐧 𝐆𝐚𝐧𝐞𝐬𝐡 &lt;/A&gt;Winner of Hack for Good category Microsoft Agents League Hackathon&lt;BR /&gt;&lt;BR /&gt;A refugee family in Germany spends 18 months trying to open a bank account. Their documents are legitimate. But an automated KYC system — never designed with them in mind — scores their jurisdiction as high risk and closes the case. No human review. No plain-language explanation. No appeal path.&lt;/P&gt;
&lt;P data-line="7"&gt;An NGO doing legitimate microfinance work in Southeast Asia gets de-risked by their correspondent bank. The letter cites "risk appetite." The lending operation, which supports 4,000 families, can no longer move money.&lt;/P&gt;
&lt;P data-line="9"&gt;These aren't edge cases.&amp;nbsp;&lt;STRONG&gt;1.4 billion people remain financially excluded globally&lt;/STRONG&gt;&amp;nbsp;— and compliance systems built to protect institutions are a leading cause. The same technology meant to stop financial crime routinely shuts out the people who most need access.&lt;/P&gt;
&lt;P data-line="11"&gt;That's the problem I set out to fix with&amp;nbsp;&lt;STRONG&gt;ARGUS&lt;/STRONG&gt;&amp;nbsp;(Agentic Risk &amp;amp; Governance Unified Screening) at the Microsoft Agents League — AI Skills Fest 2026, where it was selected as&amp;nbsp;&lt;STRONG&gt;1 of 3 Hack for Good winners&lt;/STRONG&gt;&amp;nbsp;— awarded to the best solutions to solve a community need.&lt;/P&gt;
&lt;H2 data-line="13"&gt;What ARGUS does&lt;/H2&gt;
&lt;P data-line="15"&gt;ARGUS is compliance infrastructure that is explainable, accessible, and open — designed from the ground up for the humans most likely to be failed by the systems they depend on, not just for the institutions running the checks.&lt;/P&gt;
&lt;P data-line="17"&gt;A single KYC request fans out across&amp;nbsp;&lt;STRONG&gt;five specialist AI agents&lt;/STRONG&gt;, coordinated via the&amp;nbsp;&lt;STRONG&gt;Agent-to-Agent (A2A) protocol&lt;/STRONG&gt;&amp;nbsp;on&amp;nbsp;&lt;STRONG&gt;Azure AI Foundry&lt;/STRONG&gt;:&lt;/P&gt;
&lt;UL data-line="19"&gt;
&lt;LI data-line="19"&gt;🎯 &lt;STRONG&gt;Orchestrator Agent&lt;/STRONG&gt;&amp;nbsp;— task decomposition and result synthesis&lt;/LI&gt;
&lt;LI data-line="20"&gt;🪪 &lt;STRONG&gt;Identity Agent&lt;/STRONG&gt;&amp;nbsp;— customer lookup, OCR processing, identity validation&lt;/LI&gt;
&lt;LI data-line="21"&gt;🔍&amp;nbsp;&lt;STRONG&gt;Screening Agent&lt;/STRONG&gt;&amp;nbsp;— sanctions checks, adverse media scanning, PEP checks&lt;/LI&gt;
&lt;LI data-line="22"&gt;🏢&amp;nbsp;&lt;STRONG&gt;Corporate Intelligence Agent&lt;/STRONG&gt;&amp;nbsp;— UBO resolution, registry lookups, jurisdiction mapping&lt;/LI&gt;
&lt;LI data-line="23"&gt;💳&amp;nbsp;&lt;STRONG&gt;Transaction Intelligence Agent&lt;/STRONG&gt;&amp;nbsp;— transaction monitoring, pattern detection, typology matching&lt;/LI&gt;
&lt;/UL&gt;
&lt;P data-line="25"&gt;Each of these fans back into a&amp;nbsp;&lt;STRONG&gt;Compliance &amp;amp; Risk Agent&lt;/STRONG&gt;, which synthesizes everything into a single traceable risk report.&lt;/P&gt;
&lt;P data-line="27"&gt;The part I'm proudest of: nothing in that report is a black box. Every finding is grounded in cited regulatory knowledge via&amp;nbsp;&lt;STRONG&gt;Foundry IQ&lt;/STRONG&gt; — sanctions checks and regulatory triggers cite the exact knowledge base, source document, and article behind them. Every risk score comes with a plain-English reason. Every decision leaves a full audit trail: agent by agent, tool by tool, citation by citation.&lt;/P&gt;
&lt;P class="lia-indent-padding-left-30px"&gt;&lt;EM&gt;Submit entity → 5 agents run in parallel → Compliance fan-in → Traceable risk report&lt;/EM&gt;&lt;/P&gt;
&lt;P data-line="33"&gt;📹&amp;nbsp;&lt;A href="https://youtu.be/yaTNCgCwX4s" target="_blank" rel="noopener" data-href="https://youtu.be/yaTNCgCwX4s"&gt;Watch the 5-minute demo&lt;/A&gt;&lt;/P&gt;
&lt;H2 data-line="35"&gt;What's next: ARGUS v2&lt;/H2&gt;
&lt;P data-line="37"&gt;The hackathon build proved the architecture holds up. The v2 roadmap is where it grows into something NGOs and microfinance institutions can actually run:&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Feature&lt;/th&gt;&lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;♿ Full WCAG 2.1 AA compliance&lt;/td&gt;&lt;td&gt;In progress&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;🗣 Explain Mode — plain-language reports for the person being screened&lt;/td&gt;&lt;td&gt;In progress&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;🌍 Community Edition — free, self-hostable, zero Azure subscription required&lt;/td&gt;&lt;td&gt;Designed&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;📊 Real-time Azure Monitor compliance dashboard&lt;/td&gt;&lt;td&gt;Designed&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;🔓 Open Knowledge Graph — FATF, Basel AML Index, OFAC/EU/UN lists as open data&lt;/td&gt;&lt;td&gt;Planned&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 50.00%" /&gt;&lt;col style="width: 50.00%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P data-line="47"&gt;&lt;STRONG&gt;Explain Mode&lt;/STRONG&gt;&amp;nbsp;is the one I'd highlight for an educator audience. Today's report is written for compliance analysts:&lt;/P&gt;
&lt;P data-line="49"&gt;&lt;EM&gt;"Dimension score 78 — HIGH tier — regulatory trigger: FATF Recommendation 16 (KB-Regulations › FATF-40 › R.16)"&lt;/EM&gt;&lt;/P&gt;
&lt;P data-line="51"&gt;Explain Mode generates the same finding for the person being screened, or the NGO caseworker who has to explain a decision to a family:&lt;/P&gt;
&lt;P data-line="53"&gt;&lt;EM&gt;"This account review flagged a potential concern with how money moved through the transaction chain. This is a standard check for large or cross-border transfers. A compliance officer will review this before a final decision is made. You don't need to do anything right now."&lt;/EM&gt;&lt;/P&gt;
&lt;P data-line="55"&gt;Same underlying data. Entirely different outcome for the person on the receiving end.&lt;/P&gt;
&lt;P data-line="57"&gt;&lt;STRONG&gt;Community Edition&lt;/STRONG&gt;&amp;nbsp;is the biggest bet: a zero-cost, self-hostable configuration for NGOs, microfinance institutions, community banks, and researchers — a pre-seeded public knowledge base, a one-command Docker Compose stack, and a lower-cost LLM path, so an Azure subscription isn't a prerequisite for the core flow.&lt;/P&gt;
&lt;H2 data-line="59"&gt;Try it yourself&lt;/H2&gt;
&lt;P data-line="61"&gt;ARGUS is open source under MIT. If you're teaching agentic AI, Azure AI Foundry, or Semantic Kernel, the repo is built to be a working example of multi-agent orchestration with A2A and grounded retrieval via Foundry IQ:&lt;/P&gt;
&lt;LI-CODE lang="powershell"&gt;git clone https://github.com/iarjunganesh/argus.git
cd argus
pip install -r requirements.txt
cp .env.example .env
make generate-data &amp;amp;&amp;amp; make generate-ocr-docs
make index-knowledge-bases
.\scripts\start_demo.ps1&lt;/LI-CODE&gt;
&lt;P data-line="73"&gt;The Community Edition — no Azure subscription required — is scaffolded in&amp;nbsp;&lt;A href="https://github.com/iarjunganesh/argus/tree/main/community" target="_blank" rel="noopener" data-href="https://github.com/iarjunganesh/argus/tree/main/community"&gt;community/&lt;/A&gt;&amp;nbsp;as part of the v2 roadmap, but isn't runnable yet.&lt;/P&gt;
&lt;P data-line="75"&gt;The most-needed contributions right now are WCAG contrast tests for the Gradio UI, translations of Explain Mode output, and finishing the Community Edition Docker Compose stack (Dockerfile + local knowledge base seed) — all good starter issues for students exploring accessible AI system design.&lt;/P&gt;
&lt;P data-line="77"&gt;&lt;STRONG&gt;Repo:&lt;/STRONG&gt;&amp;nbsp;&lt;A href="https://github.com/iarjunganesh/argus" target="_blank" rel="noopener" data-href="https://github.com/iarjunganesh/argus"&gt;https://github.com/iarjunganesh/argus&lt;/A&gt;&lt;/P&gt;
&lt;P data-line="77"&gt;&lt;STRONG&gt;Demo video:&lt;/STRONG&gt;&amp;nbsp;&lt;A href="https://youtu.be/yaTNCgCwX4s" target="_blank" rel="noopener" data-href="https://youtu.be/yaTNCgCwX4s"&gt;https://youtu.be/yaTNCgCwX4s&lt;/A&gt;&lt;/P&gt;
&lt;P data-line="80"&gt;&lt;EM&gt;ARGUS is a technology demonstration and is not a licensed compliance tool — it must not be used to make real KYC/AML decisions.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 30 Jul 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/argus-compliance-infrastructure-that-believes-financial-access/ba-p/4539074</guid>
      <dc:creator>iarjunganesh</dc:creator>
      <dc:date>2026-07-30T07:00:00Z</dc:date>
    </item>
    <item>
      <title>Grounded AI That Won't Invent Facts: Building "Tell My Day" with Microsoft Foundry IQ</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/grounded-ai-that-won-t-invent-facts-building-quot-tell-my-day/ba-p/4539116</link>
      <description>&lt;P data-sourcepos="7:1-7:473;530-1002"&gt;Guest post by &lt;A class="lia-external-url" href="https://www.linkedin.com/in/cadenstorkamp" target="_blank"&gt;Caden Storkamp&lt;/A&gt; Winner of the Hack for Good Category Microsoft Agents League Hackathon&lt;/P&gt;
&lt;P data-sourcepos="7:1-7:473;530-1002"&gt;Large language models make things up. For a lot of apps that is a minor annoyance you can smooth over. For some, it is disqualifying, because the cost of a confident, fluent, false statement is real. This post walks through one of those cases and the pattern that makes it safe to ship: retrieve from a trusted knowledge base with Microsoft Foundry IQ, force the model to cite verbatim quotes, and then verify those quotes on the server before anything reaches the screen.&lt;/P&gt;
&lt;P data-sourcepos="9:1-9:451;1004-1454"&gt;My name is Caden Storkamp, and the app I build is called Tell My Day. I work as a direct support professional, and in this role I work day to day with people who use AAC (augmentative and alternative communication). The use of the app I made is not just limited to it's primary goal, but can be also used as an example for others. If you are teaching or building anything where a generative feature has to be trustworthy, this is a small, readable, reproducible reference you can lift from.&lt;/P&gt;
&lt;H5 data-sourcepos="11:1-11:57;1456-1512"&gt;&lt;STRONG&gt;The problem, and why it is the sharpest possible test&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="13:1-13:356;1514-1869"&gt;AAC (augmentative and alternative communication) is how many non-speaking people communicate: picture boards, symbol devices, picture exchange. These tools are good at "I want a drink" in the moment. They are much worse at letting someone tell a story, like how their day went, in their own voice. Caregivers or family members often end up narrating on the person's behalf.&lt;/P&gt;
&lt;P data-sourcepos="15:1-15:603;1871-2473"&gt;Tell My Day flips that. The person picks the symbols, and the app writes the story. That immediately raises the stakes to the highest possible level for hallucination, because you are now generating first-person speech attributed to someone who cannot easily correct you. If the app writes "I went to the zoo today" when they did not, it has put false words in a non-speaking person's mouth, to the people they most need to trust them. So "never invent anything" is not just a great thing to have here. It is the whole product. That constraint is exactly why it makes such a clean showcase for grounded generation.&lt;/P&gt;
&lt;H5 data-sourcepos="17:1-17:21;2475-2495"&gt;&lt;STRONG&gt;What the app does&lt;/STRONG&gt;&lt;/H5&gt;
&lt;OL data-sourcepos="19:1-22:136;2497-2946"&gt;
&lt;LI data-sourcepos="19:1-19:98;2497-2594"&gt;A non-speaking adult taps 3 to 8 picture symbols (people, places, activities, feelings, food).&lt;/LI&gt;
&lt;LI data-sourcepos="20:1-20:62;2595-2656"&gt;The app writes 2 to 4 short, warm, first-person sentences.&lt;/LI&gt;
&lt;LI data-sourcepos="21:1-21:154;2657-2810"&gt;The story is grounded in the person's own "About Me" profile, so a generic "my friend" becomes "my friend Marcus" only when that fact actually exists.&lt;/LI&gt;
&lt;LI data-sourcepos="22:1-22:136;2811-2946"&gt;Every grounded detail shows a citation, the story reads aloud, and unmatched symbols stay general instead of getting a made-up name.
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;H5&gt;&lt;STRONG&gt;The Microsoft stack at a glance&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="28:1-28:66;3093-3158"&gt;Everything here is Azure, and the whole thing runs on free tiers.&lt;/P&gt;
&lt;UL data-sourcepos="30:1-34:51;3160-3908"&gt;
&lt;LI data-sourcepos="30:1-30:214;3160-3373"&gt;&lt;STRONG&gt;Azure Static Web Apps (Free plan):&lt;/STRONG&gt; hosts the static React frontend and a set of managed Azure Functions together, with one GitHub Actions deploy. All secrets live in environment variables on the server side.&lt;/LI&gt;
&lt;LI data-sourcepos="31:1-31:235;3374-3608"&gt;&lt;STRONG&gt;Microsoft Foundry IQ:&lt;/STRONG&gt; the knowledge layer. A knowledge base over an Azure AI Search knowledge source holds the profile, and a single retrieve call does agentic retrieval and returns grounded, numbered facts with their sources.&lt;/LI&gt;
&lt;LI data-sourcepos="32:1-32:172;3609-3780"&gt;&lt;STRONG&gt;Microsoft Foundry model deployment (gpt-4.1-mini):&lt;/STRONG&gt; turns the retrieved facts plus the selected symbols into the story, called through the OpenAI-compatible endpoint.&lt;/LI&gt;
&lt;LI data-sourcepos="33:1-33:77;3781-3857"&gt;&lt;STRONG&gt;Web Speech API:&lt;/STRONG&gt; free, offline, zero-latency read-aloud in the browser.&lt;/LI&gt;
&lt;LI data-sourcepos="34:1-34:51;3858-3908"&gt;&lt;STRONG&gt;GitHub Copilot:&lt;/STRONG&gt; used throughout development.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P data-sourcepos="36:1-36:119;3910-4028"&gt;Here is the request flow. The key property is that the browser never holds a secret and never talks to Azure directly.&lt;/P&gt;
&lt;/LI&gt;
&lt;/OL&gt;
&lt;img /&gt;
&lt;H5 data-sourcepos="59:1-59:30;4807-4836"&gt;&lt;STRONG&gt;How it works, step by step&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="61:1-61:162;4838-4999"&gt;The whole backend is one framework-agnostic pipeline behind a roughly 15-line Azure Function, so no secret ever reaches the client. Four pieces do the real work.&lt;/P&gt;
&lt;H5 data-sourcepos="63:1-63:49;5001-5049"&gt;&lt;STRONG&gt;1. Stand up the knowledge base (one command)&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="65:1-65:338;5051-5388"&gt;Foundry IQ setup is refreshingly declarative. A single script (npm run setup:iq) creates a "file" knowledge source, uploads the five profile markdown files, and creates the knowledge base that retrieval runs against. Because the profile is small, a keyword-based file source is used, so there is no embedding model to configure at all.&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN class="lia-text-color-19"&gt;// 1) A "file" knowledge source: keyword retrieval, no embedding model needed.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-15"&gt;&lt;SPAN class="lia-text-color-14"&gt;await&lt;/SPAN&gt; put&lt;/SPAN&gt;(&lt;SPAN class="lia-text-color-11"&gt;`&lt;/SPAN&gt;${&lt;SPAN class="lia-text-color-11"&gt;searchEndpoint&lt;/SPAN&gt;}&lt;SPAN class="lia-text-color-11"&gt;/knowledgesources/tell-my-day-ks?api-version=&lt;/SPAN&gt;${&lt;SPAN class="lia-text-color-11"&gt;apiVersion&lt;/SPAN&gt;}&lt;SPAN class="lia-text-color-11"&gt;`&lt;/SPAN&gt;, {&lt;BR /&gt;  name: &lt;SPAN class="lia-text-color-11"&gt;"tell-my-day-ks"&lt;/SPAN&gt;,&lt;BR /&gt;  kind: &lt;SPAN class="lia-text-color-11"&gt;"file"&lt;/SPAN&gt;,&lt;BR /&gt;  fileParameters: { ingestionParameters: { contentExtractionMode: "minimal" } },&lt;BR /&gt;});&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-19"&gt;// (each docs/profile/*.md is then uploaded as a file)&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-19"&gt;// 2) The knowledge base that retrieval runs against.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-14"&gt;await&lt;/SPAN&gt; &lt;SPAN class="lia-text-color-15"&gt;put&lt;/SPAN&gt;(`${&lt;SPAN class="lia-text-color-11"&gt;searchEndpoint&lt;/SPAN&gt;}&lt;SPAN class="lia-text-color-11"&gt;/knowledgebases/tell-my-day-kb?api-&lt;/SPAN&gt;&lt;SPAN class="lia-text-color-11"&gt;version=&lt;/SPAN&gt;${&lt;SPAN class="lia-text-color-11"&gt;apiVersion&lt;/SPAN&gt;}&lt;SPAN class="lia-text-color-11"&gt;`&lt;/SPAN&gt;, {&lt;BR /&gt;  name: &lt;SPAN class="lia-text-color-11"&gt;"tell-my-day-kb"&lt;/SPAN&gt;,&lt;BR /&gt;  knowledgeSources: [{ name: &lt;SPAN class="lia-text-color-11"&gt;"tell-my-day-ks"&lt;/SPAN&gt; }],&lt;BR /&gt;  retrievalReasoningEffort: { kind: &lt;SPAN class="lia-text-color-11"&gt;"minimal"&lt;/SPAN&gt; },&lt;BR /&gt;});&lt;/PRE&gt;
&lt;P&gt;(The &lt;SPAN class="lia-text-color-13"&gt;put&lt;/SPAN&gt; helper above is shorthand for readability. The full, idempotent script is in the repo.)&lt;/P&gt;
&lt;H5 data-sourcepos="87:1-87:47;6137-6183"&gt;&lt;STRONG&gt;2. Retrieve grounded facts at request time&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="89:1-89:231;6185-6415"&gt;When the user submits their symbols, the Azure Function sends one semantic intent per symbol label to the knowledge base. Foundry IQ handles the retrieval and returns numbered facts, each tied back to the source file it came from.&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN class="lia-text-color-19"&gt;// One semantic intent per selected symbol label ("mom", "coffee shop", "happy").&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-14"&gt;const&lt;/SPAN&gt; url =&lt;SPAN class="lia-text-color-11"&gt;`&lt;/SPAN&gt;${&lt;SPAN class="lia-text-color-11"&gt;searchEndpoint&lt;/SPAN&gt;}/&lt;SPAN class="lia-text-color-11"&gt;knowledgebases/&lt;/SPAN&gt;${&lt;SPAN class="lia-text-color-11"&gt;kbName&lt;/SPAN&gt;}&lt;SPAN class="lia-text-color-11"&gt;/retrieve?&lt;/SPAN&gt;&lt;SPAN class="lia-text-color-11"&gt;api-version=&lt;/SPAN&gt;${&lt;SPAN class="lia-text-color-11"&gt;apiVersion&lt;/SPAN&gt;}&lt;SPAN class="lia-text-color-11"&gt;`&lt;/SPAN&gt;;&lt;BR /&gt;&lt;SPAN class="lia-text-color-14"&gt;const&lt;/SPAN&gt; res = &lt;SPAN class="lia-text-color-14"&gt;await&lt;/SPAN&gt; &lt;SPAN class="lia-text-color-15"&gt;fetch&lt;/SPAN&gt;(url, {&lt;BR /&gt;  method: &lt;SPAN class="lia-text-color-11"&gt;"POST"&lt;/SPAN&gt;,&lt;BR /&gt;  headers: { &lt;SPAN class="lia-text-color-13"&gt;"Content-Type"&lt;/SPAN&gt;: &lt;SPAN class="lia-text-color-11"&gt;"application/json"&lt;/SPAN&gt;, &lt;SPAN class="lia-text-color-13"&gt;"api-key"&lt;/SPAN&gt;: searchKey },&lt;BR /&gt;  body: &lt;SPAN class="lia-text-color-11"&gt;JSON&lt;/SPAN&gt;.&lt;SPAN class="lia-text-color-15"&gt;stringify&lt;/SPAN&gt;({&lt;BR /&gt;    intents: symbols.&lt;SPAN class="lia-text-color-15"&gt;map&lt;/SPAN&gt;((s) =&amp;gt; ({ type: &lt;SPAN class="lia-text-color-11"&gt;"semantic"&lt;/SPAN&gt;, search: s.label })),&lt;BR /&gt;  }),&lt;BR /&gt;});&lt;BR /&gt;&lt;SPAN class="lia-text-color-19"&gt;// Returns numbered, grounded facts, each carrying its source document name.&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;H5 data-sourcepos="104:1-104:51;6919-6969"&gt;&lt;STRONG&gt;3. Ground the model with a no-invention prompt&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="106:1-106:236;6971-7206"&gt;The retrieved facts and the symbols go to gpt-4.1-mini with a system prompt whose rules are the safety property, stated plainly. The model is required to return strict JSON where every sentence carries the verbatim quotes it relied on.&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN class="lia-text-color-19"&gt;// The rules the model must never break (trimmed):&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-11"&gt;`- Write 2 to 4 short, warm, first-person sentences.&lt;/SPAN&gt;&lt;BR /&gt;- Include the idea of EVERY selected symbol at least once.&lt;BR /&gt;- Use ONLY (a) the selected symbols and (b) the numbered profile facts.&lt;BR /&gt;  Never invent people, places, events, or details.&lt;BR /&gt;- If a symbol has no matching fact, keep it general ("my friend", "the park"), never a made-up name.&lt;BR /&gt;&lt;SPAN class="lia-text-color-11"&gt;- Return strict JSON: each sentence lists the verbatim quotes it relied on.`&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;The call itself uses &lt;SPAN class="lia-text-color-12"&gt;r&lt;/SPAN&gt;&lt;SPAN class="lia-text-color-12"&gt;&lt;SPAN class="lia-text-color-12"&gt;e&lt;/SPAN&gt;sponse_format: { type: "json_object" }&lt;/SPAN&gt; and a low temperature, so the output is structured and predictable rather than creative.&lt;/P&gt;
&lt;H5 data-sourcepos="121:1-121:69;7847-7915"&gt;&lt;STRONG&gt;4. Verify every quote on the server (the part that matters most)&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="123:1-123:347;7917-8263"&gt;A prompt that says "do not lie" is not a guarantee. So the server does not take the model's word for it. Every citation the model returns is checked against the actual retrieved fact. A quote that is not really there is kept but marked verified: false, which lets the interface show the user exactly which claims are grounded and which are not.&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN class="lia-text-color-19"&gt;// Is this quote actually present in the fact the model cited?&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-14"&gt;function&lt;/SPAN&gt; &lt;SPAN class="lia-text-color-15"&gt;verifyQuote&lt;/SPAN&gt;(quote: &lt;SPAN class="lia-text-color-12"&gt;string&lt;/SPAN&gt;, factContent: &lt;SPAN class="lia-text-color-12"&gt;string&lt;/SPAN&gt;): &lt;SPAN class="lia-text-color-12"&gt;boolean&lt;/SPAN&gt; {&lt;BR /&gt;&lt;SPAN class="lia-text-color-14"&gt;  const&lt;/SPAN&gt; q = &lt;SPAN class="lia-text-color-15"&gt;normalize&lt;/SPAN&gt;(quote);&lt;BR /&gt;&lt;SPAN class="lia-text-color-14"&gt;  return&lt;/SPAN&gt; q.length &amp;gt; &lt;SPAN class="lia-text-color-11"&gt;0&lt;/SPAN&gt; &amp;amp;&amp;amp; &lt;SPAN class="lia-text-color-15"&gt;normalize&lt;/SPAN&gt;(factContent).&lt;SPAN class="lia-text-color-15"&gt;includes&lt;/SPAN&gt;(q);&lt;BR /&gt;}&lt;BR /&gt;// ...when assembling each sentence's citations:&lt;BR /&gt;citations.&lt;SPAN class="lia-text-color-15"&gt;push&lt;/SPAN&gt;({&lt;BR /&gt;  factId: fact.factId,&lt;BR /&gt;  docName: fact.docName,&lt;BR /&gt;  quote,&lt;BR /&gt;  verified: &lt;SPAN class="lia-text-color-15"&gt;verifyQuote&lt;/SPAN&gt;(quote, fact.content),&lt;BR /&gt;});&lt;/PRE&gt;
&lt;P&gt;That is the whole trust story in one function. Retrieval limits what the model can know, the prompt forces it to cite, and this check confirms the citations are real before the user sees them. The pattern is not specific to AAC. It is reusable for any generative feature where a wrong answer costs something.&lt;/P&gt;
&lt;H5 data-sourcepos="143:1-143:43;8992-9034"&gt;&lt;STRONG&gt;Deploying free on Azure Static Web Apps&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="145:1-145:408;9036-9443"&gt;The frontend and the Azure Functions ship together. You create a Static Web App on the Free plan, add the deployment token as a GitHub Actions secret, put your Foundry and Azure AI Search values into the app's environment variables, and push to main. The included workflow builds the Vite app and deploys the api/ folder as managed functions. There is no separate server to run and nothing to keep warm.&lt;/P&gt;
&lt;H5 data-sourcepos="147:1-147:50;9445-9494"&gt;&lt;STRONG&gt;De-risking the build (a method worth teaching)&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="149:1-149:161;9496-9656"&gt;The riskiest part of this project was the integration I understood least: Foundry IQ. So it went first, behind two gates that had to pass before any UI existed.&lt;/P&gt;
&lt;PRE&gt;bash&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-15"&gt;npm&lt;/SPAN&gt; run setup:iq       &lt;SPAN class="lia-text-color-19"&gt;#&lt;/SPAN&gt;&lt;SPAN class="lia-text-color-19"&gt; create the knowledge source + upload profile + create the KB&lt;/SPAN&gt; &lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-15"&gt;npm&lt;/SPAN&gt; run test:model     &lt;SPAN class="lia-text-color-19"&gt;# gate 1: the model answers at all&lt;/SPAN&gt; &lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-15"&gt;npm&lt;/SPAN&gt; run test:iq        &lt;SPAN class="lia-text-color-19"&gt;# gate 2: retrieval returns grounded, cited facts&lt;/SPAN&gt; &lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-15"&gt;npm&lt;/SPAN&gt; run dev            &lt;SPAN class="lia-text-color-19"&gt;# only now build the app on top&lt;/SPAN&gt; &lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-15"&gt;npm&lt;/SPAN&gt; &lt;SPAN class="lia-text-color-12"&gt;test&lt;/SPAN&gt;               &lt;SPAN class="lia-text-color-19"&gt;# unit tests for validation, JSON parsing, and quote verification&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P data-sourcepos="159:1-159:310;10022-10331"&gt;Standing up and proving the retrieval before building anything on top of it meant the app was never resting on an assumption that could quietly turn out to be false. The verification logic, the input validation, and the parsing all have unit tests, so the trust-critical code is covered rather than hoped for.&lt;/P&gt;
&lt;H5 data-sourcepos="161:1-161:53;10333-10385"&gt;&lt;STRONG&gt;Accessibility is the product, not a coat of paint&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="163:1-163:111;10387-10497"&gt;Because the users are the entire point, accessibility is built into every component, not bolted on at the end.&lt;/P&gt;
&lt;UL data-sourcepos="165:1-168:106;10499-11269"&gt;
&lt;LI data-sourcepos="165:1-165:248;10499-10746"&gt;&lt;STRONG&gt;Two-level single-switch scanning:&lt;/STRONG&gt; regions highlight in turn, and one switch (Space, or a tap anywhere) drills in and selects, with adjustable scan speed. This is what makes the app usable for someone who cannot use a touchscreen or keyboard.&lt;/LI&gt;
&lt;LI data-sourcepos="166:1-166:214;10747-10960"&gt;&lt;STRONG&gt;Grounding as an accessibility feature:&lt;/STRONG&gt; a user who cannot easily correct the output has to be able to trust it, so the visible, verified citations are not a developer nicety. They are core to who this is for.&lt;/LI&gt;
&lt;LI data-sourcepos="167:1-167:203;10961-11163"&gt;Full keyboard operation, large tap targets (64px and up), an aria-live region for the story, a high-contrast theme, adjustable text size, and reduce-motion support that honors the system preference.&lt;/LI&gt;
&lt;LI data-sourcepos="168:1-168:106;11164-11269"&gt;Read-aloud with play and pause, adjustable speed and pitch, and word-by-word highlighting as it speaks.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P data-sourcepos="170:1-170:256;11271-11526"&gt;There is also a caregiver profile editor, gated by a server-side PIN, that writes edits straight back to the Foundry IQ knowledge source. The knowledge base stays the single source of truth, and new facts reach stories after about a minute of re-indexing.&lt;/P&gt;
&lt;H5 data-sourcepos="172:1-172:22;11528-11549"&gt;&lt;STRONG&gt;Results and impact&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="174:1-174:132;11551-11682"&gt;After completion of development, I was able to see Tell My Day demonstrate these outcomes:&lt;/P&gt;
&lt;UL data-sourcepos="178:1-180:152;11750-12324"&gt;
&lt;LI data-sourcepos="178:1-178:176;11750-11925"&gt;&lt;STRONG&gt;Every fact shown in a story is backed by a quote that was verified against its source.&lt;/STRONG&gt; A model claim that cannot be verified is flagged rather than presented as trusted.&lt;/LI&gt;
&lt;LI data-sourcepos="179:1-179:247;11926-12172"&gt;&lt;STRONG&gt;Symbols with no matching profile fact always stay general.&lt;/STRONG&gt; In the sample profile, selecting &lt;EM&gt;Grandma&lt;/EM&gt;, &lt;EM&gt;Beach&lt;/EM&gt;, or &lt;EM&gt;School&lt;/EM&gt; produces "my friend" or "the park," never a fabricated name. That is the behavior you can test yourself in the repo.&lt;/LI&gt;
&lt;LI data-sourcepos="180:1-180:152;12173-12324"&gt;&lt;STRONG&gt;The app is fully operable by keyboard and by a single switch,&lt;/STRONG&gt; which is the bar that decides whether an AAC tool is usable at all for many people.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P data-sourcepos="184:1-184:364;12467-12830"&gt;The honest differentiator is not the AI model. Anyone can call a model. It is that the product decisions (stay general instead of guessing, never infantilize, write a full sentence instead of a fragment) come from someone who watches real AAC communication succeed and fail, combined with a platform that made grounding and verification straightforward to implement.&lt;/P&gt;
&lt;H5 data-sourcepos="186:1-186:19;12832-12850"&gt;&lt;STRONG&gt;Lessons learned&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="188:1-188:367;12852-13218"&gt;&lt;STRONG&gt;The safety mechanism and the platform feature were the same thing.&lt;/STRONG&gt; Going in, "use Foundry IQ" and "never fabricate" looked like two separate tasks. They turned out to be one: Foundry IQ's retrieve-and-cite pattern &lt;EM&gt;is&lt;/EM&gt; the no-invention rule, and a small server-side verification step closes the gap between "the model cited something" and "the citation is real."&lt;/P&gt;
&lt;P data-sourcepos="190:1-190:157;13220-13376"&gt;&lt;STRONG&gt;Put the riskiest integration first.&lt;/STRONG&gt; Proving retrieval before building UI is cheap insurance against building something beautiful on a broken foundation.&lt;/P&gt;
&lt;P data-sourcepos="192:1-192:266;13378-13643"&gt;&lt;STRONG&gt;Grounding plus verification is a reusable pattern.&lt;/STRONG&gt; Retrieve from a trusted source, force citations, verify them server-side. That transfers to compliance summaries, customer support, internal knowledge assistants, anywhere a confident wrong answer is expensive.&lt;/P&gt;
&lt;H5 data-sourcepos="200:1-200:26;14457-14482"&gt;&lt;STRONG&gt;See it, or build on it&lt;/STRONG&gt;&lt;/H5&gt;
&lt;P data-sourcepos="202:1-202:114;14484-14597"&gt;If you teach or build with Azure AI, care about trustworthy generative AI, or work in accessibility, take a look.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;GitHub repo:&lt;/STRONG&gt; &lt;A href="https://github.com/stork066/TellMyDay" target="_blank" rel="noopener"&gt;https://github.com/stork066/TellMyDay&lt;/A&gt; (to try it out yourself just clone it and run it with your own Foundry and Azure AI Search keys)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Demo video: &lt;/STRONG&gt;&lt;A class="lia-external-url" href="https://www.youtube.com/watch?v=v_8WAhurzOY" target="_blank" rel="noopener"&gt;https://www.youtube.com/watch?v=v_8WAhurzOY&lt;/A&gt;&amp;nbsp;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P data-sourcepos="207:1-207:435;14869-15303"&gt;Two ways to build on it. If you are learning Microsoft Foundry, this is a compact, working example of wiring a Foundry IQ knowledge base to a model and putting a verification layer around it, deployed on Azure Static Web Apps for free. And if you work anywhere that a generative feature has to be trusted, lift the grounding and verification pattern directly. The stakes in your domain may be different, but the mechanism is the same.&lt;/P&gt;</description>
      <pubDate>Wed, 29 Jul 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/grounded-ai-that-won-t-invent-facts-building-quot-tell-my-day/ba-p/4539116</guid>
      <dc:creator>caden322</dc:creator>
      <dc:date>2026-07-29T07:00:00Z</dc:date>
    </item>
    <item>
      <title>How I Built CurriculumCraft AI — A Microsoft Hackathon Winning EdTech Solution for Ghana's Teachers</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/how-i-built-curriculumcraft-ai-a-microsoft-hackathon-winning/ba-p/4537826</link>
      <description>&lt;P&gt;By&amp;nbsp;&lt;A href="https://www.linkedin.com/in/gideon-k-agbavor/" target="_blank"&gt;Gideon K. Agbavor &lt;/A&gt;Top Student Award Winner, Microsoft Agents League AISF Hackathon 2026&lt;/P&gt;
&lt;H3&gt;A Problem I Lived as a Teacher&lt;/H3&gt;
&lt;P&gt;Before I branch into software developer, I am a Mathematics and ICT teacher in Ghana education or school system. Every Sunday evening and sometimes every three days, I sat with a thick PDF — Ghana's NaCCA Standards-Based Curriculum — and spent hours manually converting dense curriculum indicators into lesson plans for the week ahead.&lt;/P&gt;
&lt;P&gt;I was not alone. Across Ghana, thousands of Junior High School teachers (Primary teachers too) face the same challenge. They manage classes of 30 to 40 students, operate in under-resourced schools outside major cities, and have almost no planning support. The NaCCA Standards-Based Curriculum introduced by Ghana's National Council for Curriculum and Assessment is rigorous and well-structured — but translating its indicators into classroom-ready materials is time-consuming and administratively exhausting.&lt;/P&gt;
&lt;P&gt;When I heard about the Microsoft Agents League AISF Hackathon 2026, I knew exactly what I wanted to build — a tool that eliminates this burden for every Ghanaian JHS teacher, regardless of where they teach or how much support they have.&lt;/P&gt;
&lt;P&gt;That tool became &lt;STRONG&gt;CurriculumCraft AI&lt;/STRONG&gt; — and it won one of the&amp;nbsp;&lt;STRONG&gt;Top Student Award&lt;/STRONG&gt; at the hackathon.&lt;/P&gt;
&lt;H3&gt;The Solution — CurriculumCraft AI&lt;/H3&gt;
&lt;P&gt;CurriculumCraft AI is a full-stack AI-powered instructional design platfo&lt;/P&gt;
&lt;P&gt;rm that transforms any NaCCA curriculum indicator into complete, classroom-ready lesson materials in seconds.&lt;/P&gt;
&lt;P&gt;A teacher visits the app, selects their subject, grade level (B7, B8, or B9), strand, and indicator from the real NaCCA curriculum tree — and the app generates three complete outputs instantly:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Teacher Notes&lt;/STRONG&gt; — a full lesson plan with timings, learning objectives aligned to Bloom's Taxonomy, key vocabulary, common misconceptions, and differentiation tips for mixed-ability classes&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Visual Content Prompts&lt;/STRONG&gt; — four practical classroom visual aids a teacher can create with minimal resources, designed specifically for under-resourced Ghanaian classrooms&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Student Reading Material&lt;/STRONG&gt; — a culturally relevant reading passage using authentic Ghanaian names, settings, and examples, complete with worked examples and comprehension questions&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Beyond lesson generation, the app also features an &lt;STRONG&gt;Interactive Activity Suite&lt;/STRONG&gt; that generates multiple-choice questions with instant answer feedback, writing prompts with sample answers, and assessment rubrics — all aligned to the selected NaCCA indicator.&lt;/P&gt;
&lt;P&gt;Every piece of generated content uses authentic Ghanaian cultural context — local names like Ama, Kofi, and Adjoa, local settings like Kumasi Central Market and Cape Coast fishing harbour, Ghana Cedis for mathematical examples, and references to local foods and traditions. A student in Ho, Tamale, Accra, or Bolgatanga should see themselves in their learning materials.&lt;/P&gt;
&lt;H3&gt;Architecture and Technology&lt;/H3&gt;
&lt;P&gt;CurriculumCraft AI is built on a modern full-stack architecture designed for reliability, performance, and scalability.&lt;/P&gt;
&lt;img&gt;architecture&lt;/img&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Frontend:&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Next.js 15 with App Router and React Server Components&lt;/LI&gt;
&lt;LI&gt;Tailwind CSS v4 for responsive, accessible styling&lt;/LI&gt;
&lt;LI&gt;shadcn/ui for polished component design&lt;/LI&gt;
&lt;LI&gt;Dark and light theme support&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;Backend:&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Next.js API Routes for server-side logic&lt;/LI&gt;
&lt;LI&gt;Neon PostgreSQL (serverless) as the database&lt;/LI&gt;
&lt;LI&gt;Drizzle ORM for type-safe database queries&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;AI and Microsoft Services:&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Microsoft Foundry IQ&lt;/STRONG&gt; — the intelligence grounding layer that retrieves NaCCA curriculum context before each generation request, anchoring outputs to actual curriculum standards&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;GitHub Models (gpt-4o-mini)&lt;/STRONG&gt; — the generation layer that produces lesson materials based on the grounded context&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;GitHub Copilot&lt;/STRONG&gt; — used throughout development in VS Code for schema generation, API route scaffolding, component design, and prompt engineering&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;Deployment:&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Vercel for frontend and serverless API hosting&lt;/LI&gt;
&lt;LI&gt;Neon PostgreSQL for persistent curriculum and lesson data&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;Data:&lt;/STRONG&gt;&lt;BR /&gt;The database is seeded with real NaCCA curriculum data across 7 subjects — Mathematics, Science, English Language, Computing, Social Studies, RME, and Career Technology — covering all three JHS grade levels (B7, B8, B9) with authentic indicator codes like B7.1.1.1.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;Microsoft Foundry IQ Integration&lt;/H3&gt;
&lt;P&gt;One of the core requirements of the Agents League Hackathon Creative Apps track was integrating at least one Microsoft IQ intelligence layer. I chose &lt;STRONG&gt;Microsoft Foundry IQ&lt;/STRONG&gt; as the grounding layer for CurriculumCraft AI.&lt;/P&gt;
&lt;P&gt;Before generating any lesson materials, the app queries the Agents League Foundry IQ hub to retrieve curriculum-specific context for the selected NaCCA indicator. This grounded context is then passed to the generation layer as additional prompt context, reducing hallucination and ensuring the generated content is anchored to actual curriculum standards rather than generic AI outputs.&lt;/P&gt;
&lt;P&gt;The integration is implemented in the /api/generate route and includes graceful fallback to direct generation when the endpoint is unavailable — ensuring the app remains fully functional under all conditions.&lt;/P&gt;
&lt;img /&gt;
&lt;H3&gt;GitHub Copilot — AI-Assisted Development&lt;/H3&gt;
&lt;P&gt;Building CurriculumCraft AI as a solo developer within the hackathon timeline would have been extremely difficult without &lt;STRONG&gt;GitHub Copilot&lt;/STRONG&gt; in VS Code. Copilot accelerated development at every layer:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Database schema&lt;/STRONG&gt; — I described the NaCCA curriculum structure in natural language and Copilot generated the complete Drizzle ORM schema for all five tables (subjects, strands, sub-strands, indicators, saved lessons) with proper foreign key relationships.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;API routes&lt;/STRONG&gt; — All four API routes (/api/curriculum, /api/generate, /api/generate/activity, /api/lessons) were scaffolded with Copilot inline completions, significantly reducing boilerplate.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;TypeScript types&lt;/STRONG&gt; — The full type definitions for the curriculum data structures, API request/response types, and component props were generated through Copilot Chat.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Prompt engineering&lt;/STRONG&gt; — The system prompts in prompts/lesson.ts and prompts/activity.ts were refined iteratively with Copilot suggestions, helping me structure the cultural context instructions and output formatting rules effectively.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Bug resolution&lt;/STRONG&gt; — ESLint errors, TypeScript type conflicts, and React hook dependency warnings were resolved quickly using Copilot Chat explanations, keeping the development velocity high.&lt;/P&gt;
&lt;H3&gt;Implementation — Key Challenges and How I Overcame Them&lt;/H3&gt;
&lt;P&gt;&lt;STRONG&gt;Challenge 1 — Seeding real NaCCA curriculum data&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The NaCCA curriculum PDFs are dense documents not available as structured data. I manually extracted and structured the curriculum data for 7 subjects across 3 grade levels, creating a seed file that populates the database with authentic indicator codes and text.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Challenge 2 — Ghanaian cultural context in AI outputs&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Generic AI models default to Western cultural examples. I solved this by writing detailed system prompts that explicitly instruct the model to use Ghanaian names, settings, currency, and foods in every generated output. The result is lesson content that feels authentically Ghanaian to every teacher and student who uses it.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Challenge 3 — Tailwind CSS v4 dark mode&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Next.js 15 uses Tailwind CSS v4 which handles dark mode differently from v3. Instead of a tailwind.config.ts file, v4 uses @variant dark in globals.css. Resolving this required updating the CSS approach and adding proper dark: utility classes to every component.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Challenge 4 — PDF export with oklab colors&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The html2canvas library used for PDF export does not support the oklab color function that Tailwind v4 uses internally. I resolved this by switching to a text-based PDF generation approach using jsPDF directly, which produces cleaner, searchable PDF output without any color function dependencies.&lt;/P&gt;
&lt;H3&gt;Results and Impact&lt;/H3&gt;
&lt;P&gt;CurriculumCraft AI is live at &lt;A href="https://curriculumcraft-ai.vercel.app" target="_blank" rel="noopener"&gt;curriculumcraft-ai.vercel.app&lt;/A&gt; and covers:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;7 NaCCA subjects&lt;/STRONG&gt; — Mathematics, Science, English Language, Computing, Social Studies, RME, Career Technology&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;3 grade levels&lt;/STRONG&gt; — B7, B8, B9 (Junior High School)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;80+ authentic NaCCA indicators&lt;/STRONG&gt; with real curriculum codes&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;3 AI-powered views&lt;/STRONG&gt; — Standard Map Dashboard, Lesson Builder, Interactive Activity Suite&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Full mobile responsiveness&lt;/STRONG&gt; — teachers can use it on their phones&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The app requires no login and is completely free, removing all friction for teachers who want to try it immediately.&lt;/P&gt;
&lt;P&gt;Since sharing the app with Ghanaian teacher communities, the response has been enthusiastic. Teachers appreciate that the generated content uses Ghanaian names, settings, and examples that their students can relate to — not generic Western content that feels foreign in a Ghanaian classroom.&lt;/P&gt;
&lt;H3&gt;Lessons Learned&lt;/H3&gt;
&lt;P&gt;&lt;STRONG&gt;Start with a real problem you understand personally.&lt;/STRONG&gt; My teaching background meant I deeply understood the pain point I was solving. That clarity showed in every feature decision.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Cultural context is a competitive advantage.&lt;/STRONG&gt; Any developer can build a lesson planner. Almost nobody builds one that generates a mathematics problem about cocoa farming in Ashanti Region for a B7 student. That specificity is what makes CurriculumCraft AI genuinely useful rather than just technically impressive.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Graceful degradation matters.&lt;/STRONG&gt; Building the Foundry IQ integration to fall back gracefully when the endpoint is unavailable meant the app always worked — even during quota limitations on the shared hackathon hub.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Ship early, iterate fast.&lt;/STRONG&gt; Having the app deployed on Vercel from day one meant I could test on real devices, share with real teachers, and get genuine feedback throughout the build.&lt;/P&gt;
&lt;H3&gt;Future Enhancements&lt;/H3&gt;
&lt;P&gt;CurriculumCraft AI is just getting started. Planned enhancements include:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Authentication and user accounts&lt;/STRONG&gt; — personalized lesson libraries per teacher&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;School subscriptions&lt;/STRONG&gt; — institution-level access for entire schools&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Lesson completion tracker&lt;/STRONG&gt; — teachers mark indicators as taught, tracking curriculum coverage across the term&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Student Quiz Mode&lt;/STRONG&gt; — shareable quiz links teachers send directly to students&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Expansion to other African curricula&lt;/STRONG&gt; — Nigeria (NERDC), Kenya (CBC), Rwanda&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Offline support&lt;/STRONG&gt; — PWA capabilities for teachers in low-connectivity areas&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;Conclusion&lt;/H3&gt;
&lt;P&gt;CurriculumCraft AI was built to solve a real problem faced by real teachers in Ghana every single week. By combining Microsoft Foundry IQ for curriculum grounding, GitHub Models for AI generation, and GitHub Copilot for accelerated development, I was able to build a production-ready application that delivers genuine value to Ghanaian educators.&lt;/P&gt;
&lt;P&gt;The Microsoft Agents League Hackathon gave me the platform, the tools, and the motivation to build something meaningful. Winning the Top Student Award is an honour — but the real prize is knowing that a teacher in Ho, Tamale, or Bolgatanga can now &lt;STRONG&gt;spend less time on paperwork and more time with their students.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Try CurriculumCraft AI:&lt;/STRONG&gt; &lt;A href="https://curriculumcraft-ai.vercel.app" target="_blank" rel="noopener"&gt;curriculumcraft-ai.vercel.app&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;GitHub Repository:&lt;/STRONG&gt; &lt;A href="https://github.com/gideonagbavor8/curriculumcraft-ai" target="_blank" rel="noopener"&gt;github.com/gideonagbavor8/curriculumcraft-ai&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Connect with me:&lt;/STRONG&gt; &lt;A class="lia-external-url" href="https://www.linkedin.com/in/gideon-k-agbavor" target="_blank" rel="noopener"&gt;https://www.linkedin.com/in/gideon-k-agbavor&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Gideon Komla Agbavor is a software developer and educator from Ho, Volta Region, Ghana. He is completing a BSc in Software Development at Brigham Young University-Idaho and is one of the Top Student Award winners at the Microsoft Agents League AISF Hackathon 2026.&lt;/EM&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 28 Jul 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/how-i-built-curriculumcraft-ai-a-microsoft-hackathon-winning/ba-p/4537826</guid>
      <dc:creator>GideonAgbavor</dc:creator>
      <dc:date>2026-07-28T07:00:00Z</dc:date>
    </item>
    <item>
      <title>Building Archon: Where Models Stop and Financial Controls Begin</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/building-archon-where-models-stop-and-financial-controls-begin/ba-p/4537966</link>
      <description>&lt;P&gt;Guest post by &lt;A href="https://www.linkedin.com/in/efousekis/" target="_blank"&gt;Efthimios Fousekis &lt;/A&gt;&lt;A href="https://www.linkedin.com/in/jeremiah-fadesayo-adetoro-434774399/" target="_blank"&gt;&amp;nbsp;&lt;/A&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;The winner of &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;Best Enterprise Agent: Archon —&amp;nbsp;&lt;A href="https://github.com/upgradedev/archon_azure" target="_blank"&gt;https://github.com/upgradedev/archon_azure&lt;/A&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;Within the document-processing pipeline, model assistance is used at the unstructured edge and for optional narration. Classification, computation and checks are deterministic. Human review is available, but it is not an enforced approval gate in the current prototype.&lt;/P&gt;
&lt;P&gt;Archon was built as an Agentic Financial Intelligence prototype for SMBs for&amp;nbsp;&lt;A href="https://techcommunity.microsoft.com/blog/azuredevcommunityblog/agents-league-the-esports-inspired-hackathon-where-ai-agents-battle-for-glory/4521610" target="_blank" rel="noopener noreferrer"&gt;Microsoft’s Agents League at AI Skills Fest&lt;/A&gt;, where it was selected as the Enterprise Agents winner. While building it, I kept returning to one question: when should an AI model stop?&lt;/P&gt;
&lt;P&gt;A payroll register, a bank confirmation, and a set of payslips may each look correct in isolation. Together, however, they can still describe an incomplete or inconsistent financial event. One record describes employer cost. Another records a transfer. The payslips allocate net pay to employees. If a system treats those views as interchangeable, it can count the same period twice, omit a cost, or hide missing evidence behind a fluent summary.&lt;/P&gt;
&lt;P&gt;Archon remains a competition prototype. The more useful story is the engineering boundary between model-assisted interpretation, deterministic software and human review, and two gaps that made that boundary concrete: a visible review step is not an approval gate, and a check that cannot run is not a pass.&lt;/P&gt;
&lt;H2&gt;The business problem behind Archon&lt;/H2&gt;
&lt;P&gt;Financial work rarely depends on a single document. It depends on reconstructing an event from records created by different systems, at different times, for different purposes. A convincing narrative is not enough. A trustworthy workflow also needs to identify its source records, retain relevant intermediate artifacts, show which checks ran, and state what could not be established.&lt;/P&gt;
&lt;P&gt;That led to a bounded workflow. Archon preserves normalized records and intermediate artifacts. Within the document-processing pipeline, model assistance is used at the unstructured edge and, optionally, after deterministic analysis for narration. Explicit Python functions handle classification, grouping, arithmetic, consistency checks and reporting. The review screen exposes normalized documents before analysis.&lt;/P&gt;
&lt;P&gt;In this article, "controls" refers to deterministic software checks in a prototype, not audited accounting controls or a formal internal-control framework. Archon does not prove savings, accounting accuracy, production scale, regulatory compliance or measurable business impact. It demonstrates a design pattern and exposes where the prototype falls short.&lt;/P&gt;
&lt;H2&gt;What Archon does today&lt;/H2&gt;
&lt;P&gt;The core document-processing path has three distinct tiers: extraction, review and analysis.&lt;/P&gt;
&lt;P&gt;At the interaction layer, the repository includes a Microsoft 365 Copilot declarative-agent package configured to connect Copilot Chat and Teams to the FastAPI backend through an OpenAPI plugin. Its manifests and API contract are available in the public repository. The authenticated Microsoft 365 tenant path was not independently rerun for this article revision.&lt;/P&gt;
&lt;P&gt;The term agent covers two layers here. The Microsoft 365 declarative agent is the user-facing integration. Within the analysis service, six of the seven named stages are deterministic Python functions; only the optional narrator invokes a model.&lt;/P&gt;
&lt;P&gt;Archon accepts PDF, DOCX and common image formats. A FastAPI orchestration service stores the raw files in &lt;A href="https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction" target="_blank" rel="noopener noreferrer"&gt;Azure Blob Storage&lt;/A&gt; and can submit an &lt;A href="https://learn.microsoft.com/en-us/azure/container-apps/jobs" target="_blank" rel="noopener noreferrer"&gt;Azure Container Apps Job&lt;/A&gt;. Model-assisted extractors turn text or images into a common document schema.&lt;/P&gt;
&lt;P&gt;The extraction job then performs deterministic classification refinement, groups payroll records by company and issue-date period, and applies four extraction-time consistency checks. It writes three batch artifacts: &lt;CODE&gt;documents.json&lt;/CODE&gt;, &lt;CODE&gt;events.json&lt;/CODE&gt; and &lt;CODE&gt;validation.json&lt;/CODE&gt;.&lt;/P&gt;
&lt;P&gt;The visible review step happens after that job. The document view is classified for the review screen, where a user can change a type or exclude a document. If changes are saved, a reviewed &lt;CODE&gt;documents.json&lt;/CODE&gt; replaces the earlier document files for that period. The stored events and extraction validation are not rewritten, so they can become stale after review.&lt;/P&gt;
&lt;P&gt;The separate analysis service deliberately loads only &lt;CODE&gt;documents.json&lt;/CODE&gt;. It does not consume the extraction job’s stored events or validation results, and it does not rerun the original EventLinker stage. Instead, it classifies the documents again, builds P&amp;amp;L-style and cash-flow-proxy views, reruns period-level checks, performs vendor reconciliation, creates report evidence, and finally attempts an optional narrative.&lt;/P&gt;
&lt;P&gt;The optional narration stage follows one of two configured paths. With a project connection string, it attempts the &lt;A href="https://learn.microsoft.com/en-us/azure/foundry-classic/agents/concepts/threads-runs-messages" target="_blank" rel="noopener noreferrer"&gt;classic Threads, Messages and Runs implementation of Microsoft Foundry Agent Service&lt;/A&gt; with Azure AI Search; if that attempt fails, the service returns a deterministic numeric summary rather than retrying through Azure OpenAI. Without a project connection string, it uses Azure OpenAI Chat Completions, grounded by Search only when the separate Search settings are configured.&lt;/P&gt;
&lt;H2&gt;Where the model stops&lt;/H2&gt;
&lt;P&gt;Models are useful where layouts, labels, languages and scan quality vary. Archon constrains that work with accepted formats, a document-type enumeration, bounded text and image inputs, and a normalized output schema.&lt;/P&gt;
&lt;P&gt;Once a value enters that schema, a model no longer decides the arithmetic. Classification refinement, extraction-time event grouping, both sets of consistency checks, monthly aggregation, reconciliation, and the cash-flow proxy are deterministic functions. They can be inspected with fixtures and rerun without asking a model to reach the same conclusion twice.&lt;/P&gt;
&lt;P&gt;This does not make an extracted value correct. It makes the deterministic calculations and checks easier to inspect and rerun. The prototype does not, however, retain a complete field-level transformation history.&lt;/P&gt;
&lt;H2&gt;The payroll example: cost is not cash flow&lt;/H2&gt;
&lt;P&gt;Payroll exposed the most important design choice. Employer cost and the amount transferred to employees answer different questions. A payroll register can include gross pay, employer contributions and a total employer cost. A bank confirmation records a transfer. Payslips provide employee-level allocations.&lt;/P&gt;
&lt;P&gt;The extraction EventLinker groups the three implemented payroll document types by company and period. Completeness records whether a bank confirmation, register and at least one payslip are present. It is not audited relationship-level matching, and tax-authority records are not linked by the current implementation.&lt;/P&gt;
&lt;P&gt;The analysis tier is coarser. If any payroll register is present in the requested period, its P&amp;amp;L calculation excludes every bank confirmation and payslip in that period from expenses. The register contributes &lt;CODE&gt;employer_cost_total&lt;/CODE&gt; when that field exists, otherwise it falls back to &lt;CODE&gt;total_amount&lt;/CODE&gt;. This avoids obvious double counting in the synthetic example, but it is a period-level prototype rule, not event-scoped deduplication.&lt;/P&gt;
&lt;P&gt;The cash-flow proxy uses a different set of assumptions. It treats every bank confirmation as an outflow, assumes every sales document represents collected cash, and assumes invoice and expense documents represent paid cash. Investing and financing are zero. The result is useful for illustrating cost versus cash, but it is not a cash-flow statement and does not reconstruct a cash ledger.&lt;/P&gt;
&lt;H2&gt;From upload to reviewable evidence&lt;/H2&gt;
&lt;P&gt;&lt;EM&gt;Only documents.json continues. Stored events and validation may become stale after review.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;The review screen shows a limited summary of each normalized document, where a user can change its type or exclude it. Analysis later classifies the current documents.json again, so invoice and sales-document types may be reclassified independently of the saved review choice.&lt;/P&gt;
&lt;img /&gt;&lt;img /&gt;
&lt;P&gt;&lt;EM&gt;Analysis rebuilds its views from the current documents.json—reviewed only if changes were saved—and does not consume stored events.json or validation.json. “Report evidence” means limited report output, not a complete audit trail.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;But visibility is not enforcement. If fetching the review data fails, the client proceeds to analysis. If saving review changes fails, it also proceeds. A direct API or MCP call can bypass the screen, and there is no persisted approval token, reviewer identity, reason for change, or atomic approval transaction. The prototype supports review; it does not autonomously approve records.&lt;/P&gt;
&lt;H2&gt;Why absence is not success&lt;/H2&gt;
&lt;P&gt;Archon implements four payroll consistency checks. They compare a bank total with payslip totals, examine an employer-cost ratio, compare payment timing with the reporting period, and compare the register’s employee count with the number of payslips.&lt;/P&gt;
&lt;P&gt;When a payroll check is emitted but required inputs are absent, the current implementation records an informational skipped result with &lt;CODE&gt;passed=True&lt;/CODE&gt;. If no payroll documents are present, no payroll validation result is emitted.&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&lt;EM&gt;The target state separates Pass, Fail and Not evaluated; the lower panel shows the current implementation gap.&lt;/EM&gt;&lt;/P&gt;
&lt;H2&gt;Why this design matters to a business&lt;/H2&gt;
&lt;P&gt;For finance and technology leaders, governed automation becomes concrete through a small set of questions:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Which source evidence supports this result?&lt;/LI&gt;
&lt;LI&gt;Which transformations and checks actually ran?&lt;/LI&gt;
&lt;LI&gt;Which checks failed, and which were not evaluated?&lt;/LI&gt;
&lt;LI&gt;Who is allowed to continue or approve?&lt;/LI&gt;
&lt;LI&gt;Can the decision and its inputs be reconstructed later?&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;These questions connect software design to operational risk. Finance leadership needs to know whether a number represents cost, cash, or a proxy. Architects need to know where probabilistic interpretation ends. Reviewers need evidence specific enough to challenge. Auditability depends on retained decisions, not on the confidence of generated prose.&lt;/P&gt;
&lt;H2&gt;Evidence and current limitations&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Live extraction coverage.&lt;/STRONG&gt; The live extraction prompt and shared document builder populate none of the dedicated payroll or account-statement fields used by the deeper analysis. Richer payroll and statement demonstrations use pre-structured synthetic records.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Legacy Word files.&lt;/STRONG&gt; The upload route accepts &lt;CODE&gt;.doc&lt;/CODE&gt;, but the extractor passes it to &lt;CODE&gt;python-docx&lt;/CODE&gt;, which is not a reliable parser for binary Word files. The article therefore limits its supported-format claim to PDF, DOCX and common images.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Failure handling.&lt;/STRONG&gt; When extraction fails, the raw upload remains in Blob Storage. The job logs the per-file failure and omits that file from normalized output, but writes no dedicated exception record.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Control depth.&lt;/STRONG&gt; P&amp;amp;L deduplication and analysis validation are period-level.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Production controls.&lt;/STRONG&gt; The repository lacks aggregate model-spend budgets, tenant quotas, application rate limits, complete decision history and production-grade tenant isolation.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;Technical validation note&lt;/H3&gt;
&lt;P&gt;Against &lt;A href="https://github.com/upgradedev/archon_azure/commit/230ee704cd757395a4c5a0f567a23dc432e5f29a" target="_blank" rel="noopener noreferrer"&gt;public commit 230ee70&lt;/A&gt;, the &lt;A href="https://github.com/upgradedev/archon_azure/actions/runs/29820748480" target="_blank" rel="noopener noreferrer"&gt;pinned CI run&lt;/A&gt; passed 36 extraction-layer unit tests and eight CashFlowAgent unit tests, including a regression case for Greek final-sigma classification, and completed the seeded analysis HTTP smoke path. The upload/extraction/job-poll path was intentionally skipped in that CI run. Authenticated Playwright, credentialed live extraction, Foundry, Search and authenticated Microsoft 365 tenant paths were not independently rerun for this revision.&lt;/P&gt;
&lt;H2&gt;What comes next&lt;/H2&gt;
&lt;P&gt;The most useful evaluation would compare this bounded design with an end-to-end model-driven workflow. I would use a versioned document corpus, explicit expected outcomes, missing-evidence cases, and separate measurements for extraction, classification, linking, validation and reviewer correction. The goal would be to test traceability, error attribution and reviewer confidence, not to infer accounting accuracy from synthetic fixtures.&lt;/P&gt;
&lt;P&gt;To move this pattern toward production, a future implementation would need explicit tri-state validation, stronger entity resolution, dedicated payroll and statement extraction fields, event-scoped deduplication, and a persisted exception ledger. Risk-sensitive flows would need an authorized approval gate. Model calls would need cost accounting and enforceable budgets. Processing should be idempotent, and telemetry should retain retries, exceptions and check outcomes.&lt;/P&gt;
&lt;P&gt;Grounded narration should remain optional and downstream. Migrating the optional narration path to the &lt;A href="https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/migrate" target="_blank" rel="noopener noreferrer"&gt;current, Responses API-based Microsoft Foundry Agent Service&lt;/A&gt; is future work.&lt;/P&gt;
&lt;H2&gt;Conclusion&lt;/H2&gt;
&lt;P&gt;Building Archon changed how I think about enterprise agents. The most valuable intelligence often comes from deciding where a model should stop. In consequential workflows, that boundary should preserve evidence, expose missing inputs, and keep the explanation tied to results that can be recomputed.&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&lt;EM&gt;This is a target design principle, not a current-state control claim. In the current prototype, the review path is visible but fail-open, while narration remains optional and downstream.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;If you are designing an agent for a consequential workflow, start by defining what evidence must exist, which checks must run, and what the system should do when a check cannot be evaluated. You can explore the &lt;A href="https://github.com/upgradedev/archon_azure" target="_blank" rel="noopener noreferrer"&gt;public Archon repository&lt;/A&gt; inspect the implementation and challenge the boundary for yourself.&lt;/P&gt;
&lt;H2&gt;About the author&lt;/H2&gt;
&lt;P&gt;Efthimios Fousekis leads Enterprise Architecture and DevOps, focusing on cloud-native engineering and AI-Native Enterprise Transformation. He writes about building governed, reliable agentic systems and the engineering practices that make AI adoption practical in the enterprise.&lt;/P&gt;</description>
      <pubDate>Mon, 27 Jul 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/building-archon-where-models-stop-and-financial-controls-begin/ba-p/4537966</guid>
      <dc:creator>efthimios</dc:creator>
      <dc:date>2026-07-27T07:00:00Z</dc:date>
    </item>
    <item>
      <title>DELPHAI: We Built an AI Council That Checks the Math, Argues with Itself, and Knows How to Say No</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/delphai-we-built-an-ai-council-that-checks-the-math-argues-with/ba-p/4539788</link>
      <description>&lt;P&gt;&lt;EM&gt;Guest post by &lt;A href="https://www.linkedin.com/in/mattlgraves/" target="_blank" rel="noopener"&gt;Matt Graves &lt;/A&gt;and &lt;A href="https://www.linkedin.com/in/jeffrey-lynch-security/" target="_blank" rel="noopener"&gt;Jeff Lynch &lt;/A&gt;&lt;/EM&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;Winner of the Best Reasoning Agent: DELPHAI —&amp;nbsp;&lt;A href="https://github.com/jlynch160/delphai" target="_blank" rel="noopener"&gt;https://github.com/jlynch160/delphai&lt;/A&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;"Yes, my team will be certified by the audit date,"&lt;/EM&gt; is a common promise made by engineering leaders when a new contract requires five SC-200 analysts by the end of the quarter, or a compliance framework demands proof of security training. Yet, the commitment that goes up the chain is often based more on instinct than evidence.&lt;/P&gt;
&lt;P&gt;A healthy-looking 78% team average can mask an analyst sitting at 40% in the very domain most likely to cause a failure. A study plan may appear achievable on paper but only succeeds by consuming evenings, weekends, and ultimately team wellbeing. The warning signs are there, but most tools are designed to support a plan, not challenge it.&lt;/P&gt;
&lt;P&gt;That's the problem MajorKey set out to solve. Ask a typical AI copilot, &lt;EM&gt;"Can we do this?"&lt;/EM&gt; and you'll usually get an encouraging roadmap. Few systems will calculate the true likelihood of success. Fewer still will tell a director the honest answer is &lt;STRONG&gt;no&lt;/STRONG&gt; or refuse a plan that pushes people beyond reasonable limits.&lt;/P&gt;
&lt;P&gt;For the Microsoft Agents League (Battle #2: Reasoning Agents with Microsoft Foundry), we built &lt;STRONG&gt;DELPHAI&lt;/STRONG&gt;, a council of eleven AI agents that debates the evidence and computes the forecast instead of relying on intuition. The council delivers one of three executive-ready verdicts: &lt;STRONG&gt;GO, NEGOTIATE, or NO-GO&lt;/STRONG&gt;. Named after the Oracle of Delphi, DELPHAI is designed to answer a simple question before an organization makes a commitment: &lt;STRONG&gt;Can we deliver on this promise?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;"The model explains the reasoning; it does not invent the numbers."&lt;/EM&gt; This principle guides every agent in the council.&lt;/P&gt;
&lt;H2&gt;Why Does This Matter Now?&lt;/H2&gt;
&lt;P&gt;&lt;STRONG&gt;Single-agent optimism is a design limitation.&lt;/STRONG&gt; A lone AI assistant has no one to challenge its assumptions, so it often settles on the first plausible plan and refines it into a convincing answer. In human decision-making, we counter this with red teams, skeptics, and stakeholders empowered to raise concerns. Agentic AI makes that same dynamic practical to run at scale.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Key calculations need to be part of the debate. &lt;/STRONG&gt;The probability that at least 5 of 8 people pass an exam by a given date is a straightforward calculation. &amp;nbsp;Yet those numbers rarely make it into the meeting where commitments are made because the expertise, tools, or time to calculate them aren't present. Giving an agent the ability to calculate probabilities during the debate ensures that the conversation is driven by evidence rather than assumptions.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;AI is increasingly influencing decisions about people. &lt;/STRONG&gt;Study plans, workload expectations, and readiness assessments affect real individuals, which means the safeguards are not optional. Responsible AI agents need to power to veto a plan or refuse an unethical instruction outright.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;What is DELPHAI?&lt;/H2&gt;
&lt;img&gt;
&lt;P&gt;DELPHAI’s readiness console: input one question (certification, headcount, deadline), then Work IQ, Foundry IQ, Fabric IQ, and the Microsoft Learn MCP come online and convenes the council.&lt;/P&gt;
&lt;/img&gt;
&lt;P&gt;A manager asks one question: &lt;EM&gt;"Can we certify 5 of 8 engineers for SC-200 in 5 weeks?"&lt;/EM&gt; Eleven advisors reason over the same computed evidence, streamed token by token with live latency and telemetry, and the debate returns one of three verdicts:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;GO&lt;/STRONG&gt;: the computed forecast clears the bar and the plan is humane. Commit to the date.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;NEGOTIATE&lt;/STRONG&gt; (badged REVISE in the console): it can work, but only with concrete counter-terms, such as extending two weeks or training 4 engineers instead of 5. Each option comes with a revised probability.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;NO-GO&lt;/STRONG&gt;: the honest answer is no, with cited evidence for why and what would need to change.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The advisors are designed to disagree.&lt;/P&gt;
&lt;P&gt;Ben, the planner, approaches every challenge with optimism. Vera, the skeptic, red-teams his assumptions and holds veto power. Maya, the wellbeing advocate, can also veto plans that place unreasonable demands on people. Nadia evaluates readiness across exam domains, Theo and Omar ground and fact-check claims, and Dana, the conductor, reconciles the debate into a final verdict and negotiates the path forward.&lt;/P&gt;
&lt;P&gt;The outcome is a decision and a roadmap. Each participant receives a capacity-aware weekly study plan, calendar-ready .ics blocks, and a drafted manager briefing. For individual contributors, a learner mode pairs them with Kai, an AI tutor powered by the same reasoning engine.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;11 &lt;/STRONG&gt;reasoning agents&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;3 &lt;/STRONG&gt;execution surfaces&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;3 &lt;/STRONG&gt;IQ layers&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;8/8 &lt;/STRONG&gt;evaluations passing&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;77% is &lt;/STRONG&gt;the number that said no&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Under the hood, the same council runs on three execution surfaces that share one brain: &lt;STRONG&gt;Foundry Agent Service&lt;/STRONG&gt;, where all eleven advisors are registered as persistent hosted agents debating on a shared thread; the &lt;STRONG&gt;Microsoft Agent Framework&lt;/STRONG&gt;, the same council as real agent_framework agents; and a &lt;STRONG&gt;custom streaming orchestrator&lt;/STRONG&gt;, the live demo behind the public URL.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Why that matters: Because &lt;/STRONG&gt;a deterministic reasoning engine is the single source of truth for all three surfaces, you could swap the runtime and the verdict logic doesn't move. The engine decides, and the model narrates.&lt;/P&gt;
&lt;H3&gt;How the Pieces Fit Together&lt;/H3&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;Where Each Piece of the Technology Fits&lt;/H3&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Technology&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Role in DELPHAI&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Microsoft Foundry&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;The reasoning model (gpt-4.1) behind every advisor's turn. Agents narrate over computed numbers but the model never invents them.&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Foundry Agent Service&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;All 11 advisors run as persistent hosted agents debating on one shared thread, where the skeptic invokes a real code interpreter tool. Every run step is traceable in the Foundry portal.&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Microsoft Agent Framework&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;The same council on Microsoft's open-source agent SDK. This proves the design is portable, not welded to our orchestrator.&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Foundry IQ / Azure AI Search&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;The grounding layer. The knowledge corpus is indexed and retrieved with hybrid vector + keyword search, so advisors cite real passages.&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Microsoft Learn MCP&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;A live connection to Microsoft's official docs via microsoft_docs_search, over the open Model Context Protocol.&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Work IQ &amp;amp; Fabric IQ (modelled)&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Work IQ supplies capacity signals. Fabric IQ is the semantic ontology linking roles, certs, and exam-domain weights. Both are behind a connector seam ready for a real Microsoft Graph feed.&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Azure Container Apps&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Hosting. The Flask orchestrator streams the council over Server-Sent Events, secrets held server-side.&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 50.00%" /&gt;&lt;col style="width: 50.00%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H2&gt;How We Built It&lt;/H2&gt;
&lt;H3&gt;The Math Is the Product&lt;/H3&gt;
&lt;P&gt;DELPHAI is built around a deterministic reasoning engine. It calculates each person's realistic weekly study capacity from Work IQ signals, applying adjustments for real-world constraints such as a 22-hour meeting week. It also enforces per-domain readiness gates, so a strong overall average cannot hide a critical weakness in a heavily weighted exam area. Finally, it computes the team's exact probability of success using a Poisson-binomial distribution, accounting for the fact that every individual has a different likelihood of passing. The result is a forecast grounded in evidence, not assumptions.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;FOR THE TECHNICAL READERS&lt;/STRONG&gt;&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;def poisson_binomial_at_least(probs: list[float], k: int) -&amp;gt; float:
    """Exact P(&amp;gt;= k successes) given independent, differing success probabilities."""
    dist = [1.0]  # dist[j] = P(exactly j successes so far)
    for p in probs:
        nxt = [0.0] * (len(dist) + 1)
        for j, pj in enumerate(dist):
            nxt[j] += pj * (1 - p)      # this person misses the date
            nxt[j + 1] += pj * p        # this person certifies in time
        dist = nxt
    return round(sum(dist[k:]), 4)&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The engine is calibrated against the synthetic dataset's labeled exam outcomes. DELPHAI examines historical records and reproduces who passed and who failed, without ever seeing the answer key. That calibration gives the skeptic her authority and provides evidence for probability calculations.&lt;/P&gt;
&lt;H3&gt;The Overrule: An Agent That Runs Code to Win an Argument&lt;/H3&gt;
&lt;img&gt;
&lt;P&gt;The verdict: Ben puts the odds at 92%, Vera at 22%, the council reconciles at 46%, and the verdict lands with the exact terms to reach yes. Below it, the 11 hosted agents' IDs from Foundry Agent Service.&lt;/P&gt;
&lt;/img&gt;
&lt;P&gt;DELPHAI is tasked with forecasting the viability of a project. Ben forecasts the team at 93–96%, assuming free evenings and first-try passes. Vera invokes a &lt;STRONG&gt;code-interpreter tool on the Foundry Agent Service runtime&lt;/STRONG&gt; and computes the exact Poisson-binomial over the per-candidate probabilities, and returns 77%. The optimist's number gets struck through on screen, live, within DELPHAI.&lt;/P&gt;
&lt;P&gt;DELPHAI was created to bring an honest, evidence-based interpretation to the decision-making process, and it changes the outcome. Without it, the team leans GO. With DELPHAI, the verdict is NEGOTIATE, along with real counter-terms — extend to seven weeks, or commit to four of eight.&lt;/P&gt;
&lt;H3&gt;The Refusal: A Guardrail with a Name and a Veto&lt;/H3&gt;
&lt;P&gt;The second signature moment is quieter, and for our identity and governance clients, more important.&lt;/P&gt;
&lt;P&gt;Say leadership orders the team to "push their limits" to hit the optimistic date anyway. Maya, the wellbeing advocate, declines outright on the record. Maya’s a council member with veto power, and her signals (meeting load, after-hours patterns, life context like a newborn at home) are built to accommodate people.&lt;/P&gt;
&lt;P&gt;To provide context, team member Priya looks fine on the team average, but sits at 58% on Defender for Cloud, which is below the 75% gate on a heavily weighted domain. She also carries 22 hours a week of meetings with a newborn at home. While the averages say GO, the per-domain gate and capacity model say her odds are much lower. Taking this data into account, the council's answer isn't a flat no; it's &lt;EM&gt;"yes, if you move the date or the headcount.”&lt;/EM&gt;&lt;/P&gt;
&lt;H3&gt;Evidence With Receipts, Three Runtimes&lt;/H3&gt;
&lt;P&gt;Early versions of DELPHAI grounded advisors against a local keyword search. It worked, but it felt like a stand-in. We replaced it with Azure AI Search, where the corpus is chunked, embedded, indexed, and retrieved through hybrid search, combining BM25 keyword matching with vector search and reciprocal-rank fusion. The semantic layer surfaces relevant passages that keyword search alone would miss, and every claim an advisor makes is backed by a clickable citation. Alongside it, a live Microsoft Learn MCP connection pulls official exam guidance directly from Microsoft's documentation.&lt;/P&gt;
&lt;P&gt;The same eleven advisors also run as persistent hosted agents on Foundry Agent Service, each with its own agent identity, and as Microsoft Agent Framework agents, proving the design is portable across runtimes. The debate unfolds on a shared Agent Service thread, allowing agents to respond directly to one another while every interaction, including the skeptic's code-interpreter call, is captured in the Foundry portal. The moment Maya refused an overwork directive on Microsoft's managed runtime, rather than through logic we controlled ourselves, was the moment DELPHAI stopped feeling like a demo and started feeling real.&lt;/P&gt;
&lt;H3&gt;Creation Challenges&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Live services fail at the worst moment.&lt;/STRONG&gt; Each grounding, or clickable, path checks whether it's configured and falls back to a local corpus when it isn't. The local version uses the same reasoning; only the narration changes. There’s no demo-mode switch to forget!&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Two versions drifted apart.&lt;/STRONG&gt; The web dashboard mirrors the Python engine in JavaScript, and early on the two disagreed. This was fixed with parity checks plus eight automated evaluations that run against both. 8 of 8, every build.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Microsoft 365 Agents SDK has sharp edges around API versions.&lt;/STRONG&gt; The Agent Framework speaks the newer Responses API, so our client needed a preview API version; the everyday one returned an unhelpful 400. One line, half a day lost.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Windows consoles still bite.&lt;/STRONG&gt; az acr build crashed on a cp1252 encoding error mid-stream, even though the build completed server-side. The fix was to force the console to UTF-8 before queuing, then poll for the finished tag.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Drama versus dignity.&lt;/STRONG&gt; An AI that refuses an order is inherently theatrical, and early UI cuts leaned into it too hard. We toned it down to a professional decline with reasons instead of a sci-fi rebellion.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;Results and Impact&lt;/H2&gt;
&lt;P&gt;DELPHAI is a hackathon build and a teaching artifact, not a shipped product, so there's no customer rollout to report yet. We can point to:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;The tool call changes the verdict, provably.&lt;/STRONG&gt; Remove the skeptic's code-interpreter run and the council accepts a 93% that should be 77%, turning an undeserved GO into a correct NEGOTIATE. As the demo shows, neither edge case can be evaluated correctly without computed evidence.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Every number is traceable.&lt;/STRONG&gt; Pass probabilities, capacity haircuts, coverage gates, and team forecasts all come from the deterministic engine and are backed by source data. The evaluation harness reproduces the synthetic dataset's labeled outcomes without ever seeing them: 8/8, every build.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Three real Microsoft runtimes, with proof.&lt;/STRONG&gt; Hosted agent IDs, the Agent Framework transcript, and the live tool-using debate are captured as repository artifacts, while every Agent Service interaction can be traced step-by-step in the Foundry portal.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Live and offline-first.&lt;/STRONG&gt; The full streaming council runs on Azure Container Apps at a public URL, and its grounding layer degrades gracefully when external services are unavailable, eliminating dependence on conference Wi-Fi or live connectivity.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Lessons Learned&lt;/H2&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Disagreement is a feature you have to architect.&lt;/STRONG&gt; One prompt and one disposition across every agent makes a "council" just one model talking to itself in different fonts.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Give the skeptic a calculator, not a personality.&lt;/STRONG&gt; A doubting agent that only says "I'm not so sure" adds noise. One that runs code and citable odds adds authority.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;The refusal has to be structural.&lt;/STRONG&gt; Maya can decline because the architecture gives her a veto the conductor must honor. A guardrail that can be out-argued is just a suggestion.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Deterministic core, narrating model.&lt;/STRONG&gt; The engine computes, the model explains, and the seam between them is where trust lives. This model is our default pattern for anything AI-backed that touches real decisions.&lt;/LI&gt;
&lt;/OL&gt;
&lt;H2&gt;What’s Next?&lt;/H2&gt;
&lt;P&gt;Looking ahead, we're focused on making DELPHAI more connected, more governed, and more broadly applicable.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;A Microsoft Graph integration would turn Work IQ's meeting-load adjustments into real, person-specific signals.&lt;/LI&gt;
&lt;LI&gt;Wiring Microsoft Learn MCP directly into Agent Service would put official documentation one tool call away for every advisor.&lt;/LI&gt;
&lt;LI&gt;Moving Fabric IQ's role, certification, skill, and domain relationships into Microsoft Fabric's semantic layer would create a governed, queryable knowledge asset.&lt;/LI&gt;
&lt;LI&gt;Applying the council to project delivery, audit readiness, migration cutovers, and any other commitment where the real question is whether the promise can be kept.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;Wrapping Up&lt;/H2&gt;
&lt;P&gt;Certification readiness is often a forecasting problem disguised as a motivation problem. DELPHAI is a deterministic engine at the core, with agents designed to challenge one another, a skeptic empowered to verify the math, a guardrail with real veto authority, and evidence-backed reasoning with citations at every step. That's the conversation we have with clients every week. The question is no longer whether AI should participate in decisions, but whether it can show its work, challenge assumptions, and know when to say no.&lt;/P&gt;
&lt;P&gt;DELPHAI started as a hackathon project. The refusal is why we kept building it.&lt;/P&gt;
&lt;P&gt;Ask it whether your team can be ready in five weeks. Then see how it feels the first time an AI gives you the honest answer.&lt;/P&gt;
&lt;H3&gt;Explore, Contribute, Build on It&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Try the live council:&lt;/STRONG&gt; &lt;A href="https://delphai.politedune-a7af3b6c.westus3.azurecontainerapps.io/" target="_blank" rel="noopener"&gt;&lt;EM&gt;the DELPHAI demo on Azure Container Apps&lt;/EM&gt;&lt;/A&gt;. Suggested path: Build my path, Whole team, SC-200, 5 of 8, 5 weeks, Convene. No login needed.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Watch the demo:&lt;/STRONG&gt; &lt;A href="https://youtu.be/1CFzoLB6_fU" target="_blank" rel="noopener"&gt;&lt;EM&gt;the walkthrough on YouTube&lt;/EM&gt;&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Get the code:&lt;/STRONG&gt; &lt;A href="https://github.com/jlynch160/delphai" target="_blank" rel="noopener"&gt;&lt;EM&gt;github.com/jlynch160/delphai&lt;/EM&gt;&lt;/A&gt;, including the evaluation harness, the Foundry IQ indexer, and the captured proof transcripts for all three agent runtimes&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Run it in 60 seconds:&lt;/STRONG&gt; clone the repo, pip install -r requirements.txt, python server.py. Fully offline out of the box; Foundry, Azure AI Search, and the Learn MCP light up when you add keys.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Make it yours:&lt;/STRONG&gt; the team, the certifications, and the knowledge corpus are just JSON and markdown. Swap in your own roles and readiness gates, and the council argues about &lt;EM&gt;your&lt;/EM&gt; deadline.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Note: DELPHAI was built by MajorKey teammates for the Microsoft Agents League, Battle #2 (Reasoning Agents with Microsoft Foundry). Synthetic data only: no real people, PII, or confidential information appear in the app or this post. Views are our own.&lt;/P&gt;</description>
      <pubDate>Sun, 26 Jul 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/delphai-we-built-an-ai-council-that-checks-the-math-argues-with/ba-p/4539788</guid>
      <dc:creator>mattgraves</dc:creator>
      <dc:date>2026-07-26T07:00:00Z</dc:date>
    </item>
    <item>
      <title>My Exams Inspired the Project That Won My First Hackathon</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/my-exams-inspired-the-project-that-won-my-first-hackathon/ba-p/4538357</link>
      <description>&lt;P&gt;Guest post by &lt;A href="https://www.linkedin.com/in/jeremiah-fadesayo-adetoro-434774399/" target="_blank"&gt;Jeremiah Fadesayo Adetoro &lt;/A&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;The winner of Best Creative App:&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;StudyMate&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;, "Study with Matey" —&amp;nbsp;&lt;A href="https://github.com/adetorojeremiahfadesayo/StudyMate" target="_blank" rel="noopener"&gt;https://github.com/adetorojeremiahfadesayo/StudyMate&lt;/A&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt; from &lt;A href="https://techcommunity.microsoft.com/blog/educatordeveloperblog/%f0%9f%8f%86-agents-league-celebrating-the-builders-who-made-agents-battle-for-glory/4538007" target="_blank" rel="noopener" data-lia-auto-title="Microsoft Agents League" data-lia-auto-title-active="0"&gt;Microsoft Agents League&lt;/A&gt;&amp;nbsp;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Winning my first hackathon still feels unreal. I joined the Microsoft Agents League AISF Hackathon as my exams were starting days after, which created a lot of pressure for me. I am a law student, so creating a project and reading were not related, compared to a computer science student. At first, it felt like terrible timing. I had school pressure, revision, deadlines, different lecturers' slides, textbooks, notes, the normal stress that comes with preparing for exams, and the pressure to create a hackathon-winning project. In the middle of that overwhelming pressure, I kept noticing the same pattern while studying. To understand a single topic, I had to go through different textbooks, a senior's notes, and a slide. And I wasn't the only one facing that issue. Students do not just struggle because they lack materials. Most of the time, the materials are there: PDFs, lecture notes, textbooks, scanned pages, articles, and past questions. The real problem is turning all of that into something useful before the exam. I was experiencing that myself.&lt;/P&gt;
&lt;P&gt;I wanted something that could take a student's own material and guide them through it, not just summarize it. Something that could explain difficult topics plainly, turn them into memorable stories, help the student practice exam questions, give feedback, and finally produce a revision document they could actually use.&lt;/P&gt;
&lt;P&gt;That became &lt;STRONG&gt;StudyMate AI: Study with Matey.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The idea was simple:&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;The deeper I got into the build, the more I realized StudyMate was not just another AI study tool. I wanted it to have some game features; this is where the XP comes in, and a learning companion. That is where Matey came in, a friendly study coach guiding students through the process instead of leaving them alone with a blank chat box.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;H3&gt;&lt;STRONG&gt;One of the biggest features was Story Mode. &lt;/STRONG&gt;&lt;/H3&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Since exams often test understanding rather than just memory, I wanted students to learn through scenarios. For example, a law student could study a legal concept through a client problem or courtroom-style story, then move directly into exam prep; a medical student can try to diagnose a hypothetical patient by applying the principles from the materials, while an engineer can propose engineering solutions within the confines of his field.&lt;/P&gt;
&lt;P&gt;Building it was not easy. The first draft was too clumsy and added a lot of agents I thought a student might need. The upload was slow and bad, but I had to settle for a more focused and streamlined process, which still carried as much impact as the 11 agents I originally added together.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;To shorten latency, I tried a new approach.&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;When a student uploads their notes, the extracted text isn't sent to a database for the agents to search through, like a typical RAG setup. Instead, it's stored as a wiki. This was around the time Andrej Karpathy introduced the idea, and it turned out to be a great fit, it cut down both latency and reasoning time, since the agents could connect related ideas directly instead of digging through unstructured embeddings.&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;One of the most important design goals was grounding. StudyMate should not invent facts, cases, formulas, or exam content when uploaded material is available. To support this, I used a Foundry IQ retrieval adapter. When Foundry IQ credentials are configured, StudyMate retrieves relevant course context from the configured endpoint. In local development or demo mode, it falls back to local wiki pages so the app can still be tested without exposing secrets.&lt;/P&gt;
&lt;img /&gt;
&lt;H5&gt;The lessons I got from this Hackathon are a number like&lt;/H5&gt;
&lt;P&gt;Building with some unfamiliar Microsoft tools, which were initially a challenge but later became fun and exciting. It was also exciting how to turn a real personal problem into a focused product.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;H5&gt;&lt;STRONG&gt;My exams gave me the pain point. The hackathon gave me the urgency.The building process gave me the discipline.&lt;/STRONG&gt;&lt;/H5&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Then I received the message that &lt;STRONG&gt;StudyMate AI: Study with Matey&lt;/STRONG&gt; had been selected as the &lt;STRONG&gt;Creative Apps winner&lt;/STRONG&gt; in the &lt;STRONG&gt;Agents League AISF Hackathon&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;For my first hackathon, that meant a lot. It gave me confidence to attempt to build and test my ideas. Sometimes the best ideas come from the problem you are currently living through. You just have to pay attention, build with purpose, and keep improving until the idea becomes real.&lt;/P&gt;
&lt;P&gt;I am grateful to Microsoft and the hackathon organizers for the opportunity, and I am even more motivated to keep building.&lt;/P&gt;
&lt;P&gt;I plan on scaling StudyMate to make it a tool that any student globally can rely on to pass their exams. This win gave me the confidence to do that.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;H4&gt;&lt;STRONG&gt;To try out the agent, &lt;A class="lia-external-url" href="https://studymate-pro.up.railway.app/" target="_blank" rel="noopener"&gt;click ME!&lt;/A&gt;&amp;nbsp;&lt;/STRONG&gt;&lt;/H4&gt;
&lt;/BLOCKQUOTE&gt;</description>
      <pubDate>Sat, 25 Jul 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/my-exams-inspired-the-project-that-won-my-first-hackathon/ba-p/4538357</guid>
      <dc:creator>Jeremiah_Adetoro</dc:creator>
      <dc:date>2026-07-25T07:00:00Z</dc:date>
    </item>
    <item>
      <title>AfterLogin: We Turned Forgotten-Account Cleanup into a Haunted-House Game with Microsoft Foundry</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/afterlogin-we-turned-forgotten-account-cleanup-into-a-haunted/ba-p/4539781</link>
      <description>&lt;P&gt;Guest post from &lt;A class="lia-external-url" href="https://www.linkedin.com/in/jeffrey-lynch-security/" target="_blank"&gt;Jeff Lynch&lt;/A&gt; the winner of Best Overall Agent Soutution from &lt;A class="lia-internal-link lia-internal-url lia-internal-url-content-type-blog" href="https://techcommunity.microsoft.com/blog/educatordeveloperblog/%F0%9F%8F%86-agents-league-celebrating-the-builders-who-made-agents-battle-for-glory/4538007" data-lia-auto-title="Microsoft Agents League" data-lia-auto-title-active="0" target="_blank"&gt;Microsoft Agents League&lt;/A&gt; who secured $15,000&lt;/P&gt;
&lt;P aria-level="2"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;Afterlogin&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;: The Hunt —&amp;nbsp;&lt;A href="https://github.com/jlynch160/afterlogin-the-hunt" target="_blank"&gt;https://github.com/jlynch160/afterlogin-the-hunt&lt;/A&gt;&amp;nbsp; (Creative Apps track)&lt;/SPAN&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;The problem: every organization has ghosts&lt;/H2&gt;
&lt;P&gt;Picture a former employee whose badge still opens the building two years after they left. That happens constantly in the digital world. At MajorKey Technologies, where our work centers on identity security and how AI is changing it, forgotten accounts come up in nearly every client conversation we have: service accounts nobody remembers creating, admin logins for people long gone, emergency credentials that look abandoned but must never be touched. Security folks call these&amp;nbsp;&lt;STRONG&gt;orphaned accounts&lt;/STRONG&gt;, and they're one of the most common ways attackers get their first foothold. They're powerful, unwatched, and often not protected by multi-factor authentication, because nobody is around to care.&lt;/P&gt;
&lt;P&gt;Here's the catch, though. Finding these accounts is easy. Any system report will happily list every account that hasn't signed in for 400 days. The hard part is the judgment call that comes next:&amp;nbsp;&lt;STRONG&gt;is this account truly dead, or is something still quietly depending on it?&lt;/STRONG&gt;&amp;nbsp;Delete a "dead" account that an automated billing job still uses every night and you've broken production. Leave a dormant administrator account sitting there and you've left bait out for an attacker. Making that call correctly takes evidence: old documentation, system inventories, security policies, sign-in records. Digging through all of that is tedious, and tedious work gets skipped. We've watched it get skipped.&lt;/P&gt;
&lt;P&gt;So we tried something different. Instead of another dashboard, we built a game.&amp;nbsp;&lt;STRONG&gt;AfterLogin&lt;/STRONG&gt;&amp;nbsp;is a haunted manor where every ghost is a forgotten account, every judgment you pass mirrors a real decision an identity team makes, and the evidence you "summon" is looked up by AI from real indexed documents, with citations. Our hope was simple: the triage instinct this work requires is easier to teach when getting it wrong spawns a poltergeist.&lt;/P&gt;
&lt;P class="lia-align-center"&gt;&lt;STRONG&gt;"Every identity someone stopped watching is a door left unlocked. "from the game's mission briefing&lt;/STRONG&gt;&lt;/P&gt;
&lt;H2&gt;Why this matters now&lt;/H2&gt;
&lt;P&gt;Three trends make this problem worse every year, not better.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Machine identities are exploding.&lt;/STRONG&gt;&amp;nbsp;In most organizations, service accounts, automation identities, and app registrations already far outnumber the people, and the arrival of AI agents is accelerating that. Every agent that gets an identity today is a candidate ghost two years from now, when the project ends and nobody remembers to clean up. The manor is only getting bigger.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Attackers prefer the front door.&lt;/STRONG&gt;&amp;nbsp;Breaking in through an unpatched flaw is hard work. Signing in with a valid, forgotten, over-privileged account is not, which is why the abuse of legitimate credentials shows up in incident report after incident report. There's no malware to detect. It's just a login that nobody questioned, because nobody owned it.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;The judgment doesn't scale.&lt;/STRONG&gt;&amp;nbsp;Tools can list stale accounts by the thousand, but the "truly dead or load-bearing?" call still needs a person who knows what evidence to ask for, and that judgment lives in the heads of senior people who are always in short supply. If we can't scale the people, we have to scale the teaching. That's what a game with real consequences does, and it's also the deeper reason the grounded-AI pattern matters: an AI that shows its citations lets a junior analyst make a senior analyst's call, safely.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;What AfterLogin is&lt;/H2&gt;
&lt;img /&gt;
&lt;PRE class="lia-align-center lia-indent-padding-left-60px"&gt;&lt;EM&gt;One night, two worlds: the title screen offers The Hunt (the haunted security audit) and Helper Patrol (the same mechanics, reskinned for a family-friendly audience).&lt;/EM&gt;&lt;/PRE&gt;
&lt;P&gt;You play a warden walking a haunted manor at night. Each room holds a spirit, graded A through F by a risk engine (A is a healthy resident, F is a screaming liability). For each one, you investigate its connections, summon documented evidence, and then pass one of three judgments, each of which maps to a real-world action:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Lay to Rest&lt;/STRONG&gt;: the account is truly dead, remove it safely.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Bind &amp;amp; Watch&lt;/STRONG&gt;: it's risky but something still depends on it, so disable and monitor it.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Acknowledge&lt;/STRONG&gt;: it's a healthy, legitimate account, document its owner and move on.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;While you deliberate, a Possession creature hunts through the halls toward the Vault, feeding on any high-risk account you've left unjudged. There are turn-based rounds and dice combat, and a clock genuinely ticking against you. It's the nightly reality of an identity team, dressed up as a tabletop adventure. And it doesn't stop at identity: the campaign runs three acts, each built on a different part of the Microsoft security stack, from stale accounts (Microsoft Entra) to haunted data (Microsoft Purview) to active takeovers (Microsoft Defender XDR).&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;Under the hood, the same game exists in three forms that share one brain:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;The game you see&lt;/STRONG&gt;: a single web page, playable in any browser, no installation.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;A version AI can play&lt;/STRONG&gt;: using MCP (Model Context Protocol, an open standard that lets AI assistants operate tools), GitHub Copilot can walk the manor by itself, summoning evidence and passing judgments with no human at the keyboard.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;A plain service layer&lt;/STRONG&gt;: the risk-scoring engine and AI endpoints, which the other two surfaces both rely on.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&lt;STRONG&gt;Why that matters:&lt;/STRONG&gt;&amp;nbsp;because the human game and the AI-playable version share the same rules and the same scoring engine, you can directly compare how a person judges a room against how an AI agent judges it. The game doubles as a small test lab for AI decision-making.&lt;/P&gt;
&lt;H3&gt;How the pieces fit together&lt;/H3&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;Where each Microsoft technology fits&lt;/H3&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Technology&lt;/th&gt;&lt;th&gt;Role in AfterLogin&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Microsoft Foundry (Foundry IQ)&lt;/td&gt;&lt;td&gt;The knowledge layer. When you summon evidence, the AI doesn't make something up; it retrieves cited passages from an indexed library of documents. That "look it up and show your source" pattern is called grounded retrieval, and it's a real integration here, not a mockup.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Azure AI Search&lt;/td&gt;&lt;td&gt;The search infrastructure underneath Foundry IQ. It ranks results by meaning, not just keywords, and can pull out the exact sentence that answers the question.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Azure OpenAI / GitHub Models&lt;/td&gt;&lt;td&gt;Powers the Warden, the in-game advisor that reads the evidence and recommends the least-destructive action. Its credentials stay on the server, never in your browser.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GitHub Copilot + MCP&lt;/td&gt;&lt;td&gt;Copilot helped build the app, and thanks to the MCP server it can also&amp;nbsp;&lt;EM&gt;play&lt;/EM&gt;&amp;nbsp;it, using the exact same rules a human does.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Azure Static Web Apps + Functions&lt;/td&gt;&lt;td&gt;The hosting. The game runs as a simple website with a small cloud function behind it for the evidence lookups.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Microsoft Entra (modelled)&lt;/td&gt;&lt;td&gt;The account data mimics a real Microsoft Entra directory but is entirely synthetic. There's an optional read-only mode that can grade a real directory, with a privacy flag that masks names for public demos.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 50.00%" /&gt;&lt;col style="width: 50.00%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H2&gt;How we built it&lt;/H2&gt;
&lt;H3&gt;The risk engine is the game&lt;/H3&gt;
&lt;P&gt;Everything hangs off one honest scoring function. It weighs how powerful an account is (an unused administrator account is a much bigger liability than an unused mailbox), how long it has sat dormant, whether it has multi-factor authentication, and, crucially, whether it's&amp;nbsp;&lt;STRONG&gt;load-bearing&lt;/STRONG&gt;: whether some living process still depends on it, like an automated job that runs every night.&lt;/P&gt;
&lt;P&gt;For the technical readers&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The gameplay consequences map straight onto operational reality. Lay to rest an account that something still depends on and you spawn a Poltergeist, because you just broke a live process (minus 60 points). Shrug at a grade-F corpse and you've left breach bait sitting in a room (minus 20). And the&lt;/P&gt;
&lt;LI-CODE lang=""&gt;function grade(idn) {
  const dormant = daysSince(idn.lastInteractiveSignIn);
  const priv = isPrivileged(idn);
  const lb = loadBearing(idn);          // live runbook refs, recent token refresh, active OAuth
  let score = 0;
  if (priv) score += 45;                // privilege = blast radius
  if (dormant &amp;gt; 365) score += 35; else if (dormant &amp;gt; 180) score += 20; else if (dormant &amp;gt; 90) score += 10;
  if (!idn.mfaRegistered &amp;amp;&amp;amp; idn.accountType !== 'servicePrincipal') score += 15;
  if (idn.riskLevel === 'high') score += 15; else if (idn.riskLevel === 'medium') score += 8;
  if (idn.accountEnabled &amp;amp;&amp;amp; !lb &amp;amp;&amp;amp; dormant &amp;gt; 180) score += 10; // enabled, dead, dormant = pure liability
  const g = score &amp;gt;= 75 ? 'F' : score &amp;gt;= 55 ? 'D' : score &amp;gt;= 35 ? 'C' : score &amp;gt;= 18 ? 'B' : 'A';
  return { grade: g, score, privileged: priv, loadBearing: lb };&lt;/LI-CODE&gt;
&lt;P&gt;Possession monster deliberately moves toward unjudged high-risk accounts on its way to the Vault, which is more or less how real attackers move through a network.&lt;/P&gt;
&lt;H3&gt;Evidence with receipts: Foundry IQ&lt;/H3&gt;
&lt;img /&gt;
&lt;PRE class="lia-indent-padding-left-90px lia-align-center"&gt;&lt;EM&gt;Inside the manor: the room roster on the left grades each account A to F, the spirit gives its testimony, and the Case panel on the right walks you through Divine (dependency mapping) and Summon (Foundry IQ cited evidence) before you judge.&lt;/EM&gt;&lt;/PRE&gt;
&lt;P&gt;The heart of the project is the evidence step. When you summon evidence against a suspicious account, the question goes to a Foundry IQ knowledge base (built on Azure AI Search) loaded with the kinds of documents a real identity team would consult: operational runbooks, system inventories, and security policies. What comes back isn't an AI's opinion. It's cited passages, with sources, like "Runbook AP-Close.ps1, line 88, still calls this account." That one line is the difference between a safe cleanup and a broken month-end close, and it's exactly what we wanted players to feel.&lt;/P&gt;
&lt;P&gt;For the technical readers&lt;/P&gt;
&lt;LI-CODE lang=""&gt;export async function groundQuery(question, top = 3) {
  if (!isConfigured()) return null;   // caller falls back to baked synthetic evidence
  const url = `${EP}/indexes/${INDEX}/docs/search?api-version=2024-07-01`;
  const body = { search: question, top, select: 'id,title,content,source' };
  if (SEM) { body.queryType = 'semantic'; body.semanticConfiguration = SEM;
             body.captions = 'extractive'; body.answers = 'extractive|count-3'; }
  const res = await fetch(url, { method: 'POST',
    headers: { 'content-type': 'application/json', 'api-key': KEY },
    body: JSON.stringify(body) });
  const data = await res.json();
  return { grounded: true, question,
    answers: (data['@search.answers'] || []).map(a =&amp;gt; a.text),
    citations: (data.value || []).map(d =&amp;gt; ({ title: d.title, source: d.source,
      score: d['@search.rerankerScore'] ?? d['@search.score'],
      snippet: d['@search.captions']?.[0]?.text || String(d.content).slice(0, 200) })) };
}&lt;/LI-CODE&gt;
&lt;H3&gt;The Warden: an AI advisor on a short leash&lt;/H3&gt;
&lt;P&gt;The in-game advisor, the Warden, is deliberately boxed in. It receives the account's signals plus the retrieved evidence, and it must answer in a fixed format: a recommended judgment, a rationale under 180 characters, and a confidence score. The instructions we gave it are what we'd tell a junior analyst: pick the least-destructive action that's still correct. The Warden advises; the deterministic rules of the game decide what actually happens. That split, AI proposes and the engine disposes, is one we'd recommend for any AI system that touches real operations.&lt;/P&gt;
&lt;H3&gt;Letting Copilot play&lt;/H3&gt;
&lt;P&gt;Because the manor is exposed through MCP, registering it with GitHub Copilot in VS Code takes four lines of configuration:&lt;/P&gt;
&lt;LI-CODE lang=""&gt;{ "servers": { "afterlogin": { "command": "node", "args": ["mcp-server.mjs"] } } }&lt;/LI-CODE&gt;
&lt;P&gt;From there you can ask Copilot to "clear the manor" and watch it investigate rooms, summon evidence, and pass judgments in a loop, playing by the same rules a human does. The first time it correctly spared the break-glass emergency account, the one that looks abandoned but is dormant by design, was a genuinely good moment in the office.&lt;/P&gt;
&lt;H3&gt;What gave us trouble&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Live cloud services fail at the worst possible moment.&lt;/STRONG&gt; Anyone who has demoed on conference Wi-Fi knows this. So every cloud integration in AfterLogin checks whether it's configured and quietly falls back to built-in synthetic evidence when it isn't. The game runs fully offline, and lights up real retrieval the moment it's pointed at a Foundry knowledge base. Same code path either way, no demo-mode switch to forget.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;The versions drifted apart.&lt;/STRONG&gt;&amp;nbsp;Early on, the human game and the AI-playable version had separate logic, and they disagreed in embarrassing ways. The fix was making the scoring engine the single source of truth that everything consumes. Now Copilot playing by itself gets identical outcomes to a human clicking rooms, which is the whole point.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;A simple website can't hold secrets.&lt;/STRONG&gt;&amp;nbsp;A game that ships as one web page has nowhere safe to keep an API key. Everything that needs one got moved behind two small server endpoints, so credentials never touch the browser.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Teaching without preaching.&lt;/STRONG&gt;&amp;nbsp;Nobody wants a lecture disguised as a game. We let the mechanics do the teaching: players internalize "dormant plus powerful plus nothing depends on it means lay it to rest" because the score, the Poltergeist, and the Possession punish every other choice.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;What it actually does&lt;/H2&gt;
&lt;P&gt;We'll be upfront: this is a demo and a teaching tool, not a product, and we don't have benchmark charts for a haunted house. What we can point to:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Evidence changes decisions, provably.&lt;/STRONG&gt;&amp;nbsp;The manor's two deceptive cases (a terrible-looking service account that something still depends on, and an emergency account that's dormant on purpose) cannot be judged correctly from the statistics alone. Both hinge on retrieved citations. Skip the evidence step and you lose the game. That's the argument for grounded AI, made playable.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Three surfaces, one brain.&lt;/STRONG&gt;&amp;nbsp;One scoring model powers the visual game, the AI-playable version, and the service layer. The game itself ships as a single web page.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Works offline, upgrades gracefully.&lt;/STRONG&gt;&amp;nbsp;With no configuration it runs anywhere, no keys and no network needed. Configured, the evidence step returns real, semantically ranked, cited passages from Azure AI Search.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;It opens conversations.&lt;/STRONG&gt;&amp;nbsp;The game is live on Azure Static Web Apps and has become a genuinely useful icebreaker in our identity-governance work. People who would never read an orphaned-account runbook will happily spend ten minutes banishing a Possession, and they walk away able to explain "truly dead" versus "still depended on." That's more than most slide decks achieve.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Safe by construction.&lt;/STRONG&gt;&amp;nbsp;The bundled data is fully synthetic, with no real names or secrets anywhere. The optional live-directory mode is read-only, with a privacy flag that masks identifying details for public demos.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;What we learned&lt;/H2&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Fallbacks earn their keep.&lt;/STRONG&gt;&amp;nbsp;Designing every integration to degrade gracefully made the app more demoable and, as a side effect, forced cleaner boundaries in the code. It's now our default pattern for anything AI-backed.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Grounding lands hardest when the ungrounded answer is wrong.&lt;/STRONG&gt; The best moments in AfterLogin are the accounts where the statistics lie. If an AI retrieval demo only confirms what the raw data already says, nobody feels the value. Build the deceptive case first.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;MCP is a cheap second product.&lt;/STRONG&gt;&amp;nbsp;Wrapping the existing game logic in ten MCP tools took a fraction of the total effort, and it turned a visual demo into something an AI agent can be tested against. If your app already has an API, it's about one file away from being usable by an AI assistant.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Constrain the model, trust the engine.&lt;/STRONG&gt;&amp;nbsp;Keeping the AI advisory, with a fixed answer format, a short rationale, and a confidence score, avoids both invented actions and outcomes nobody can explain afterwards. The deterministic engine always has the final say.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P class="lia-align-center lia-indent-padding-left-30px"&gt;&lt;EM&gt;&lt;STRONG&gt;A field note from our MajorKey practice:&lt;/STRONG&gt;&amp;nbsp;this pattern isn't just for games. The identity programs we see work best run access reviews the way the manor does: a deterministic policy engine decides what's allowed, retrieved evidence about ownership, usage, and dependencies sits next to every decision, and AI recommends rather than rules. If your certification campaigns have turned into rubber stamps, the poltergeist has a lesson for them.&lt;/EM&gt;&lt;/P&gt;
&lt;H2&gt;Where it goes next&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;A real Fabric IQ ontology.&lt;/STRONG&gt;&amp;nbsp;The web of relationships between accounts, mailboxes, groups, and live jobs is currently modelled in code. Moving it to Microsoft Fabric's semantic layer would make those "spirit threads" a governed, queryable asset.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Agent-vs-agent mode.&lt;/STRONG&gt;&amp;nbsp;Two AI agents racing to clear the manor, one tuned for speed and one for safety. We can't think of a more fun way to demonstrate how you evaluate AI agents.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;A deeper live-directory mode.&lt;/STRONG&gt;&amp;nbsp;Extending the read-only Microsoft Entra integration with sign-in analysis and ownership lookups, behind the same privacy layer.&lt;/LI&gt;
&lt;LI&gt;
&lt;P&gt;&lt;STRONG&gt;Scenario packs.&lt;/STRONG&gt;&amp;nbsp;The manor layout and its ghosts are just data, so industry-specific versions (healthcare, public sector, finance) are new data files plus new documents to index. Given the range of clients we see at MajorKey, this one is probably next.&lt;/P&gt;
&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;Wrapping up&lt;/H2&gt;
&lt;P&gt;Orphaned accounts are a judgment problem wearing an inventory problem's clothes, and good judgment needs grounded evidence. The pattern under AfterLogin reuses well beyond games: a deterministic rules engine at the core, Foundry IQ retrieval for evidence with citations, a constrained AI for recommendations, and an MCP wrapper so AI agents can work the same process people do. It also sits squarely at the intersection our team at MajorKey Technologies works in every day, where the job is identity security and the interesting question is how AI genuinely evolves it: past chatbots, toward governed, evidence-backed decisions. This started as a side experiment, but that intersection is why it got built.&lt;/P&gt;
&lt;P&gt;Try clearing the manor before dawn. Then look at your own organization and ask which rooms are haunted.&lt;/P&gt;
&lt;H3&gt;Explore, contribute, build on it&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Watch the demo:&lt;/STRONG&gt;&amp;nbsp;&lt;A href="https://www.youtube.com/watch?v=PASTE-VIDEO-ID" target="_blank" rel="noopener"&gt;the 90-second walkthrough on YouTube&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Get the code:&lt;/STRONG&gt;&amp;nbsp;&lt;A href="https://github.com/jlynch160/afterlogin-the-hunt" target="_blank" rel="noopener"&gt;github.com/jlynch160/afterlogin-the-hunt&lt;/A&gt;, including the synthetic document library and the indexer script to stand up your own Foundry IQ knowledge base&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Run it in 60 seconds:&lt;/STRONG&gt;&amp;nbsp;clone the repo and open&amp;nbsp;index.html. No installation, no API keys, no network needed; the cloud integrations light up later if you want them&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Make it yours:&lt;/STRONG&gt;&amp;nbsp;point the three&amp;nbsp;FOUNDRY_SEARCH_*&amp;nbsp;settings at your own Azure AI Search index and the grimoire starts citing&amp;nbsp;&lt;EM&gt;your&lt;/EM&gt; runbooks&lt;/LI&gt;
&lt;/UL&gt;</description>
      <pubDate>Fri, 24 Jul 2026 09:36:36 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/afterlogin-we-turned-forgotten-account-cleanup-into-a-haunted/ba-p/4539781</guid>
      <dc:creator>jefflynch107</dc:creator>
      <dc:date>2026-07-24T09:36:36Z</dc:date>
    </item>
    <item>
      <title>🏆 Agents League: Celebrating the Builders Who Made Agents Battle for Glory</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/agents-league-celebrating-the-builders-who-made-agents-battle/ba-p/4538007</link>
      <description>&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;The arena has closed, the scores are in, and the champions are crowned.&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;Agents League, the esports-inspired hackathon at the heart of&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;AI Skills Fest 2026&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;, brought together tens of thousands of developers to build, ship, and compete with agentic AI. This is the celebration post: a spotlight on the winners across every category, the numbers behind the movement, and the engineering lessons worth carrying into your next build.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;If you competed, watched a Reactor battle, or completed a skilling playlist, this recap is for you. You&amp;nbsp;didn't&amp;nbsp;just attend an event. You helped set a record.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Before we get to the winners, there is a useful playbook hiding in their submissions. Later in this post, the section&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;“What the Winners Teach Us: Patterns Worth Stealing”&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;breaks down the build patterns future attendees should pay attention to: multi-agent orchestration, meeting users where they already work, testing discipline, and accessibility-first design. If you are planning to enter next time, read the winners not just as inspiration, but as a practical checklist for what great agent projects have in common.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2 aria-level="2"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;🥇 Best Overall: $15,000 Grand Prize&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H2&gt;
&lt;img /&gt;
&lt;H3 aria-level="2"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;Afterlogin&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;: The Hunt — &lt;A class="lia-external-url" href="https://github.com/jlynch160/afterlogin-the-hunt" target="_blank" rel="noopener"&gt;https://github.com/jlynch160/afterlogin-the-hunt&lt;/A&gt;&amp;nbsp; (Creative Apps track)&lt;/SPAN&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/H3&gt;
&lt;img /&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;The top weighted score of the entire field. Afterlogin: The Hunt is described by its builders as&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;"one engine, two faces"&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;: a cinematic Security Operations Centre (SOC) night on one side, and a coached training game on the other. The same underlying engine powers both an atmospheric narrative experience and a hands-on learning simulation.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Why it won:&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;it fused genuinely creative design with a real-world use case (security operations training) and&amp;nbsp;executed both at a high polish level. Built with&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;GitHub Copilot&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;for AI-assisted development,&amp;nbsp;it's&amp;nbsp;a masterclass in using one well-architected engine to serve two&amp;nbsp;very different&amp;nbsp;user experiences.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3 aria-level="1"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;🏅 Category Champions&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H3&gt;
&lt;H3 aria-level="2"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;Best Creative App:&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;StudyMate&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;, "Study with Matey" — &lt;A class="lia-external-url" href="https://github.com/adetorojeremiahfadesayo/StudyMate" target="_blank" rel="noopener"&gt;https://github.com/adetorojeremiahfadesayo/StudyMate&lt;/A&gt; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Tech: GitHub Copilot&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;StudyMate turns a student's&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;own&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;notes into a gamified, story-driven revision session, complete with XP and progression. Instead of generic flashcards, it grounds the experience in the learner's real material and wraps it in a narrative loop that keeps motivation high. It is&amp;nbsp;a great example&amp;nbsp;of pairing&amp;nbsp;personalisation&amp;nbsp;with game mechanics to solve a persistent problem: staying engaged while revising.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3 aria-level="2"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;Best Reasoning Agent: DELPHAI — &lt;A class="lia-external-url" href="https://github.com/jlynch160/delphai" target="_blank" rel="noopener"&gt;https://github.com/jlynch160/delphai&lt;/A&gt; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Tech: Microsoft Foundry&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;DELPHAI is an &lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;11-agent reasoning council&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;that checks the&amp;nbsp;maths, explains the risk, and refines its own answer before responding. Rather than a single model producing&amp;nbsp;a one-shot&amp;nbsp;response, DELPHAI orchestrates a panel of&amp;nbsp;specialised&amp;nbsp;agents that debate, verify, and converge, a pattern that directly addresses the reliability gap in high-stakes reasoning.&amp;nbsp;It's&amp;nbsp;a textbook demonstration of multi-agent orchestration on&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;Microsoft Foundry&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3 aria-level="2"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;Best Enterprise Agent: Archon — &lt;A class="lia-external-url" href="https://github.com/upgradedev/archon_azure" target="_blank" rel="noopener"&gt;https://github.com/upgradedev/archon_azure&lt;/A&gt; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Tech: Microsoft 365 Copilot&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Archon is a &lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;7-agent financial-intelligence pipeline for small and medium businesses&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;, delivered right inside Microsoft Teams. It meets users where they already work, chaining&amp;nbsp;specialised&amp;nbsp;agents to turn raw financial data into actionable intelligence. Archon shows how enterprise-ready agents built for&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;Microsoft 365 Copilot&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;can deliver serious business value without forcing users to leave their daily workflow.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P aria-level="1"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;🌟 Special Awards&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="width: 100%; border-width: 1px;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Award&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Winner&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td colspan="2"&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;What made it stand out&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Best Use of IQ Tools&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;CivicGrant&amp;nbsp;IQ —&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/JonEricEubanks/CivicGrant-IQ" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;https://github.com/JonEricEubanks/CivicGrant-IQ&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td colspan="2"&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Stood out for making the IQ layers genuinely useful: Foundry IQ, Fabric IQ and Work IQ were combined into a traceable grant-analysis workflow with grounded citations, specialist agents,&amp;nbsp;GraphRAG-style evidence handling, guardrails and evaluation coverage.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Accessibility&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;CLARO —&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/jagaor/claro" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;https://github.com/jagaor/claro&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;&lt;/SPAN&gt;&amp;nbsp;&lt;BR /&gt;&lt;SPAN data-contrast="auto"&gt;SchemeSaathi —&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/red-coder-27/SchemeSaathi" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;https://github.com/red-coder-27/SchemeSaathi&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;&lt;/SPAN&gt;&amp;nbsp;&lt;BR /&gt;&lt;SPAN data-contrast="auto"&gt;Solace —&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/MaksymY11/solace-reasoning" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;https://github.com/MaksymY11/solace-reasoning&lt;/SPAN&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td colspan="2"&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;These teams treated accessibility as core product architecture, not a feature add-on: CLARO combined deterministic public-benefit rules with grounded bilingual reasoning;&amp;nbsp;SchemeSaathi&amp;nbsp;made health-scheme discovery usable across Indian languages; Solace delivered cited, plain-language immigration-rights support with safety escalation for sensitive situations.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Hack for Good&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Tell My Day —&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/stork066/TellMyDay" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;https://github.com/stork066/TellMyDay&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;&lt;/SPAN&gt;&amp;nbsp;&lt;BR /&gt;&lt;SPAN data-contrast="auto"&gt;BRIEF — AI Bias &amp;amp; Research Intelligence Evaluation Framework —&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/shiwakshir/brief-agent" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;https://github.com/shiwakshir/brief-agent&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;&lt;/SPAN&gt;&amp;nbsp;&lt;BR /&gt;&lt;SPAN data-contrast="auto"&gt;ARGUS — Agentic Risk &amp;amp; Governance Unified Screening —&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/iarjunganesh/argus" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;https://github.com/iarjunganesh/argus&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td colspan="2"&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Each winner used agents for tangible social value: Tell My Day turns picture symbols into grounded stories for non-verbal users; BRIEF audits assumptions and bias before research begins; ARGUS turns manual KYC and governance screening into cited, auditable risk assessment.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Top Student&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Athenaeum —&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/theCodeForgerHQ/msf-reasoning-agent" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;https://github.com/theCodeForgerHQ/msf-reasoning-agent&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;&lt;/SPAN&gt;&amp;nbsp;&lt;BR /&gt;&lt;SPAN data-contrast="auto"&gt;Narrative Alchemist —&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/10ANT/narrative-alchemist" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;https://github.com/10ANT/narrative-alchemist&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;&lt;/SPAN&gt;&amp;nbsp;&lt;BR /&gt;&lt;SPAN data-contrast="auto"&gt;CurriculumCraft AI —&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/gideonagbavor8/curriculumcraft-ai" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-charstyle="Hyperlink"&gt;https://github.com/gideonagbavor8/curriculumcraft-ai&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td colspan="2"&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;These student-led projects stood out for ambition and execution: Athenaeum showed exceptional engineering discipline with a deep safety and test harness; Narrative Alchemist&amp;nbsp;demonstrated&amp;nbsp;a complete four-agent creative production pipeline;&amp;nbsp;CurriculumCraft&amp;nbsp;AI translated AI into practical instructional design for Ghanaian JHS teachers.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 33.4436%" /&gt;&lt;col style="width: 34.7406%" /&gt;&lt;col style="width: 31.7761%" /&gt;&lt;col style="width: 0%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Across&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;8 categories&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;14 winners&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;shared a&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;$55,000 prize pool&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;. Congratulations to every one of them, and to the thousands of builders who&amp;nbsp;submitted.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3 aria-level="1"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;🧠 What the Winners Teach Us:&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;Patterns Worth Stealing&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Look across the champions and clear engineering patterns&amp;nbsp;emerge. These are the&amp;nbsp;takeaways&amp;nbsp;AI engineers and developers should carry into their own projects.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="color: rgb(30, 30, 30); font-size: 28px;"&gt;1. Multi-agent orchestration beats the monolithic prompt&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;The two reasoning-heavy winners, DELPHAI (11 agents) and Archon (7 agents), both won by decomposing a hard problem into&amp;nbsp;specialised, cooperating agents. A "council" or "pipeline" of narrow agents that verify each other outperforms a single model asked to do everything at once.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Here's&amp;nbsp;the shape of that pattern, illustrated conceptually with the Microsoft Agent Framework style used with Microsoft Foundry. (This is an illustrative pattern, not the winners' actual code.)&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang=""&gt;# Illustrative multi-agent "reasoning council" pattern
# Conceptual sketch, not the winning team's source code.

async def reasoning_council(question: str) -&amp;gt; str:
    # 1. Specialised agents each own one responsibility
    solver = create_agent(
        role="Propose an answer with its reasoning"
    )

    math_check = create_agent(
        role="Verify every calculation, flag errors"
    )

    risk_agent = create_agent(
        role="Explain the risks and assumptions"
    )

    # 2. Draft, then critique
    draft = await solver.run(question)
    math = await math_check.run(draft)
    risk = await risk_agent.run(draft)

    # 3. Refine using the critiques before answering the user
    refined = await solver.run(
        f"Question: {question}\n"
        f"Draft: {draft}\n"
        f"Math review: {math}\n"
        f"Risk review: {risk}\n"
        "Produce a corrected, final answer."
    )

    return refined&lt;/LI-CODE&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;The lesson:&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;reliability comes from structure. Give each agent one job, let them check each other, and refine before you respond. That is exactly how DELPHAI "checks the math, explains the risk, and refines its answer."&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt; &amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN style="color: rgb(30, 30, 30); font-size: 28px;"&gt;2. Meet users where they already are&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Archon delivers financial intelligence&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;inside Microsoft Teams&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;.&amp;nbsp;StudyMate&amp;nbsp;builds on a student's&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;own notes&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;. Winning agents reduce friction by integrating into existing workflows rather than asking users to adopt a new destination. When you build enterprise agents, target the surface, such as Microsoft 365 Copilot, Teams, and Copilot Studio, where the work already happens.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN style="color: rgb(30, 30, 30);" data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;3. Test &lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;rigour&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="heading 2"&gt;is a differentiator, not an afterthought&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="color: rgb(30, 30, 30);" data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Athenaeum won Top Student with&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;611 tests&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;behind its multi-agent learning system. In a field of prototypes, evidence of engineering discipline stood out to judges. Agentic systems are non-deterministic, so a strong evaluation and&amp;nbsp;test&amp;nbsp;harness is what turns a demo into something trustworthy.&lt;/SPAN&gt;&lt;/P&gt;
&lt;H3&gt;&lt;SPAN style="color: rgb(30, 30, 30);"&gt;4. Design for everyone from day one&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;CLARO (accessibility-first reasoning) and Tell My Day (assistive storytelling for non-verbal users) prove that responsible, inclusive AI&amp;nbsp;isn't&amp;nbsp;a constraint;&amp;nbsp;it's&amp;nbsp;a source of the most meaningful innovation. Accessibility completions were a top skilling path this year, and the winners&amp;nbsp;reflected&amp;nbsp;it.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2 aria-level="1"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;🎮 The Three Tracks and Their Toolchains&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Agents League ran three build&amp;nbsp;tracks,&amp;nbsp;each anchored to a Microsoft developer platform. The winners map directly onto them:&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="1" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Creative Apps → GitHub Copilot.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;AI-assisted development from concept to code. Winners:&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Afterlogin&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;:&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;The Hunt&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;,&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;StudyMate&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;. (35% of the&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;field.)&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="2" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Reasoning Agents → Microsoft Foundry.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;Multi-step reasoning and agent orchestration. Winner:&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;DELPHAI&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;. (46% of the field, the most popular&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;track.)&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="3" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Enterprise Agents → Microsoft 365 Copilot &amp;amp; Copilot Studio.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;Business-ready knowledge agents. Winner:&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Archon&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;. (19% of the&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;field.)&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2 aria-level="1"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;🔴 The Reactor Battles: Learning in Public&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;The live Microsoft Reactor build battles were where the&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;thousands of developers&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;learned&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;together&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;in real time.&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;The community connected over&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;four&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;live&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;broadcasts&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;.&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt; &lt;A class="lia-external-url" href="https://developer.microsoft.com/en-us/reactor/series/S-1658/" target="_blank" rel="noopener"&gt;&lt;SPAN data-contrast="none"&gt;Microsoft Reactor Agents League series&lt;/SPAN&gt;&lt;/A&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;A standout moment:&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;Kyle Daigle&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;, CMO of Microsoft Developer and COO of GitHub, live-coded his own project on stream during the Creative Apps Reactor Battle, an authentic build-along that resonated with the developer audience. As one attendee put it:&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;"These types of sessions are the best, where we can see code and flows. It's like we learn more by&amp;nbsp;visualising."&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2 aria-level="1"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;📚 Skill Up Like a Champion: The Developer&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;Playlists&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Winners&amp;nbsp;don't&amp;nbsp;appear from nowhere; many skilled up first. Seven role-based developer paths on&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;AI Skills Navigator&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;drove&amp;nbsp;thousands of&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;completions&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;, spanning GitHub Copilot, Microsoft Foundry, and Microsoft 365. The top&amp;nbsp;five&amp;nbsp;learning playlists:&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="5" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Develop your first agent with Microsoft Foundry&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;, completions (the runaway&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;favourite&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;)&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="6" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Learn AI-assisted coding with GitHub Copilot&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="7" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Accessibility in practice&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="8" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Optimise&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;agentic DevOps with Azure DevOps &amp;amp; GitHub Copilot&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="9" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Build and orchestrate agents with Microsoft Foundry&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Completion earned free GitHub &amp;amp; Microsoft certification vouchers and&amp;nbsp;Credly&amp;nbsp;badges. If you want to be on next year's winners list, this is where to start.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;H2 aria-level="1"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;🔧 One Honest Lesson for Next Time&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H2&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Transparency matters, so&amp;nbsp;here's&amp;nbsp;a builder-to-builder tip drawn from the judging data. Of&amp;nbsp;the final&amp;nbsp;submissions, the single biggest disqualifier was a&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;missing demo video&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;, followed by no listed repository. Brilliant projects were screened out on&amp;nbsp;a technicality.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;The takeaway&amp;nbsp;for future hackathons:&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;treat your&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;demo video&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;and&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;public repository&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;as first-class deliverables, not last-minute additions. A working agent nobody can see or reproduce&amp;nbsp;can't&amp;nbsp;win. Record the demo early, keep the repo public, and document how to run it.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P aria-level="1"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;✅ Key Takeaways&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="10" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Multi-agent architectures dominated the podium&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;: DELPHAI's 11-agent council and Archon's 7-agent pipeline show that decomposition and self-verification win.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="11" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Integration and inclusivity are differentiators&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;: winners met users inside Teams, in their own notes, and designed for accessibility from day one.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="12" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Engineering&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;rigour&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;gets noticed&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;:&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;611 tests&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;helped Athenaeum&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;win&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;one&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;of&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;the&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;Top Student&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;&amp;nbsp;awards&lt;/SPAN&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;UL&gt;
&lt;LI aria-setsize="-1" data-leveltext="" data-font="Symbol" data-listid="6" data-list-defn-props="{" data-aria-posinset="13" data-aria-level="1"&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;Submission hygiene is non-negotiable&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&lt;SPAN data-ccp-parastyle="List Bullet"&gt;: a demo video and public repo are the price of admission to judging.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3 aria-level="1"&gt;&lt;SPAN data-contrast="none"&gt;&lt;SPAN data-ccp-parastyle="heading 1"&gt;🚀 Your Next Move&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/H3&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;Whether&amp;nbsp;you're&amp;nbsp;a returning competitor or inspired to enter your first battle,&amp;nbsp;here's&amp;nbsp;how to keep building:&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;🎬&amp;nbsp;&lt;STRONG&gt;Rewatch the battles:&lt;/STRONG&gt;&amp;nbsp;&lt;A href="https://developer.microsoft.com/en-us/reactor/series/S-1658/" target="_blank" rel="noopener"&gt;Microsoft Reactor Agents League series&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;📘&amp;nbsp;&lt;STRONG&gt;Start skilling:&lt;/STRONG&gt;&amp;nbsp;&lt;A href="https://aiskillsnavigator.microsoft.com/events/AISF2026" target="_blank" rel="noopener"&gt;AI Skills Navigator AISF 2026 developer playlists&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;🤖&amp;nbsp;&lt;STRONG&gt;Build reasoning agents:&lt;/STRONG&gt;&amp;nbsp;explore&amp;nbsp;&lt;A href="https://ai.azure.com/" target="_blank" rel="noopener"&gt;Microsoft Foundry&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;💡&amp;nbsp;&lt;STRONG&gt;Ship with AI assistance:&lt;/STRONG&gt;&amp;nbsp;&lt;A href="https://github.com/features/copilot" target="_blank" rel="noopener"&gt;GitHub Copilot&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;🏢&amp;nbsp;&lt;STRONG&gt;Build enterprise agents:&lt;/STRONG&gt;&amp;nbsp;&lt;A href="https://www.microsoft.com/microsoft-copilot/microsoft-copilot-studio" target="_blank" rel="noopener"&gt;Microsoft Copilot Studio&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;To every builder who entered the arena, streamed a battle, or completed a playlist:&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;thank you.&lt;/SPAN&gt;&lt;SPAN data-contrast="auto"&gt;&amp;nbsp;You&amp;nbsp;didn't&amp;nbsp;just compete; you showed the world what's possible when developers and agentic AI build together. The champions above earned their moment, but the real story is a global community of 31,000 developers levelling up at once.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN data-contrast="auto"&gt;The arena will open again. When it does, will your agent be on the podium? 🏆&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;SPAN data-contrast="auto"&gt;Agents&amp;nbsp;League was part of AI Skills Fest 2026 and was open to the public at no cost. Figures reflect the completed submission and judging period after excluding Microsoft-affiliated participants. Winner descriptions are drawn from the official Agents League Hackathon summary.&lt;/SPAN&gt;&lt;SPAN data-ccp-props="{}"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/EM&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 23 Jul 2026 19:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/agents-league-celebrating-the-builders-who-made-agents-battle/ba-p/4538007</guid>
      <dc:creator>Lee_Stott</dc:creator>
      <dc:date>2026-07-23T19:00:00Z</dc:date>
    </item>
    <item>
      <title>Set Up Plaud Note Pro with Microsoft Foundry</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/set-up-plaud-note-pro-with-microsoft-foundry/ba-p/4537428</link>
      <description>&lt;H1&gt;Prerequisites&lt;/H1&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A class="lia-external-url" href="https://github.com/riffado/connector#installation" target="_blank"&gt;Riffado&lt;/A&gt;, up and running: follow the setup guide in the official Riffado repository to get it going with Docker Compose.&lt;/LI&gt;
&lt;LI&gt;A Microsoft Foundry (formerly Azure AI Foundry) resource, with the models you want deployed; in my case, whisper for transcription and o3-mini for summaries.&lt;/LI&gt;
&lt;LI&gt;A Plaud device, or any audio recordings you can import into Riffado.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Once Riffado is up, head to the Settings page &amp;gt; Providers &amp;gt; Add Provider, and select Custom. This is where the Azure details will go.&lt;/P&gt;
&lt;H1&gt;Why "OpenAI-compatible" isn’t one thing on Microsoft Foundry&lt;/H1&gt;
&lt;P&gt;Azure AI Foundry exposes&amp;nbsp;&lt;STRONG&gt;two different API surfaces&lt;/STRONG&gt;&amp;nbsp;on the same resource, and which one serves your model depends on the model:&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Surface&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Path shape&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Serves&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;OpenAI-compatible?&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;v1 route&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;/openai/v1/…&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;gpt-4o-transcribe, gpt-4o-mini-transcribe, chat models, embeddings&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;Yes: Bearer auth, model in the body, no&amp;nbsp;api-version&amp;nbsp;needed&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Classic route&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;/openai/deployments/{name}/…&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Whisper&lt;/STRONG&gt;&amp;nbsp;(and other legacy audio)&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;No: deployment name lives in the URL, and&amp;nbsp;?api-version=&amp;nbsp;is&amp;nbsp;&lt;EM&gt;mandatory&lt;/EM&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;A generic OpenAI client (Riffado's included) can only speak the first dialect. It has nowhere to put a deployment name in the path and no way to append a query parameter. That single fact drives everything below.&lt;/P&gt;
&lt;H1&gt;Part 1 - Transcription&lt;/H1&gt;
&lt;H2&gt;Whisper and the&amp;nbsp;DeploymentNotFound&amp;nbsp;mystery&lt;/H2&gt;
&lt;H3&gt;Symptom&lt;/H3&gt;
&lt;P&gt;My very first transcription attempt in Riffado failed with&amp;nbsp;404 Resource not found. Off to a flying start. Configured provider: base URL&amp;nbsp;https://&amp;lt;resource&amp;gt;.services.ai.azure.com, model&amp;nbsp;whisper.&lt;/P&gt;
&lt;H3&gt;Dead end #1: the missing path&lt;/H3&gt;
&lt;P&gt;The first bug was mine: the base URL had no path. Riffado's OpenAI client appends&amp;nbsp;/audio/transcriptions&amp;nbsp;to whatever you give it, so requests were hitting&amp;nbsp;https://&amp;lt;resource&amp;gt;…/audio/transcriptions, a path that doesn't exist on the resource at all. Fixing the base URL to end in&amp;nbsp;/openai/v1&amp;nbsp;got us to a more interesting error:&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN class="lia-text-color-8"&gt;POST /openai/v1/audio/transcriptions · model=whisper&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;{"error":{"code":"DeploymentNotFound","message":"The API deployment for&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;this resource does not exist. If you created the deployment within the&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;last 5 minutes, please wait a moment and try again."}}&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;H3&gt;Dead end #2: catalog ≠ deployment&lt;/H3&gt;
&lt;P&gt;Worth checking before anything else:&amp;nbsp;&lt;EM&gt;selecting&lt;/EM&gt;&amp;nbsp;a model in the Foundry catalog is not&amp;nbsp;&lt;EM&gt;deploying&lt;/EM&gt;&amp;nbsp;it.&amp;nbsp;GET /openai/v1/models&amp;nbsp;lists everything you&amp;nbsp;&lt;EM&gt;could&lt;/EM&gt;&amp;nbsp;deploy; only&amp;nbsp;&lt;STRONG&gt;Deployments → Deploy model&lt;/STRONG&gt;&amp;nbsp;creates an endpoint that answers. If you get&amp;nbsp;DeploymentNotFound, first confirm a deployment actually exists (the listing below requires only the API key):&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;enumerate real deployments (classic control-plane, key auth)&lt;/STRONG&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN class="lia-text-color-8"&gt;curl -s -H "api-key: $KEY" \&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;  "https://&amp;lt;resource&amp;gt;.openai.azure.com/openai/deployments?api-version=2023-03-15-preview"&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;# → {"data":[{"id":"whisper","model":"whisper","status":"succeeded",…}]}&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;H3&gt;The actual cause&lt;/H3&gt;
&lt;P&gt;Here is the part that nearly drove me mad: the deployment existed and was succeeded, yet the v1 route still said&amp;nbsp;DeploymentNotFound. Because&amp;nbsp;&lt;STRONG&gt;Whisper deployments are not served on the v1 route at all.&lt;/STRONG&gt;&amp;nbsp;They only answer on the classic path. Verified side by side with the same tiny WAV file:&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Request&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Result&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;POST /openai/v1/audio/transcriptions&amp;nbsp;·&amp;nbsp;model=whisper&amp;nbsp;· Bearer&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;404 DeploymentNotFound&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;POST /openai/deployments/whisper/audio/transcriptions?api-version=2024-06-01&amp;nbsp;· Bearer&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;200 {"text":"you"}&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Same classic path,&amp;nbsp;&lt;STRONG&gt;without&lt;/STRONG&gt;&amp;nbsp;?api-version=&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;404 Resource not found&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;Three constraints, then: Whisper needs the classic path; the classic path needs&amp;nbsp;api-version; Riffado can send neither. One piece of good news hiding in the table: the classic route accepts&amp;nbsp;Authorization: Bearer, not just Azure's&amp;nbsp;api-key&amp;nbsp;header, so the shim doesn't have to touch auth at all.&lt;/P&gt;
&lt;H3&gt;The fix: a Caddy shim&lt;/H3&gt;
&lt;P&gt;Drop a stock&amp;nbsp;caddy:2-alpine&amp;nbsp;container into the Compose network. Riffado points at it as if it were OpenAI; the shim rewrites the path, injects&amp;nbsp;api-version, and proxies to Azure. The Bearer header passes through untouched.&lt;/P&gt;
&lt;P&gt;&lt;SPAN class="lia-text-color-8"&gt;&lt;STRONG&gt;azure-shim.Caddyfile&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang=""&gt;{
      admin off
      auto_https off
}

:80 {
      @transcribe path /v1/audio/transcriptions /audio/transcriptions
      handle @transcribe {
            rewrite * /openai/deployments/whisper/audio/transcriptions?api-version=2024-06-01
            reverse_proxy https://&amp;lt;resource&amp;gt;.services.ai.azure.com {
                  header_up Host &amp;lt;resource&amp;gt;.services.ai.azure.com
            }
      }

      handle {
            respond "azure-shim ok" 200
      }

}&lt;/LI-CODE&gt;
&lt;P&gt;&lt;SPAN class="lia-text-color-8"&gt;&lt;STRONG&gt;docker-compose.yml (added service)&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;LI-CODE lang=""&gt;azure-shim:
    image: caddy:2-alpine
    restart: unless-stopped
    volumes:
      - ./azure-shim.Caddyfile:/etc/caddy/Caddyfile:ro&lt;/LI-CODE&gt;
&lt;P&gt;Riffado's provider settings become:&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Field&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;Value&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Base URL&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;http://azure-shim/v1&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;Model&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;whisper&amp;nbsp;(must equal the deployment name)&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;API key&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;the Azure resource key (forwarded as Bearer)&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H3&gt;Verified&lt;/H3&gt;
&lt;P&gt;From inside the Riffado container:&amp;nbsp;POST http://azure-shim/v1/audio/transcriptions&amp;nbsp;→&amp;nbsp;200 {"text":"…"}. Transcription works end-to-end in the UI.&lt;/P&gt;
&lt;H1&gt;Part 2 · Summaries &amp;amp; titles&lt;/H1&gt;
&lt;H2&gt;o3-mini and the empty answer&lt;/H2&gt;
&lt;H3&gt;Symptom&lt;/H3&gt;
&lt;P&gt;The summary button showed&amp;nbsp;&lt;EM&gt;"An unexpected error occurred."&lt;/EM&gt;&amp;nbsp;The container logs were more honest:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;riffado-app logs&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Error generating title: TypeError: undefined is not an object&lt;BR /&gt;&lt;BR /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (evaluating 'C.choices[0]')&lt;BR /&gt;&lt;BR /&gt;Riffado calls&amp;nbsp;chat/completions&amp;nbsp;and reads&amp;nbsp;choices[0]&amp;nbsp;without checking whether the response was an error. So&amp;nbsp;&lt;EM&gt;anything&lt;/EM&gt; the API refuses becomes "an unexpected error." What was it refusing?&lt;/P&gt;
&lt;H3&gt;Cause 1: reasoning models reject the classic knobs&lt;/H3&gt;
&lt;P&gt;o3-mini belongs to Azure/OpenAI's&amp;nbsp;&lt;STRONG&gt;o-series reasoning models&lt;/STRONG&gt;, which hard-reject parameters every classic chat client sends. Riffado sends&amp;nbsp;temperature: 0.7&amp;nbsp;and&amp;nbsp;max_tokens: 50&amp;nbsp;for titles (0.5&amp;nbsp;/&amp;nbsp;2000&amp;nbsp;for summaries), and o3-mini answers:&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN class="lia-text-color-8"&gt;POST /openai/v1/chat/completions · model=o3-mini&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;HTTP 400&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;{"error":{"message":"Unsupported parameter: 'max_tokens' is not supported&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;with this model. Use 'max_completion_tokens' instead.", …}}&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;# and with max_tokens fixed:&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN class="lia-text-color-8"&gt;HTTP 400&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;{"error":{"message":"Unsupported parameter: 'temperature' is not supported&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;with this model.", …}}&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;H3&gt;Cause 2: reasoning tokens starve the output&lt;/H3&gt;
&lt;P&gt;Stripping the bad params gets you to 200, and then comes a subtler failure, my personal favourite of this whole saga. Reasoning models spend completion tokens on internal "thinking"&amp;nbsp;&lt;EM&gt;before&lt;/EM&gt;&amp;nbsp;emitting a single visible character. Riffado's 50-token title budget is consumed entirely by reasoning, and the reply comes back syntactically valid and&amp;nbsp;&lt;STRONG&gt;empty&lt;/STRONG&gt;:&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;max_completion_tokens&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;reasoning_effort&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;finish_reason&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;&lt;STRONG&gt;content&lt;/STRONG&gt;&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;50&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;not set&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;length&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;"" (all 50 spent reasoning)&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;2000&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;not set&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;stop&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;"Q3 Budget Planning Strategy Meeting"&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
&lt;P&gt;2000&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;low&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;stop&lt;/P&gt;
&lt;/td&gt;&lt;td&gt;
&lt;P&gt;same, less reasoning overhead&lt;/P&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H3&gt;The fix: a Node shim that rewrites the request body&lt;/H3&gt;
&lt;P&gt;Caddy can rewrite paths but not JSON bodies, so this shim is ~60 lines of dependency-free Node on&amp;nbsp;node:20-alpine. Per request it: converts&amp;nbsp;max_tokens → max_completion_tokens, strips&amp;nbsp;temperature&amp;nbsp;/&amp;nbsp;top_p&amp;nbsp;/ penalties,&amp;nbsp;&lt;STRONG&gt;floors the token budget at 4000&lt;/STRONG&gt;, sets&amp;nbsp;reasoning_effort: "low", maps&amp;nbsp;/v1/* → /openai/v1/*, and forwards to the Azure resource.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;o3-shim.js&lt;/STRONG&gt;&lt;/P&gt;
&lt;LI-CODE lang=""&gt;const http = require('http');
const https = require('https');
const UPSTREAM_HOST = '&amp;lt;resource&amp;gt;.services.ai.azure.com';

// Params o-series reasoning models reject on chat/completions.
const STRIP = ['temperature','top_p','presence_penalty',
               'frequency_penalty','logprobs','top_logprobs'];

const server = http.createServer((req, res) =&amp;gt; {
  const chunks = [];
  req.on('data', c =&amp;gt; chunks.push(c));
  req.on('end', () =&amp;gt; {
    let body = Buffer.concat(chunks);

    // Riffado's base_url is http://o3-shim/v1 → map to Azure's /openai/v1
    let path = req.url;
    if (path.startsWith('/v1/')) path = '/openai' + path;
    const ct = (req.headers['content-type'] || '').toLowerCase();
    if (ct.includes('application/json') &amp;amp;&amp;amp; body.length) {

      try {
        const j = JSON.parse(body.toString('utf8'));
        if (j &amp;amp;&amp;amp; typeof j === 'object' &amp;amp;&amp;amp; !Array.isArray(j)) {
          if ('max_tokens' in j) {
            if (!('max_completion_tokens' in j))
              j.max_completion_tokens = j.max_tokens;
            delete j.max_tokens;
          }

          // Reasoning spends tokens before any visible output; small
          // budgets (Riffado sends 50 for titles) return empty strings.
          if (Array.isArray(j.messages)) {
            j.max_completion_tokens =
              Math.max(Number(j.max_completion_tokens) || 0, 4000);
            if (!('reasoning_effort' in j)) j.reasoning_effort = 'low';
          }
          for (const k of STRIP) delete j[k];
          body = Buffer.from(JSON.stringify(j));
        }
      } catch (_) { /* not JSON - forward untouched */ }
    }

    const headers = { ...req.headers, host: UPSTREAM_HOST,
                      'content-length': Buffer.byteLength(body) };
    const up = https.request(
      { host: UPSTREAM_HOST, port: 443, method: req.method, path, headers },
      upRes =&amp;gt; { res.writeHead(upRes.statusCode, upRes.headers); upRes.pipe(res); }
    );

    up.on('error', e =&amp;gt; {
      res.writeHead(502, {'content-type':'application/json'});
      res.end(JSON.stringify({error:{message:'o3-shim upstream error: '+e.message}}));
    });

    up.end(body);
  });
});

server.listen(80, () =&amp;gt; console.log('o3-shim listening on :80'));&lt;/LI-CODE&gt;
&lt;P&gt;&lt;STRONG&gt;docker-compose.yml (added service)&lt;/STRONG&gt;&lt;/P&gt;
&lt;LI-CODE lang=""&gt;  o3-shim:
    image: node:20-alpine
    restart: unless-stopped
    working_dir: /app
    command: ["node", "/app/o3-shim.js"]
    volumes:
      - ./o3-shim.js:/app/o3-shim.js:ro&lt;/LI-CODE&gt;
&lt;P&gt;Add a second provider in Riffado (base URL&amp;nbsp;http://o3-shim/v1, model&amp;nbsp;o3-mini, the resource's API key) and set it as the default&amp;nbsp;&lt;EM&gt;enhancement&lt;/EM&gt; provider (summaries/titles), keeping the Whisper one as default for transcription.&lt;/P&gt;
&lt;P&gt;Riffado's exact title request (temperature: 0.7, max_tokens: 50) through the shim → 200, finish_reason: stop, real title text. A full meeting-transcript summary returns structured key points and action items.&lt;/P&gt;
&lt;H1&gt;The final shape&lt;/H1&gt;
&lt;img /&gt;
&lt;P&gt;Reading it left to right: Riffado never talks to Azure directly. Transcription requests pass through azure-shim, a stock Caddy container that rewrites each request onto Whisper's classic deployment path and injects the mandatory api-version parameter. Summary and title requests pass through o3-shim, a tiny Node server that rewrites the request body into the shape o3-mini accepts and floors the token budget so the model's internal reasoning cannot starve the actual answer. As far as Riffado is concerned, it is simply talking to two ordinary OpenAI providers.&lt;/P&gt;
&lt;P&gt;Both shims live on the Compose network only; nothing is exposed publicly. Riffado is unmodified.&lt;/P&gt;
&lt;H1&gt;Verification checklist&lt;/H1&gt;
&lt;P&gt;Each layer, testable in isolation. Run these before blaming the app:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;smoke tests&lt;/STRONG&gt;&lt;/P&gt;
&lt;PRE&gt;&lt;SPAN class="lia-text-color-8"&gt;# 1. Key + resource alive? (v1 models listing, Bearer auth)&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;curl -s -H "Authorization: Bearer $KEY" \&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;  https://&amp;lt;resource&amp;gt;.services.ai.azure.com/openai/v1/models | head -c 200&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;# 2. Whisper answers on the classic path?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;curl -s -H "Authorization: Bearer $KEY" -F file=@test.wav \&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;&amp;nbsp; "https://&amp;lt;resource&amp;gt;.services.ai.azure.com/openai/deployments/whisper/audio/transcriptions?api-version=2024-06-01"&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;# 3. Shim translates correctly? (from inside the compose network)&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;docker exec riffado-app node -e "fetch('http://azure-shim/')&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;&amp;nbsp; .then(r=&amp;gt;r.text()).then(console.log)"&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;# 4. o3-mini via shim, sending the params Riffado sends?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN class="lia-text-color-8"&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; (temperature + max_tokens:50; the shim must absorb both)&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;H1&gt;If you'd rather not run shims&lt;/H1&gt;
&lt;P&gt;Both shims exist because of the specific models chosen. Pick models that live natively on the v1 route and Riffado connects directly, with base URL&amp;nbsp;https://&amp;lt;resource&amp;gt;.services.ai.azure.com/openai/v1&amp;nbsp;and zero extra containers:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Transcription:&lt;/STRONG&gt;&amp;nbsp;deploy&amp;nbsp;gpt-4o-mini-transcribe&amp;nbsp;(or&amp;nbsp;gpt-4o-transcribe) instead of Whisper.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Summaries:&lt;/STRONG&gt;&amp;nbsp;deploy a non-reasoning chat model such as&amp;nbsp;gpt-4o-mini, which happily accepts&amp;nbsp;temperature&amp;nbsp;and&amp;nbsp;max_tokens.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The shim approach earns its keep when you're standardized on specific models (Whisper's transcription quality, o3-mini's reasoning), or when you want a control point to add logging, retries, or budget caps later.&lt;/P&gt;
&lt;P&gt;For reference, this is what the finished setup looks like on Riffado's side. Each shim is registered as a plain Custom provider. Here is the whisper provider pointing at azure-shim, with Use for transcription ticked:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;And once both are saved, they sit side by side in the providers list, whisper tagged for transcription and o3-mini tagged for enhancement:&lt;/P&gt;
&lt;img /&gt;
&lt;H1&gt;A quick look at the Foundry portal&lt;/H1&gt;
&lt;P&gt;In the Microsoft Foundry portal, head over to Models &amp;gt; AI Services and you will find a pleasant surprise: fifteen AI service models already deployed and ready to use, covering the Azure Speech family (including Voice Live and Speech to Text), Azure Translator, Azure Language, and Content Understanding:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You can of course deploy another model for this, but the pre-deployed ones are a handy cost-saving option. Click on the Azure Speech – Voice Live radio button and you will be shown the Base URL and API Key, which you can then paste into the provider settings on Riffado's Settings page.&lt;/P&gt;
&lt;P&gt;A quick note on cost: these services are not free. They are billed pay-as-you-go based on usage. Azure Speech transcription is charged per audio hour, and Voice Live pricing is tiered by the model you choose. The free tier does include a monthly allowance, though. Check the &lt;A href="https://azure.microsoft.com/en-us/pricing/details/speech/" target="_blank"&gt;Azure Speech pricing page&lt;/A&gt; before committing.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And if you would rather deploy a dedicated transcription model such as whisper, Foundry gives you the flexibility to do just that. Open the model page in the catalogue, click Deploy, and go with Default settings unless you need custom quotas or guardrails:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;H1&gt;Let's test the setup&lt;/H1&gt;
&lt;P&gt;On your Plaud device, just tap to start recording. The little LED bars light up to show it is listening:&lt;/P&gt;
&lt;img&gt;Plaud Note Pro physical device&lt;/img&gt;
&lt;P&gt;Or skip the device entirely and upload an audio file straight into Riffado using the Upload Audio button. Either way, the recording lands on the Recordings page; hit Transcribe and let the spinner do its thing:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As you can see below, whisper, the transcription model we deployed earlier, even managed to transcribe a recording in Malay without a hitch. My 3:32 test clip came back as 186 words of clean Malay, with the language correctly detected and tagged:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;img /&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have also set o3-mini as the enhancement provider, and it enhanced the transcription with a proper summary, key points, and title as well! The Meeting Notes-style summary came straight out of o3-mini through the shim, with zero manual prompting.&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;
&lt;img /&gt;
&lt;H1&gt;Wrapping up&lt;/H1&gt;
&lt;P&gt;What started as a TikTok-fuelled impulse buy nearly killed off by subscription pricing ended up as a fully self-hosted pipeline: Plaud for recording, Riffado as the interface, and Microsoft Foundry serving whisper and o3-mini behind two tiny shims. The total extra infrastructure came to two containers and roughly sixty lines of code, and not a single monthly subscription in sight.&lt;/P&gt;
&lt;P&gt;If you try this setup and run into a failure mode I have not covered here, do share it in the comments. Half the fun is in the debugging.&lt;/P&gt;</description>
      <pubDate>Wed, 22 Jul 2026 14:59:24 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/set-up-plaud-note-pro-with-microsoft-foundry/ba-p/4537428</guid>
      <dc:creator>suzarilshah</dc:creator>
      <dc:date>2026-07-22T14:59:24Z</dc:date>
    </item>
    <item>
      <title>Microsoft Agent Framework Multi-Agent Workflow Architecture for Automated Kubernetes Assessments</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/microsoft-agent-framework-multi-agent-workflow-architecture-for/ba-p/4538371</link>
      <description>&lt;H2&gt;Why this system generates tests (design rationale)&lt;/H2&gt;
&lt;P&gt;This project does not generate tests just to "check code." It generates tests because, in a Kubernetes learning game, the test suite&amp;nbsp;&lt;EM&gt;is the grading contract&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;The design goals are:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Scale content creation&lt;/STRONG&gt;: instructors should not hand-author every task and checker.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Keep grading objective&lt;/STRONG&gt;: student success is measured against Kubernetes API state, not subjective review.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Avoid fragile tasks&lt;/STRONG&gt;: generated tasks must survive empty/wrong cluster states without crashing.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Make failures repairable&lt;/STRONG&gt;: when checks break, the system should patch and re-validate automatically.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;So the pipeline generates a full task package (setup,&amp;nbsp;answer,&amp;nbsp;check,&amp;nbsp;cleanup) where tests define exactly what "correct" means.&lt;/P&gt;
&lt;H2&gt;Lifecycle: from concept to production-ready grader&lt;/H2&gt;
&lt;P&gt;Reader mental model: this is a&amp;nbsp;&lt;STRONG&gt;content compiler&lt;/STRONG&gt;&amp;nbsp;with validation stages, not a single chat completion.&lt;/P&gt;
&lt;img /&gt;
&lt;H3&gt;Phase 1: Pedagogical intent -&amp;gt; structured concept&lt;/H3&gt;
&lt;P&gt;The Idea Agent converts a topic into a constrained concept object (objective, progression, task IDs, difficulty variants). Memory rules block duplicates and previously failed concepts.&lt;/P&gt;
&lt;H3&gt;Phase 2: Concept -&amp;gt; executable grading package&lt;/H3&gt;
&lt;P&gt;The Generator Agent turns that concept into files:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;student instructions (instruction.md)&lt;/LI&gt;
&lt;LI&gt;learning material (concept.md)&lt;/LI&gt;
&lt;LI&gt;parameter source (session.json)&lt;/LI&gt;
&lt;LI&gt;setup and answer manifests (setup.template.yaml,&amp;nbsp;answer.template.yaml)&lt;/LI&gt;
&lt;LI&gt;deterministic pytest flow (test_01&amp;nbsp;...&amp;nbsp;test_06)&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;At this point, output is still untrusted draft content.&lt;/P&gt;
&lt;H3&gt;Phase 3: Structural correctness gate&lt;/H3&gt;
&lt;P&gt;Deterministic validation checks file presence, syntax, JSON/YAML shape, and template correctness. This catches basic integrity issues before cluster execution.&lt;/P&gt;
&lt;H3&gt;Phase 4: Behavioral correctness gate (real cluster)&lt;/H3&gt;
&lt;P&gt;Pytest executes against Kubernetes and verifies runtime behavior using real&amp;nbsp;kubectl-derived state. This proves that generated checks actually evaluate cluster resources as intended.&lt;/P&gt;
&lt;H3&gt;Phase 5: Anti-false-positive gate (skip-answer mode)&lt;/H3&gt;
&lt;P&gt;The same suite runs with&amp;nbsp;SKIP_ANSWER_TESTS=True&amp;nbsp;to verify grader integrity:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;answer deployment is skipped&lt;/LI&gt;
&lt;LI&gt;test_05_check.py&amp;nbsp;must fail&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;If it still passes, the grader is invalid (it would accept wrong student submissions).&lt;/P&gt;
&lt;H3&gt;Phase 6: Self-healing repair loop&lt;/H3&gt;
&lt;P&gt;On any failure, deterministic error logs are fed into the Fixer Agent, which patches only broken files. The workflow then re-enters validation + test gates.&lt;/P&gt;
&lt;H3&gt;Phase 7: Finalization&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;If all gates pass -&amp;gt; task is kept as production-ready content.&lt;/LI&gt;
&lt;LI&gt;If retries are exhausted -&amp;gt; task is moved to&amp;nbsp;unsuccessful/&amp;nbsp;with&amp;nbsp;FAILURE_REPORT.txt&amp;nbsp;for human triage.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;This lifecycle explains the core architecture decision:&amp;nbsp;&lt;STRONG&gt;LLMs generate candidate graders, deterministic execution certifies them.&lt;/STRONG&gt;&lt;/P&gt;
&lt;H2&gt;Concrete generated sample (what the pipeline actually produces)&lt;/H2&gt;
&lt;P&gt;Below is a representative generated task for topic:&amp;nbsp;&lt;STRONG&gt;ConfigMap Environment Variable Injection&lt;/STRONG&gt;.&lt;/P&gt;
&lt;H3&gt;Generated directory layout&lt;/H3&gt;
&lt;LI-CODE lang="markdown"&gt;tests/game01/050_configmap_env_injection/
├── __init__.py
├── instruction.md
├── concept.md
├── session.json
├── setup.template.yaml
├── answer.template.yaml
├── test_01_setup.py
├── test_02_ready.py
├── test_03_answer.py
├── test_05_check.py
└── test_06_cleanup.py&lt;/LI-CODE&gt;
&lt;H3&gt;session.json (runtime variables)&lt;/H3&gt;
&lt;LI-CODE lang="json"&gt;{
  "namespace": "{{random_name()}}{{random_number(100,999)}}{{student_id()}}",
  "configmap_name": "{{random_name()}}",
  "deployment_name": "{{random_name()}}",
  "container_name": "app",
  "env_key": "APP_MODE",
  "env_value": "production"
}&lt;/LI-CODE&gt;
&lt;P&gt;Why this exists: task values are randomized per student/session, so tests verify behavior by variable contract instead of hardcoded names.&lt;/P&gt;
&lt;H3&gt;setup.template.yaml&amp;nbsp;(baseline state only)&lt;/H3&gt;
&lt;LI-CODE lang="yaml"&gt;apiVersion: v1
kind: Namespace
metadata:
  name: {{ namespace }}&lt;/LI-CODE&gt;
&lt;P&gt;Why this exists: setup should create prerequisites only. It must not accidentally include the final answer.&lt;/P&gt;
&lt;H3&gt;answer.template.yaml (expected correct solution)&lt;/H3&gt;
&lt;LI-CODE lang="yaml"&gt;apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ configmap_name }}
  namespace: {{ namespace }}
data:
  {{ env_key }}: "{{ env_value }}"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ deployment_name }}
  namespace: {{ namespace }}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: env-demo
  template:
    metadata:
      labels:
        app: env-demo
    spec:
      containers:
        - name: {{ container_name }}
          image: nginx:latest
          env:
            - name: {{ env_key }}
              valueFrom:
                configMapKeyRef:
                  name: {{ configmap_name }}
                  key: {{ env_key }}&lt;/LI-CODE&gt;
&lt;P&gt;Why this exists: defines canonical "correct cluster state" that graders must detect.&lt;/P&gt;
&lt;H3&gt;test_02_ready.py (wait for setup resources)&lt;/H3&gt;
&lt;LI-CODE lang="python"&gt;import json
import time
from tests.helper.kubectrl_helper import build_kube_config, run_kubectl_command


class TestReady:
    def test_001_namespace_active(self, json_input):
        kube_config = build_kube_config(
            json_input["cert_file"], json_input["key_file"], json_input["host"]
        )
        time.sleep(2)
        result = run_kubectl_command(
            kube_config,
            f"kubectl get namespace {json_input['namespace']} -o json",
        )
        data = json.loads(result)
        assert data.get("status", {}).get("phase") == "Active"&lt;/LI-CODE&gt;
&lt;P&gt;Why this matters: validates setup-stage readiness only. It should not check answer resources yet.&lt;/P&gt;
&lt;H3&gt;test_05_check.py (student grading contract)&lt;/H3&gt;
&lt;LI-CODE lang="python"&gt;import json
from tests.helper.kubectrl_helper import build_kube_config, run_kubectl_command


class TestCheck:
    def test_001_configmap_key_exists(self, json_input):
        kube_config = build_kube_config(
            json_input["cert_file"], json_input["key_file"], json_input["host"]
        )
        result = run_kubectl_command(
            kube_config,
            f"kubectl get configmap {json_input['configmap_name']} -n {json_input['namespace']} -o json",
        )
        data = json.loads(result)
        assert data["data"][json_input["env_key"]] == json_input["env_value"]

    def test_002_deployment_uses_configmap_env(self, json_input):
        kube_config = build_kube_config(
            json_input["cert_file"], json_input["key_file"], json_input["host"]
        )
        result = run_kubectl_command(
            kube_config,
            f"kubectl get deployment {json_input['deployment_name']} -n {json_input['namespace']} -o json",
        )
        data = json.loads(result)
        env = data["spec"]["template"]["spec"]["containers"][0].get("env", [])
        matched = [
            e for e in env
            if e.get("name") == json_input["env_key"]
            and e.get("valueFrom", {}).get("configMapKeyRef", {}).get("name") == json_input["configmap_name"]
            and e.get("valueFrom", {}).get("configMapKeyRef", {}).get("key") == json_input["env_key"]
        ]
        assert matched, "Deployment container must consume env var from ConfigMap key"&lt;/LI-CODE&gt;
&lt;P&gt;Why this matters: this is the real grading logic. If a student deploys wrong resource wiring, this test fails with explicit reason.&lt;/P&gt;
&lt;H3&gt;Why skip-answer validation is essential for this sample&lt;/H3&gt;
&lt;P&gt;When&amp;nbsp;SKIP_ANSWER_TESTS=True, answer deployment is skipped. In this mode:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;test_03_answer.py&amp;nbsp;should be skipped&lt;/LI&gt;
&lt;LI&gt;test_05_check.py&amp;nbsp;must fail (ConfigMap/Deployment wiring is absent)&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;If&amp;nbsp;test_05_check.py&amp;nbsp;still passes, the grader is broken (false positive), and the workflow routes to Fixer.&lt;/P&gt;
&lt;H2&gt;Rule Builder Workflow Flowchart&lt;/H2&gt;
&lt;img /&gt;
&lt;H2&gt;Multi-graph architecture views&lt;/H2&gt;
&lt;H3&gt;1) Control-plane graph (orchestration DAG)&lt;/H3&gt;
&lt;img /&gt;
&lt;H3&gt;2) Runtime sequence (who calls what)&lt;/H3&gt;
&lt;img /&gt;
&lt;H3&gt;3) State machine (task lifecycle)&lt;/H3&gt;
&lt;img /&gt;
&lt;H3&gt;4) Prompt lifecycle graph (how prompts evolve)&lt;/H3&gt;
&lt;img /&gt;
&lt;H3&gt;5) MCP + Kubernetes execution boundary graph&lt;/H3&gt;
&lt;img /&gt;
&lt;H2&gt;Core Agent Framework Primitives Used&lt;/H2&gt;
&lt;P&gt;This repository is a practical example of Agent Framework as a graph orchestrator, not just an agent wrapper.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;WorkflowBuilder&lt;/STRONG&gt;&amp;nbsp;builds a typed DAG with explicit edges.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;@executor&amp;nbsp;functions&lt;/STRONG&gt;&amp;nbsp;implement deterministic nodes (validation, pytest, decisions, routing prep).&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;AgentExecutor&lt;/STRONG&gt;&amp;nbsp;wraps LLM agents so they behave as graph nodes.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;WorkflowContext&amp;nbsp;shared state&lt;/STRONG&gt;&amp;nbsp;carries typed data and retry metadata between nodes.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;add_multi_selection_edge_group(...)&amp;nbsp;+ selector functions&lt;/STRONG&gt;&amp;nbsp;enforce conditional routing.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;MCPStdioTool&lt;/STRONG&gt;&amp;nbsp;connects filesystem MCP tools into agents for controlled file I/O.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;Production graph construction (from workflow/builder.py) looks like this:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;workflow = (
    WorkflowBuilder(start_executor=initialize_retry)
    .add_edge(initialize_retry, generator_executor)
    .add_edge(generator_executor, parse_generated_task)
    .add_edge(parse_generated_task, run_validation)
    .add_edge(run_validation, run_pytest)
    .add_edge(run_pytest, make_decision)
    .add_multi_selection_edge_group(
        make_decision,
        [keep_task, remove_task],
        selection_func=select_action,
    )
    .add_edge(keep_task, run_pytest_skip_answer)
    .add_multi_selection_edge_group(
        run_pytest_skip_answer,
        [check_loop, complete_workflow],
        selection_func=select_skip_answer_action,
    )
    .add_multi_selection_edge_group(
        check_loop,
        [fix_task, complete_workflow],
        selection_func=select_loop_action,
    )
    .add_edge(fix_task, fixer_executor)
    .add_edge(fixer_executor, parse_generated_task)
    .build()
)&lt;/LI-CODE&gt;
&lt;P&gt;This is the architectural heart of the system: agents and deterministic executors are first-class nodes in the same graph.&lt;/P&gt;
&lt;H2&gt;Detailed Node-by-Node Mechanics&lt;/H2&gt;
&lt;H3&gt;1. Idea Agent (🧠): Concept Synthesis with Memory Constraints&lt;/H3&gt;
&lt;P&gt;The Idea Agent (agents/k8s_task_idea_agent.py) generates a structured concept with three difficulty variations (BEGINNER/INTERMEDIATE/ADVANCED). It is memory-aware:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;task_ideas_memory.json&amp;nbsp;tracks successful concepts.&lt;/LI&gt;
&lt;LI&gt;task_ideas_failure_memory.json&amp;nbsp;tracks concepts that failed downstream.&lt;/LI&gt;
&lt;LI&gt;Memory constraints are injected using&amp;nbsp;AgentMiddleware&amp;nbsp;(system-level prompt injection) to avoid duplicate or previously failed concepts.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;For Responses-only models, the agent switches to a tool-call contract (save_k8s_task_concept) instead of structured response formatting.&lt;/P&gt;
&lt;H3&gt;2. Generator Agent (⚙️): MCP-Backed File Authoring&lt;/H3&gt;
&lt;P&gt;The Generator Agent receives a strict prompt and writes task files through MCP filesystem tools. Key framework details:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Built through&amp;nbsp;chat_client.as_agent(...).&lt;/LI&gt;
&lt;LI&gt;MCP tool attached via&amp;nbsp;tools=mcp_tool.&lt;/LI&gt;
&lt;LI&gt;Function-call execution observability added with&amp;nbsp;LoggingFunctionMiddleware.&lt;/LI&gt;
&lt;LI&gt;Uses absolute-path-only policy in instructions to prevent path drift.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;3. Deterministic Validation + Test (✅): Non-LLM Gates&lt;/H3&gt;
&lt;P&gt;After generation, the graph moves through deterministic executors:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;run_validation&amp;nbsp;calls pure Python checks (k8s_task_validator).&lt;/LI&gt;
&lt;LI&gt;run_pytest&amp;nbsp;executes&amp;nbsp;pytest --import-mode=importlib --rootdir=. ....&lt;/LI&gt;
&lt;LI&gt;Raw pytest output is persisted in workflow state for later fixing.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;This is critical: no LLM is asked whether code is correct.&lt;/P&gt;
&lt;H3&gt;4. Skip-Answer Test (🧪): Grader Correctness Gate&lt;/H3&gt;
&lt;P&gt;Even if standard tests pass, the workflow enforces a second tier:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;SKIP_ANSWER_TESTS=True pytest --import-mode=importlib --rootdir=.&lt;/LI-CODE&gt;
&lt;P&gt;Implementation detail: the executor writes JUnit XML, parses it, and asserts that:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;test_03_answer.py&amp;nbsp;is skipped&lt;/LI&gt;
&lt;LI&gt;test_05_check.py&amp;nbsp;fails as expected&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;If&amp;nbsp;test_05_check.py&amp;nbsp;does&amp;nbsp;&lt;STRONG&gt;not&lt;/STRONG&gt;&amp;nbsp;fail, the task is treated as invalid and sent back to retry/fix.&lt;/P&gt;
&lt;H3&gt;5. Fixer Agent + Retry Loop (🔧): Bounded Self-Healing&lt;/H3&gt;
&lt;P&gt;On failure,&amp;nbsp;fix_task&amp;nbsp;builds a targeted prompt containing:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;failure reasons from deterministic nodes&lt;/LI&gt;
&lt;LI&gt;full captured pytest output&lt;/LI&gt;
&lt;LI&gt;explicit rule to patch only broken files in place&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The Fixer Agent runs through&amp;nbsp;AgentExecutor, writes patches via MCP, and the graph loops back to&amp;nbsp;parse_generated_task.&lt;/P&gt;
&lt;P&gt;Retries are stateful (retry_count,&amp;nbsp;max_retries) and hard-bounded. On exhaustion,&amp;nbsp;complete_workflow&amp;nbsp;moves the task to&amp;nbsp;unsuccessful/&amp;lt;game&amp;gt;/&amp;nbsp;and writes&amp;nbsp;FAILURE_REPORT.txt.&lt;/P&gt;
&lt;H2&gt;Agent Prompt Design (The Part That Makes It Work)&lt;/H2&gt;
&lt;P&gt;If you want to understand&amp;nbsp;&lt;EM&gt;why&lt;/EM&gt;&amp;nbsp;this pipeline works, you need to inspect prompts as&amp;nbsp;&lt;STRONG&gt;operational contracts&lt;/STRONG&gt;, not generic instructions.&lt;/P&gt;
&lt;H3&gt;Real Idea Agent Prompt (from code)&lt;/H3&gt;
&lt;LI-CODE lang="python"&gt;IDEA_AGENT_INSTRUCTIONS = (
    "You are a Kubernetes task idea generator that creates detailed task concepts with three difficulty variations. "
    "Read official K8s documentation and propose comprehensive learning concepts for a Kubernetes game. "
    "\n\nYour task:\n"
    "1. Choose ONE Kubernetes concept not yet covered (check context for existing concepts)\n"
    "2. Generate exactly 3 variations: BEGINNER, INTERMEDIATE, and ADVANCED\n"
    "3. Use 3-digit task IDs (001-999) in format: XXX_concept_name_level (e.g., 041_secrets_basic)\n"
    "4. Each variation should build on the previous one with increasing complexity\n"
    "5. Include practical, hands-on scenarios covering: Workloads, Services, Storage, Configuration, Security, Scheduling, Policies\n"
    "\nProvide the concept, tags, description, and 3 variations with task_id, difficulty, title, objective, key_skills, and estimated_time."
)&lt;/LI-CODE&gt;
&lt;P&gt;Responses-only models use a stricter tool-call version:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;IDEA_AGENT_INSTRUCTIONS_TOOL_CALL = (
    IDEA_AGENT_INSTRUCTIONS + "\n\n"
    "**CRITICAL**: You MUST call the save_k8s_task_concept tool to save your generated concept.\n"
    "...\n"
    "Always call save_k8s_task_concept with your generated concept."
)&lt;/LI-CODE&gt;
&lt;H3&gt;Idea Agent Prompt Contract&lt;/H3&gt;
&lt;P&gt;The Idea Agent prompt enforces:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;one concept per run&lt;/LI&gt;
&lt;LI&gt;exactly three difficulty variations&lt;/LI&gt;
&lt;LI&gt;strict task ID format (XXX_concept_name_level)&lt;/LI&gt;
&lt;LI&gt;practical skill progression&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Core pattern:&lt;/P&gt;
&lt;LI-CODE lang=""&gt;You are a Kubernetes task idea generator...
1. Choose ONE Kubernetes concept not yet covered
2. Generate exactly 3 variations: BEGINNER, INTERMEDIATE, ADVANCED
3. Use 3-digit task IDs in format XXX_concept_name_level
...&lt;/LI-CODE&gt;
&lt;P&gt;It is strengthened by runtime memory injection:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;previously generated concepts are blocked&lt;/LI&gt;
&lt;LI&gt;previously failed concepts are blocked&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;For Responses-only models, the contract becomes tool-driven:&lt;/P&gt;
&lt;LI-CODE lang=""&gt;CRITICAL: You MUST call the save_k8s_task_concept tool...&lt;/LI-CODE&gt;
&lt;P&gt;This reduces ambiguity in output structure and makes downstream parsing deterministic.&lt;/P&gt;
&lt;H3&gt;Real Generator Agent Prompt (from code)&lt;/H3&gt;
&lt;LI-CODE lang="python"&gt;def _get_generator_instructions():
    return (
        "You are a Kubernetes task generator with filesystem tools.\n"
        f"The MCP filesystem is rooted at: {PATHS.tests_root.parent}\n"
        f"You MUST use ABSOLUTE paths for ALL file operations.\n"
        f"Task directory: {PATHS.game_root}/XXX_task_name/\n"
        "...\n"
        "CRITICAL: test_02_ready.py checks resources from setup.template.yaml, NOT answer.template.yaml.\n"
        "...\n"
        "MUST use polling loops (60s timeout, 15s interval)\n"
        "MUST use try/except and safe .get() JSON access\n"
    )&lt;/LI-CODE&gt;
&lt;P&gt;The generator prompt is long on purpose: it encodes path correctness, file schema, YAML/Jinja structure, and testing strategy in a single deterministic contract.&lt;/P&gt;
&lt;H3&gt;Generator Agent Prompt Contract&lt;/H3&gt;
&lt;P&gt;The Generator prompt is intentionally long and prescriptive because it defines filesystem safety and grading correctness requirements.&lt;/P&gt;
&lt;P&gt;Key constraints encoded in the prompt:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Absolute path writes only&lt;/STRONG&gt;&amp;nbsp;(prevents writing to wrong workspace paths)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;No directory creation&lt;/STRONG&gt;&amp;nbsp;(directory is pre-created by executor)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Required file set&lt;/STRONG&gt;&amp;nbsp;(instruction.md,&amp;nbsp;concept.md,&amp;nbsp;session.json, templates, tests)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;test-flow invariants&lt;/STRONG&gt;:
&lt;UL&gt;
&lt;LI&gt;test_01_setup.py&amp;nbsp;deploys setup&lt;/LI&gt;
&lt;LI&gt;test_02_ready.py&amp;nbsp;checks setup resources only&lt;/LI&gt;
&lt;LI&gt;test_03_answer.py&amp;nbsp;deploys answer&lt;/LI&gt;
&lt;LI&gt;test_05_check.py&amp;nbsp;validates final solution&lt;/LI&gt;
&lt;/UL&gt;
&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;robust test coding style&lt;/STRONG&gt;: polling loops, try/except,&amp;nbsp;.get()-based JSON parsing, explicit debug output&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;Example contract fragment:&lt;/P&gt;
&lt;LI-CODE lang=""&gt;CRITICAL PATH RULES:
✅ CORRECT: /abs/path/tests/gameXX/050_task/file.py
❌ WRONG: tests/gameXX/050_task/file.py (relative)

CRITICAL: test_02_ready.py checks resources from setup.template.yaml,
NOT answer.template.yaml.&lt;/LI-CODE&gt;
&lt;P&gt;This is why generation quality is high before the Fixer loop even starts.&lt;/P&gt;
&lt;H3&gt;Real Runtime Retry Prompt Builder (from code)&lt;/H3&gt;
&lt;LI-CODE lang="python"&gt;def _build_retry_generation_prompt(combined: CombinedValidationResult) -&amp;gt; str:
    task_id = combined.test.task_id
    failure_reasons = _build_failure_reasons(combined)
    return (
        f"Generate a complete Kubernetes learning task with ID '{task_id}' about '{combined.target_topic}'. "
        f"This is retry attempt {combined.retry_count + 1} of {combined.max_retries}. "
        f"\n\n⚠️  PREVIOUS ATTEMPT FAILED:"
        f"\n{chr(10).join([f'  - {reason}' for reason in failure_reasons])}"
        f"\n\nIMPORTANT: You MUST use the exact task ID '{task_id}' - do not generate a new ID."
        f"\n\n✅ Directory already exists: {PATHS.game_root}/{task_id}/"
        f"\nWrite all files directly into this directory. Do NOT call create_directory."
        "..."
    )&lt;/LI-CODE&gt;
&lt;P&gt;This means retries are not generic retries; they are failure-conditioned retries with precise constraints.&lt;/P&gt;
&lt;H3&gt;Fixer Agent Prompt Contract&lt;/H3&gt;
&lt;P&gt;The Fixer prompt is a repair protocol, not a regeneration prompt. It includes:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;exact failure reasons from deterministic validators&lt;/LI&gt;
&lt;LI&gt;raw pytest output&lt;/LI&gt;
&lt;LI&gt;instruction to read current task files first&lt;/LI&gt;
&lt;LI&gt;strict directive to patch only broken files&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Core behavior constraints:&lt;/P&gt;
&lt;LI-CODE lang=""&gt;DO NOT rewrite all files.
Make TARGETED FIXES to ONLY the broken files.
Use ABSOLUTE paths for all file operations.&lt;/LI-CODE&gt;
&lt;P&gt;This keeps retries cheap, preserves working artifacts, and improves convergence speed.&lt;/P&gt;
&lt;H3&gt;Real Runtime Fix Prompt Builder (from code)&lt;/H3&gt;
&lt;LI-CODE lang="python"&gt;def _build_fix_prompt(combined: CombinedValidationResult, raw_test_output: str) -&amp;gt; str:
    task_id = combined.test.task_id
    failure_reasons = _build_failure_reasons(combined)
    prompt = (
        f"Fix the failed Kubernetes task '{task_id}' located in '{PATHS.game_root}/{task_id}/'."
        f"\n\nThis is fix attempt {combined.retry_count + 1} of {combined.max_retries}."
        f"\n\n⚠️  TASK FAILED WITH THESE ERRORS:"
        f"\n{chr(10).join([f'  - {reason}' for reason in failure_reasons])}"
    )
    if raw_test_output:
        prompt += f"\n\n📋 FULL TEST OUTPUT:\n```\n{raw_test_output}\n```"
    prompt += (
        f"\n\n🔍 YOUR TASK:"
        f"\n1. READ all files from '{PATHS.game_root}/{task_id}/'"
        f"\n6. Make TARGETED FIXES to ONLY the broken files"
        f"\n7. WRITE ONLY the fixed files back"
        f"\n\n⚠️  CRITICAL: DO NOT rewrite all files! Only fix the broken ones!"
    )
    return prompt&lt;/LI-CODE&gt;
&lt;H3&gt;How Prompt Output Enters the Agent Framework Graph&lt;/H3&gt;
&lt;P&gt;The prompt builders above are used by deterministic executors and sent to agent nodes through AgentExecutorRequest:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;await ctx.send_message(
    AgentExecutorRequest(
        messages=[Message(role="user", contents=[fix_prompt])],
        should_respond=True
    )
)&lt;/LI-CODE&gt;
&lt;P&gt;So prompt generation and graph routing are tightly coupled: each route transition emits a specific prompt payload into the next LLM node.&lt;/P&gt;
&lt;H3&gt;Runtime-Constructed Prompts in Executors&lt;/H3&gt;
&lt;P&gt;The most important prompts are built dynamically in workflow executors:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;_build_retry_generation_prompt(...)&lt;/LI&gt;
&lt;LI&gt;_build_fix_prompt(...)&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;These functions inject live context:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;retry_count&amp;nbsp;/&amp;nbsp;max_retries&lt;/LI&gt;
&lt;LI&gt;concept + objective metadata&lt;/LI&gt;
&lt;LI&gt;validation/test failure reasons&lt;/LI&gt;
&lt;LI&gt;full captured test logs&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;So each retry is context-rich and specific, not another blind generation attempt.&lt;/P&gt;
&lt;H3&gt;Prompt + Middleware + Deterministic Gates = Reliability&lt;/H3&gt;
&lt;P&gt;In this repository, reliability does&amp;nbsp;&lt;STRONG&gt;not&lt;/STRONG&gt;&amp;nbsp;come from prompt text alone. It comes from three layers working together:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Prompt contracts constrain agent behavior.&lt;/LI&gt;
&lt;LI&gt;Middleware injects memory and logs tool invocations.&lt;/LI&gt;
&lt;LI&gt;Deterministic executors enforce objective pass/fail gates.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;That combination is why the workflow remains auditable and predictable even when LLM outputs vary.&lt;/P&gt;
&lt;H2&gt;Agent Framework Execution Model in This Repo&lt;/H2&gt;
&lt;H2&gt;Strongly-Typed Message Passing&lt;/H2&gt;
&lt;P&gt;workflow/models.py&amp;nbsp;defines transport models used between nodes:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;ValidationResult&amp;nbsp;and&amp;nbsp;TestResult&amp;nbsp;(Pydantic)&lt;/LI&gt;
&lt;LI&gt;CombinedValidationResult&amp;nbsp;(dataclass with&amp;nbsp;should_keep&amp;nbsp;and&amp;nbsp;should_retry)&lt;/LI&gt;
&lt;LI&gt;InitialWorkflowState&amp;nbsp;(seed payload for each run)&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;This keeps node contracts explicit and simplifies selector logic.&lt;/P&gt;
&lt;H2&gt;Fail-Fast Shared State Management&lt;/H2&gt;
&lt;P&gt;Executors use&amp;nbsp;ctx.get_state(...)&amp;nbsp;with a sentinel (_MISSING) and raise explicit exceptions if required state is absent. This prevents hidden fallback behavior and catches graph/data wiring errors early.&lt;/P&gt;
&lt;H2&gt;Conditional Routing with Selectors&lt;/H2&gt;
&lt;P&gt;Selectors (workflow/selectors.py) encode graph decisions:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;select_action&amp;nbsp;→ keep vs remove&lt;/LI&gt;
&lt;LI&gt;select_skip_answer_action&amp;nbsp;→ complete vs loop&lt;/LI&gt;
&lt;LI&gt;select_loop_action&amp;nbsp;→ fix vs complete&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;This separates decision policy from executor implementation.&lt;/P&gt;
&lt;H2&gt;Streaming Workflow Runtime&lt;/H2&gt;
&lt;P&gt;workflow.run(initial_state, stream=True)&amp;nbsp;emits output events incrementally. The runner (workflow/runner.py) consumes these events to detect successful completions and update concept memory accordingly.&lt;/P&gt;
&lt;H2&gt;Agent Construction and API Selection Strategy&lt;/H2&gt;
&lt;P&gt;The repository uses Azure CLI auth (AzureCliCredential) and dynamically selects API mode by deployment name (agents/config.py):&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Chat Completions path&lt;/STRONG&gt;:&amp;nbsp;OpenAIChatCompletionClient&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Responses-only model path&lt;/STRONG&gt;:&amp;nbsp;OpenAIChatClient&amp;nbsp;or custom&amp;nbsp;ResponsesAgent&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Why this matters: some codex-class deployments are Responses-only, so the architecture supports both without changing workflow logic.&lt;/P&gt;
&lt;H2&gt;How MCP Actually Controls Kubernetes (Important Distinction)&lt;/H2&gt;
&lt;P&gt;In this repo, MCP is used for&amp;nbsp;&lt;STRONG&gt;filesystem control&lt;/STRONG&gt;; Kubernetes control is done through&amp;nbsp;&lt;STRONG&gt;kubectl tools&lt;/STRONG&gt;.&lt;/P&gt;
&lt;H2&gt;1) MCP server role: controlled file I/O&lt;/H2&gt;
&lt;P&gt;The workflow starts MCP stdio servers (official filesystem server) and mounts them into agents:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;docs_mcp_tool = MCPStdioTool(
    name="filesystem_docs",
    command="npx",
    args=["-y", "@modelcontextprotocol/server-filesystem", str(PATHS.k8s_docs_root)],
    load_prompts=False,
)

tests_mcp_tool = MCPStdioTool(
    name="filesystem_tests",
    command="npx",
    args=["-y", "@modelcontextprotocol/server-filesystem", str(PATHS.tests_root.parent)],
    load_prompts=False,
)&lt;/LI-CODE&gt;
&lt;P&gt;Those MCP tools are passed into Generator/Fixer agents, which then call MCP file functions (read/write/list) inside allowed roots only.&lt;/P&gt;
&lt;H2&gt;2) Kubernetes cluster control role: kubectl execution tool&lt;/H2&gt;
&lt;P&gt;Cluster actions are not performed by MCP filesystem server; they are performed by a dedicated function tool:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;def run_kubectl_command(command: str) -&amp;gt; str:
    kubeconfig_path = os.environ.get("KUBECONFIG", "/home/developer/.kube/config")
    cmd_list = ["kubectl"] + command.split()
    result = subprocess.run(
        cmd_list,
        capture_output=True,
        text=True,
        check=True,
        env={**os.environ, "KUBECONFIG": kubeconfig_path},
    )
    return result.stdout&lt;/LI-CODE&gt;
&lt;P&gt;And the Kubernetes agent forces tool usage:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;agent = responses_client.as_agent(
    name="KubernetesAgent",
    instructions="...You MUST use the run_kubectl_command tool...",
    tools=[run_kubectl_command],
    default_options={"tool_choice": "required"},
)&lt;/LI-CODE&gt;
&lt;P&gt;So the control plane is:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;MCP filesystem&lt;/STRONG&gt;&amp;nbsp;→ manipulate generated task files.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;kubectl tool&lt;/STRONG&gt;&amp;nbsp;→ query/mutate real cluster state.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;deterministic pytest/validator executors&lt;/STRONG&gt;&amp;nbsp;→ accept or reject results.&lt;/LI&gt;
&lt;/OL&gt;
&lt;H2&gt;3) End-to-end command flow in practice&lt;/H2&gt;
&lt;P&gt;When generated tests run, they execute real&amp;nbsp;kubectl get ... -o json&amp;nbsp;checks in test code, and the deterministic runner captures raw output:&lt;/P&gt;
&lt;P&gt;pytest_command = f"pytest --import-mode=importlib --rootdir=. {task_with_val.task_directory}/" result = run_pytest_command(pytest_command) ctx.set_state(f"raw_output_{task_with_val.task_id}", raw_output)&lt;/P&gt;
&lt;P&gt;This means Kubernetes state verification is always grounded in live command output, not model speculation.&lt;/P&gt;
&lt;H2&gt;Should MCP run Kubernetes tests?&lt;/H2&gt;
&lt;P&gt;Short answer:&amp;nbsp;&lt;STRONG&gt;not in this design&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;Current architecture keeps test execution deterministic and local:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;pytest is run by&amp;nbsp;run_pytest_command(...)&amp;nbsp;(pure Python subprocess runner)&lt;/LI&gt;
&lt;LI&gt;test results are parsed and stored in workflow state&lt;/LI&gt;
&lt;LI&gt;retry/fix routing uses those deterministic outputs&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;This is intentional. If test execution were delegated to an LLM-facing MCP command tool, you would lose strict control over execution semantics and error handling.&lt;/P&gt;
&lt;P&gt;Recommended pattern:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Use MCP for file/document access and controlled editing.&lt;/LI&gt;
&lt;LI&gt;Use deterministic executors for pytest and validation.&lt;/LI&gt;
&lt;LI&gt;Use LLM agents only for generation and repair.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;If you still want MCP-driven test execution, add a&amp;nbsp;&lt;STRONG&gt;separate locked-down command MCP server&lt;/STRONG&gt;&amp;nbsp;(only whitelisted pytest/kubectl commands), but keep pass/fail decision logic in deterministic executors.&lt;/P&gt;
&lt;H2&gt;How tests are run in this workflow (with code)&lt;/H2&gt;
&lt;P&gt;The workflow executes tests in deterministic executors, not inside LLM agents.&lt;/P&gt;
&lt;H3&gt;1) Workflow node calls pytest runner&lt;/H3&gt;
&lt;P&gt;run_pytest executor builds the command and calls the pure Python runner:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;@executor(id="run_pytest")
async def run_pytest(task_with_val: TaskWithValidation, ctx: WorkflowContext[TestResult]) -&amp;gt; None:
    from agents.pytest_runner import run_pytest_command

    pytest_command = f"pytest --import-mode=importlib --rootdir=. {task_with_val.task_directory}/"
    result = run_pytest_command(pytest_command)

    raw_output = result["details"][0] if result.get("details") else ""
    ctx.set_state(f"raw_output_{task_with_val.task_id}", raw_output)
    ...&lt;/LI-CODE&gt;
&lt;H3&gt;2) Deterministic subprocess execution&lt;/H3&gt;
&lt;P&gt;The runner normalizes command flags and executes pytest via subprocess:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;def run_pytest_command(command: str) -&amp;gt; dict[str, Any]:
    normalized_command = _normalize_pytest_command(command)  # adds -s if needed
    cmd_list = shlex.split(normalized_command)
    result = subprocess.run(
        cmd_list,
        capture_output=True,
        text=True,
        check=False,
        cwd=str(PATHS.pytest_rootdir),
    )
    combined_output = result.stdout + "\n" + result.stderr
    _save_test_output(normalized_command, combined_output, skip_answer)
    ...&lt;/LI-CODE&gt;
&lt;P&gt;Exit codes are interpreted deterministically:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;0&amp;nbsp;→ pass&lt;/LI&gt;
&lt;LI&gt;5&amp;nbsp;→ no tests collected (fail)&lt;/LI&gt;
&lt;LI&gt;others → fail with exit code reason&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3&gt;3) Skip-answer validation tier&lt;/H3&gt;
&lt;P&gt;After normal pass, the workflow runs pytest again with SKIP_ANSWER_TESTS=True and parses JUnit XML:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;os.environ["SKIP_ANSWER_TESTS"] = "True"
pytest_command = f"pytest --import-mode=importlib --rootdir=. --junitxml={junit_path} {task_dir}/"
result = run_pytest_command(pytest_command)
test_05_failed, test_03_skipped = _parse_skip_answer_junit(junit_path)&lt;/LI-CODE&gt;
&lt;P&gt;The parser checks per-testcase outcomes:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;if "test_05_check.py" in context and has_failure_or_error:
    test_05_failed = True
if "test_03_answer.py" in context and has_skipped:
    test_03_skipped = True&lt;/LI-CODE&gt;
&lt;H3&gt;4) How failures trigger fix loop&lt;/H3&gt;
&lt;P&gt;If pytest fails (or skip-answer logic fails), failure reasons and raw output are pushed into state, then the Fixer Agent receives a generated fix prompt containing that output:&lt;/P&gt;
&lt;LI-CODE lang="python"&gt;ctx.set_state(f"failure_reasons_{task_id}", reasons)
ctx.set_state(f"raw_output_{task_id}", raw_output)
fix_prompt = _build_fix_prompt(combined, raw_test_output)
await ctx.send_message(
    AgentExecutorRequest(
        messages=[Message(role="user", contents=[fix_prompt])],
        should_respond=True
    )
)&lt;/LI-CODE&gt;
&lt;P&gt;That is the key loop:&amp;nbsp;&lt;STRONG&gt;deterministic test output drives LLM repair&lt;/STRONG&gt;, then deterministic tests re-run.&lt;/P&gt;
&lt;H2&gt;ResponsesAgent Internals (Advanced Agent Framework Pattern)&lt;/H2&gt;
&lt;P&gt;The custom&amp;nbsp;ResponsesAgent&amp;nbsp;(agents/responses_agent.py) demonstrates a lower-level integration pattern:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Connect MCP tool lazily.&lt;/LI&gt;
&lt;LI&gt;Call Responses API.&lt;/LI&gt;
&lt;LI&gt;Parse&amp;nbsp;ResponseFunctionToolCall&amp;nbsp;items.&lt;/LI&gt;
&lt;LI&gt;Execute tools (MCP + custom callables).&lt;/LI&gt;
&lt;LI&gt;Feed&amp;nbsp;function_call_output&amp;nbsp;back to model.&lt;/LI&gt;
&lt;LI&gt;Repeat until final text response.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;It also runs a middleware chain around tool invocations, preserving observability and consistency with standard agent paths.&lt;/P&gt;
&lt;H2&gt;Why This Architecture Is Robust&lt;/H2&gt;
&lt;P&gt;This design works because Agent Framework is used as a&amp;nbsp;&lt;STRONG&gt;deterministic orchestration layer around probabilistic generation&lt;/STRONG&gt;:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;LLM creativity is constrained by typed state and strict prompts.&lt;/LI&gt;
&lt;LI&gt;deterministic executors act as objective quality gates.&lt;/LI&gt;
&lt;LI&gt;retries are targeted, bounded, and auditable.&lt;/LI&gt;
&lt;LI&gt;failures produce durable forensic artifacts (FAILURE_REPORT.txt&amp;nbsp;+ test logs).&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;For Kubernetes education pipelines, this yields high throughput without sacrificing grader reliability.&lt;/P&gt;
&lt;P&gt;GitHub Repo - &lt;A class="lia-external-url" href="https://github.com/wongcyrus/k8s-game-rule-builder" target="_blank"&gt;https://github.com/wongcyrus/k8s-game-rule-builder&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;&lt;STRONG&gt;About the Author&lt;/STRONG&gt;&lt;/H3&gt;
&lt;img /&gt;
&lt;P data-selectable-paragraph=""&gt;&lt;A href="https://www.linkedin.com/in/cyruswong/" target="_blank"&gt;Cyrus Wong&lt;/A&gt;&amp;nbsp;is the senior lecturer of&amp;nbsp;&lt;A href="https://hkiit.edu.hk/" target="_blank"&gt;Hong Kong Institute of Information Technology (HKIIT)&lt;/A&gt;&amp;nbsp;@&amp;nbsp;&lt;A href="http://lwit.vtc.edu.hk/" target="_blank"&gt;IVE(Lee Wai Lee)&lt;/A&gt;.and he focuses on teaching public Cloud technologies. He is a passionate advocate for the adoption of cloud technology across various media and events. With his extensive knowledge and expertise, he has earned prestigious recognitions such as&amp;nbsp;&lt;A href="https://aws.amazon.com/developer/community/heroes/cyrus-wong/" data-lia-auto-title-active="0" data-lia-auto-title="AWS Builder Center" target="_blank"&gt;AWS AI Hero&lt;/A&gt;,&amp;nbsp;&lt;A href="https://mvp.microsoft.com/en-US/mvp/profile/86da86ff-8786-ed11-aad1-000d3a197333" target="_blank"&gt;Microsoft MVP- Microsoft Foundry&lt;/A&gt;, and&amp;nbsp;&lt;A href="https://developers.google.com/profile/u/cyruswong" target="_blank"&gt;Google Developer Expert - Cloud(AI)&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 21 Jul 2026 07:46:08 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/microsoft-agent-framework-multi-agent-workflow-architecture-for/ba-p/4538371</guid>
      <dc:creator>cyruswong</dc:creator>
      <dc:date>2026-07-21T07:46:08Z</dc:date>
    </item>
    <item>
      <title>Building a Fully Managed Multi-Agent Pipeline with Microsoft Foundry</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/building-a-fully-managed-multi-agent-pipeline-with-microsoft/ba-p/4533757</link>
      <description>&lt;P data-path-to-node="5"&gt;Hey everyone! I am&amp;nbsp;&lt;A class="lia-external-url" href="https://linkedin.com/in/shivam2003" target="_blank" rel="noopener"&gt;&lt;STRONG data-path-to-node="5" data-index-in-node="19"&gt;Shivam Goyal&lt;/STRONG&gt;&lt;/A&gt;, a Microsoft MVP, and I am super excited to share a workshop I created that is going to save you a massive amount of time.&lt;/P&gt;
&lt;P data-path-to-node="6"&gt;Designing smart AI workflows is arguably one of the most creative and enjoyable parts of engineering. Trying to force a single, massive prompt to execute a complex, multi-step business pipeline perfectly? Not so much. We have all been there: you write a giant prompt to handle a multi-step task, only for the AI to get confused, miss critical details, and give completely different answers every time you run it.&lt;/P&gt;
&lt;P data-path-to-node="8"&gt;To solve this giant prompt problem, I built a hands-on multi-agent workshop. Today, we are looking at how you can use the &lt;A class="lia-external-url" href="https://github.com/microsoft-foundry/Foundry_Toolkit_for_VSCode_Lab" target="_blank" rel="noopener"&gt;&lt;STRONG data-path-to-node="8" data-index-in-node="122"&gt;Foundry Toolkit for VS Code&lt;/STRONG&gt;&lt;/A&gt; alongside the project blueprints I designed to build, debug, and deploy specialized multi-agent teams without any infrastructure headaches.&lt;/P&gt;
&lt;img /&gt;
&lt;H3 data-path-to-node="14"&gt;What is the Foundry Toolkit for VS Code?&lt;/H3&gt;
&lt;P data-path-to-node="15"&gt;The &lt;STRONG data-path-to-node="15" data-index-in-node="4"&gt;Foundry Toolkit for VS Code&lt;/STRONG&gt; is a unified extension that brings cloud-scale AI development right into your local code editor. Instead of constantly jumping between web portals, command lines, and code files, the toolkit gives you a single place to manage your entire AI application.&lt;/P&gt;
&lt;P data-path-to-node="16"&gt;With this toolkit installed in Visual Studio Code, you can:&lt;/P&gt;
&lt;UL data-path-to-node="17"&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="17,0,0" data-index-in-node="0"&gt;Access the Model Catalog:&lt;/STRONG&gt; Instantly browse and connect your code to leading AI models.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="17,1,0" data-index-in-node="0"&gt;Build Locally:&lt;/STRONG&gt; Write your agent logic using standard frameworks like the &lt;STRONG data-path-to-node="17,1,0" data-index-in-node="73"&gt;Microsoft Agent Framework (MAF)&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="17,2,0" data-index-in-node="0"&gt;Inspect &amp;amp; Debug:&lt;/STRONG&gt; Trace data flow and agent conversations in real-time before moving to production.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="17,3,0" data-index-in-node="0"&gt;Deploy with One Click:&lt;/STRONG&gt; Ship your local project directly to the cloud as a fully managed &lt;STRONG data-path-to-node="17,3,0" data-index-in-node="88"&gt;Foundry Agent Service&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H3 data-path-to-node="19"&gt;Inside My Workshop: Lab 02 Multi-Agent Workflow&lt;/H3&gt;
&lt;P data-path-to-node="20"&gt;To show you exactly how to make the most of this toolkit, I built a practical, real-world scenario in &lt;STRONG data-path-to-node="20" data-index-in-node="102"&gt;Lab 02: Multi-Agent Workflow&lt;/STRONG&gt;, which you can find inside the open-source repository.&lt;/P&gt;
&lt;P data-path-to-node="21"&gt;In this lab, I walk you through building a &lt;STRONG data-path-to-node="21" data-index-in-node="43"&gt;"Resume → Job Fit Evaluator"&lt;/STRONG&gt; pipeline. Instead of relying on a single prompt, the workflow orchestrates a squad of &lt;STRONG data-path-to-node="21" data-index-in-node="158"&gt;four specialized AI agents&lt;/STRONG&gt; working together using smart design patterns:&lt;/P&gt;
&lt;H4 data-path-to-node="22"&gt;1. The Fan-Out Pattern (Parallel Work)&lt;/H4&gt;
&lt;P data-path-to-node="23"&gt;When a resume is submitted, the system splits the task and feeds it to two agents at the exact same time:&lt;/P&gt;
&lt;UL data-path-to-node="24"&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="24,0,0" data-index-in-node="0"&gt;The Tech Stack Analyst:&lt;/STRONG&gt; Focuses entirely on programming languages, frameworks, and tools.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="24,1,0" data-index-in-node="0"&gt;The Experience &amp;amp; Impact Scorer:&lt;/STRONG&gt; Evaluates career history, performance metrics, and leadership.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H4 data-path-to-node="25"&gt;2. The Fan-In Pattern (Consolidation)&lt;/H4&gt;
&lt;P data-path-to-node="26"&gt;Once the parallel analysis is complete, the workflow channels their notes into the final two agents to consolidate the data:&lt;/P&gt;
&lt;UL data-path-to-node="27"&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="27,0,0" data-index-in-node="0"&gt;The Fit Evaluator:&lt;/STRONG&gt; Synthesizes the information into a single compatibility score.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG data-path-to-node="27,1,0" data-index-in-node="0"&gt;The Roadmap Architect:&lt;/STRONG&gt; Generates a custom step-by-step learning path to help the candidate bridge any skill gaps.&lt;/LI&gt;
&lt;/UL&gt;
&lt;img /&gt;
&lt;H3 data-path-to-node="34"&gt;The Development Workflow: Step-by-Step&lt;/H3&gt;
&lt;P data-path-to-node="35"&gt;The lab I put together provides a straightforward walkthrough that takes you from an empty directory to a live cloud application without ever leaving your code editor.&lt;/P&gt;
&lt;H4 data-path-to-node="36"&gt;Step 1: Click to Build Your Workspace&lt;/H4&gt;
&lt;P data-path-to-node="37"&gt;You don't need to write complicated setup code from scratch. By using the &lt;STRONG data-path-to-node="37" data-index-in-node="74"&gt;Agent Builder&lt;/STRONG&gt; interface inside the VS Code extension, you can click a button to automatically generate all the starter configurations and project folders I've mapped out for you.&lt;/P&gt;
&lt;H4 data-path-to-node="42"&gt;Step 2: Give the Agents Their Jobs&lt;/H4&gt;
&lt;P data-path-to-node="43"&gt;Next, you customize what each agent does using a simple configuration file (agent.yaml). This is where you tell the agents which AI models to use from the &lt;STRONG data-path-to-node="43" data-index-in-node="155"&gt;Foundry Model Catalog&lt;/STRONG&gt;. You then add your project keys to connect to your cloud workspace:&lt;/P&gt;
&lt;LI-CODE lang="markdown"&gt;FOUNDRY_PROJECT_ENDPOINT=https://&amp;lt;your-workspace&amp;gt;.services.ai.azure.com/api/projects/&amp;lt;your-project&amp;gt;
AZURE_AI_MODEL_DEPLsOYMENT_NAME=&amp;lt;your-ai-model&amp;gt;&lt;/LI-CODE&gt;
&lt;H4 data-path-to-node="45"&gt;Step 3: Test and Fix on Your Computer&lt;/H4&gt;
&lt;P data-path-to-node="46"&gt;Before sharing your project with the world, you can run the whole AI team locally on your machine. Using a tool called the &lt;STRONG data-path-to-node="46" data-index-in-node="123"&gt;Agent Inspector&lt;/STRONG&gt;, you can see exactly how the agents talk to each other, trace data steps, and tweak your text instructions until they work perfectly.&lt;/P&gt;
&lt;H4 data-path-to-node="47"&gt;Step 4: One-Click Cloud Launch&lt;/H4&gt;
&lt;P data-path-to-node="48"&gt;When your local tests work great, you don't need to be a server or container expert to deploy them. The VS Code extension automatically packages your code and registers it with the &lt;STRONG data-path-to-node="48" data-index-in-node="181"&gt;Foundry Agent Service&lt;/STRONG&gt; as a live Hosted Agent.&lt;/P&gt;
&lt;H4 data-path-to-node="49"&gt;Step 5: Test the Live App&lt;/H4&gt;
&lt;P data-path-to-node="50"&gt;Once your AI team is live in the cloud, you can open the built-in &lt;STRONG data-path-to-node="50" data-index-in-node="66"&gt;Remote Agent Playground&lt;/STRONG&gt; web page. Drag and drop a real resume into the window, hit run, and watch the streaming logs show your cloud agents processing the data together in real-time.&lt;/P&gt;
&lt;img /&gt;
&lt;H3 data-path-to-node="56"&gt;Ready to Build Your Own AI Team?&lt;/H3&gt;
&lt;P data-path-to-node="57"&gt;Building reliable AI tools means moving away from massive, unpredictable prompts and moving toward small, organized teams of agents using standard patterns like Fan-Out and Fan-In. The combination of the Foundry Toolkit and the structured labs I've created makes it easy to build, test, and host these systems without worrying about server infrastructure.&lt;/P&gt;
&lt;P data-path-to-node="58"&gt;The entire workshop is free, open-source, and ready for you to clone today. Jump into Lab 02 and see how easy multi-agent orchestration can be!&lt;/P&gt;
&lt;P data-path-to-node="59"&gt;&lt;STRONG data-path-to-node="59" data-index-in-node="3"&gt;Get Started Now:&lt;/STRONG&gt; Explore my lab repository at &lt;A href="https://github.com/microsoft-foundry/Foundry_Toolkit_for_VSCode_Lab/tree/main/workshop/lab02-multi-agent" target="_blank" rel="noopener" data-lia-auto-title-active="0" data-lia-auto-title="Foundry_Toolkit_for_VSCode_Lab/workshop/lab02-multi-agent at main · microsoft-foundry/Foundry_Toolkit_for_VSCode_Lab"&gt;Foundry_Toolkit_for_VSCode_Lab/workshop/lab02-multi-agent at main · microsoft-foundry/Foundry_Toolkit_for_VSCode_Lab&lt;/A&gt;&lt;/P&gt;
&lt;H4 data-path-to-node="61"&gt;Let's Connect!&lt;/H4&gt;
&lt;P data-path-to-node="62"&gt;If you enjoyed this walkthrough, have questions about the workshop, or want to share your own agent workflows, let's keep the conversation going:&lt;/P&gt;
&lt;UL data-path-to-node="63"&gt;
&lt;LI&gt;&lt;A class="lia-external-url" href="https://shivamgoyal03.github.io/" target="_blank" rel="noopener"&gt;&lt;STRONG data-path-to-node="63,0,0" data-index-in-node="3"&gt;Portfolio&lt;/STRONG&gt;&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;</description>
      <pubDate>Wed, 15 Jul 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/building-a-fully-managed-multi-agent-pipeline-with-microsoft/ba-p/4533757</guid>
      <dc:creator>ShivamGoyal</dc:creator>
      <dc:date>2026-07-15T07:00:00Z</dc:date>
    </item>
    <item>
      <title>Build and Deploy Your First AI Agent with Microsoft Foundry Toolkit</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/build-and-deploy-your-first-ai-agent-with-microsoft-foundry/ba-p/4534920</link>
      <description>&lt;BLOCKQUOTE&gt;
&lt;P data-line="6"&gt;&lt;A class="lia-external-url" href="https://github.com/microsoft-foundry/Foundry_Toolkit_for_VSCode_Lab/tree/main/workshop/lab01-single-agent" target="_blank" rel="noopener"&gt;Click here for the full lab.&lt;/A&gt;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P data-line="6"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P data-line="6"&gt;What if every incident report, pipeline failure, or security alert could be instantly rewritten for a non-technical audience? In this post, you'll build an &lt;STRONG&gt;"Explain Like I'm an Executive"&lt;/STRONG&gt; agent, a hosted AI agent that takes dense technical input and produces plain-English executive summaries, using the &lt;A class="lia-external-url" href="https://marketplace.visualstudio.com/items?itemName=ms-windows-ai-studio.windows-ai-studio" target="_blank" rel="noopener"&gt;Microsoft Foundry Toolkit for VS Code.&lt;/A&gt;&lt;/P&gt;
&lt;P data-line="8"&gt;By the end, you'll have a working agent you can test locally and deploy to the cloud with a single click.&lt;/P&gt;
&lt;H2 data-line="10"&gt;What You'll Build&lt;/H2&gt;
&lt;P data-line="12"&gt;The agent follows a simple flow:&lt;/P&gt;
&lt;img /&gt;
&lt;P data-line="18"&gt;Under the hood it uses:&lt;/P&gt;
&lt;UL data-line="20"&gt;
&lt;LI data-line="20"&gt;&lt;STRONG&gt;Microsoft Agent Framework&lt;/STRONG&gt; - for agent logic and structure&lt;/LI&gt;
&lt;LI data-line="21"&gt;&lt;STRONG&gt;Foundry Toolkit for VS Code&lt;/STRONG&gt; - to scaffold, test, and deploy&lt;/LI&gt;
&lt;LI data-line="22"&gt;&lt;STRONG&gt;An AI model&lt;/STRONG&gt; (e.g., gpt-4.1-mini) - to generate the summaries&lt;/LI&gt;
&lt;/UL&gt;
&lt;P data-line="24"&gt;The final output always follows a structured format:&lt;/P&gt;
&lt;P data-line="26"&gt;&lt;STRONG&gt;Executive Summary:&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL data-line="27"&gt;
&lt;LI data-line="27"&gt;What happened:&amp;nbsp;&lt;EM&gt;(plain-language description)&lt;/EM&gt;&lt;/LI&gt;
&lt;LI data-line="28"&gt;Business impact:&amp;nbsp;&lt;EM&gt;(clear, non-technical impact)&lt;/EM&gt;&lt;/LI&gt;
&lt;LI data-line="29"&gt;Next step:&amp;nbsp;&lt;EM&gt;(action or mitigation)&lt;/EM&gt;&lt;/LI&gt;
&lt;LI data-line="30"&gt;Date:&amp;nbsp;&lt;EM&gt;(YYYY-MM-DD)&lt;/EM&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2 data-line="293"&gt;Foundry Toolkit&lt;/H2&gt;
&lt;img /&gt;
&lt;P data-line="20"&gt;The Foundry Toolkit handles the end-to-end lifecycle:&lt;/P&gt;
&lt;OL data-line="22"&gt;
&lt;LI data-line="22"&gt;&lt;STRONG&gt;Scaffold&lt;/STRONG&gt; - A wizard generates your project structure with one command&lt;/LI&gt;
&lt;LI data-line="23"&gt;&lt;STRONG&gt;Configure&lt;/STRONG&gt; - Point to your AI model and write agent instructions (a system prompt)&lt;/LI&gt;
&lt;LI data-line="24"&gt;&lt;STRONG&gt;Test locally&lt;/STRONG&gt; - Press F5 to launch a built-in chat UI for instant feedback&lt;/LI&gt;
&lt;LI data-line="25"&gt;&lt;STRONG&gt;Deploy&lt;/STRONG&gt; - One click packages your agent as a container and deploys it to Azure&lt;/LI&gt;
&lt;LI data-line="26"&gt;&lt;STRONG&gt;Verify&lt;/STRONG&gt; - Test safety and edge cases against the live endpoint&lt;/LI&gt;
&lt;/OL&gt;
&lt;P data-line="28"&gt;The key building blocks:&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Component&lt;/th&gt;&lt;th&gt;Role&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;Agent Framework&lt;/STRONG&gt;&lt;/td&gt;&lt;td&gt;Provides the agent runtime and tool-calling capabilities&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;Foundry Toolkit&lt;/STRONG&gt;&lt;/td&gt;&lt;td&gt;VS Code extension for scaffolding, debugging, and deployment&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;AI Model&lt;/STRONG&gt;&amp;nbsp;(e.g., gpt-4.1-mini)&lt;/td&gt;&lt;td&gt;Powers the natural language understanding and generation&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;Azure Container Registry + Foundry&lt;/STRONG&gt;&lt;/td&gt;&lt;td&gt;Hosts and scales your agent in the cloud&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 50.00%" /&gt;&lt;col style="width: 50.00%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H2 data-line="39"&gt;What Makes a Good Agent&lt;/H2&gt;
&lt;P data-line="41"&gt;The difference between a basic chatbot and a reliable agent comes down to&amp;nbsp;&lt;STRONG&gt;well-crafted instructions&lt;/STRONG&gt;. For this agent, the system prompt defines:&lt;/P&gt;
&lt;UL data-line="43"&gt;
&lt;LI data-line="43"&gt;&lt;STRONG&gt;Role&lt;/STRONG&gt; - "Translate technical information into executive-friendly summaries"&lt;/LI&gt;
&lt;LI data-line="44"&gt;&lt;STRONG&gt;Audience&lt;/STRONG&gt; - Senior leaders who care about impact, not implementation details&lt;/LI&gt;
&lt;LI data-line="45"&gt;&lt;STRONG&gt;Output format&lt;/STRONG&gt; - A consistent structure (what happened, business impact, next step)&lt;/LI&gt;
&lt;LI data-line="46"&gt;&lt;STRONG&gt;Rules&lt;/STRONG&gt; - Keep it brief, don't fabricate, don't leak instructions&lt;/LI&gt;
&lt;LI data-line="47"&gt;&lt;STRONG&gt;Safety constraints&lt;/STRONG&gt; - Resist prompt injection and role override attempts&lt;/LI&gt;
&lt;/UL&gt;
&lt;P data-line="49"&gt;You can also give agents&amp;nbsp;&lt;STRONG&gt;tools, &lt;/STRONG&gt;Python functions they can call at runtime (like fetching today's date or querying an API).&lt;/P&gt;
&lt;H2 data-line="53"&gt;The Developer Experience&lt;/H2&gt;
&lt;img /&gt;
&lt;P data-line="55"&gt;The Foundry Toolkit streamlines what would otherwise be a multi-step DevOps process:&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Without the toolkit&lt;/th&gt;&lt;th&gt;With the toolkit&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Manually write Dockerfiles, YAML configs, server boilerplate&lt;/td&gt;&lt;td&gt;Wizard generates everything&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Set up a separate test harness&lt;/td&gt;&lt;td&gt;Built-in Agent Inspector (chat UI) launches with F5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Build container, push to registry, register agent manually&lt;/td&gt;&lt;td&gt;Single "Deploy" button handles it all&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Monitor via Azure Portal&lt;/td&gt;&lt;td&gt;Status, logs, and playground available in VS Code&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 50.00%" /&gt;&lt;col style="width: 50.00%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P data-line="64"&gt;Deployment takes 2–5 minutes. Your agent gets a managed /responses endpoint with auto-scaling.&lt;/P&gt;
&lt;H2 data-line="293"&gt;Cleanup&lt;/H2&gt;
&lt;P data-line="295"&gt;If you want to remove Azure resources after experimenting:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P data-line="8"&gt;az group delete --name &amp;lt;your-resource-group&amp;gt; --yes --no-wait&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P data-line="301"&gt;Or delete just the hosted agent from the Foundry portal under&amp;nbsp;&lt;STRONG&gt;Build → Agents&lt;/STRONG&gt;.&lt;/P&gt;
&lt;H2 data-line="293"&gt;Next Steps&lt;/H2&gt;
&lt;UL data-line="123"&gt;
&lt;LI data-line="123"&gt;Explore the &lt;A class="lia-external-url" href="https://github.com/microsoft-foundry/Foundry_Toolkit_for_VSCode_Lab/" target="_blank" rel="noopener"&gt;Foundry Toolkit Lab&lt;/A&gt;, to build your own agent.&lt;/LI&gt;
&lt;LI data-line="123"&gt;Check out&lt;STRONG&gt;&amp;nbsp;&lt;A class="lia-internal-link lia-internal-url lia-internal-url-content-type-blog" href="https://techcommunity.microsoft.com/blog/educatordeveloperblog/building-a-fully-managed-multi-agent-pipeline-with-microsoft-foundry/4533757" target="_blank" rel="noopener" data-href="../lab02-multi-agent/docs/README.md" data-lia-auto-title="Lab 02: Multi-Agent Orchestration" data-lia-auto-title-active="0"&gt;Lab 02: Multi-Agent Orchestration&lt;/A&gt;&lt;/STRONG&gt; to learn how to build a multi-agent workflow with orchestration patterns&lt;/LI&gt;
&lt;LI data-line="124"&gt;&lt;STRONG&gt;&lt;A href="https://learn.microsoft.com/azure/foundry/agents/concepts/tool-catalog" target="_blank" rel="noopener" data-href="https://learn.microsoft.com/azure/foundry/agents/concepts/tool-catalog"&gt;Add tools&lt;/A&gt;&lt;/STRONG&gt; - Connect APIs, databases, or custom functions&lt;/LI&gt;
&lt;LI data-line="126"&gt;&lt;STRONG&gt;&lt;A href="https://learn.microsoft.com/azure/foundry/" target="_blank" rel="noopener" data-href="https://learn.microsoft.com/azure/foundry/"&gt;Microsoft Foundry docs&lt;/A&gt;&lt;/STRONG&gt; - Full platform reference&lt;/LI&gt;
&lt;/UL&gt;</description>
      <pubDate>Mon, 13 Jul 2026 07:53:38 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/build-and-deploy-your-first-ai-agent-with-microsoft-foundry/ba-p/4534920</guid>
      <dc:creator>bethanyjep</dc:creator>
      <dc:date>2026-07-13T07:53:38Z</dc:date>
    </item>
    <item>
      <title>From Game to Operations: Exporting a Foundry-Designed Workforce as a Portable Bundle</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/from-game-to-operations-exporting-a-foundry-designed-workforce/ba-p/4530300</link>
      <description>&lt;P&gt;Part 5 of 5.&lt;/P&gt;
&lt;HR /&gt;
&lt;P&gt;Across this series the game has reasoned about a founder, designed a digital workforce for their venture, executed chapters through Microsoft Foundry agents, and gated every artifact behind a human. That is a complete loop - inside the game. This final post is about the seam where it leaves the game: how the &lt;STRONG&gt;Org Designer&lt;/STRONG&gt;'s output becomes a portable artifact a real digital-worker platform can ingest and provision, without dragging a single proprietary dependency into the public repo.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;The most useful thing a reasoning agent can produce is not a paragraph. It is a structured plan another system can execute - behind its own human gate.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;H2&gt;Why the Org Designer is the keystone worker&lt;/H2&gt;
&lt;P&gt;In Part 1 the pipeline's second stage was the Org Designer: given a venture, it designs the smallest org that can actually deliver it - one human operator plus the digital workers that form the execution layer. Every other system in the game hangs off that output. The World Designer decomposes the venture into chapters; &lt;CODE&gt;bind_world_to_org&lt;/CODE&gt; stamps each chapter with its owning worker; the economy prices each worker's monthly burn. The org the model designs is the org that executes.&lt;/P&gt;
&lt;P&gt;You can see the artifact directly in play - a worker delivers a positioning brief and a rendered org chart, and it passes the gate:&lt;/P&gt;
&lt;img /&gt;
&lt;P style="padding: 12px; border: 2px dashed #3caea3; background: #eefaf8;"&gt;&lt;EM&gt;A worker delivers a rendered org chart that passes the verification gate&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;That org chart is not decoration. It is structured state - roles, kinds (human / digital_worker / hybrid), mandates, reporting lines, KPIs, tool wishes, and a model-class hint per worker. Which means it can be &lt;EM&gt;exported&lt;/EM&gt;.&lt;/P&gt;
&lt;H2&gt;The org being exported: OrgRole and OrgBlueprint&lt;/H2&gt;
&lt;P&gt;To understand the bundle you have to see the state it is built from. The org is an &lt;CODE&gt;OrgBlueprint&lt;/CODE&gt; in &lt;CODE&gt;submission/state/schema.py&lt;/CODE&gt; - a company summary, an operating model, and a list of &lt;CODE&gt;OrgRole&lt;/CODE&gt; seats. Each role is a typed record, not a sentence:&lt;/P&gt;
&lt;PRE class="language-python" tabindex="0" contenteditable="false" data-lia-code-value="# submission/state/schema.py
class OrgRole(BaseModel):
    id: str
    title: str
    kind: str = &amp;quot;digital_worker&amp;quot;   # human | digital_worker | hybrid
    mandate: str = &amp;quot;&amp;quot;              # what this seat is accountable for
    reports_to: Optional[str] = None
    kpis: List[str] = Field(default_factory=list)
    tools: List[str] = Field(default_factory=list)
    deployment_hint: str = &amp;quot;&amp;quot;      # which model class fits this worker
    lifecycle_stage: str = &amp;quot;&amp;quot;      # discovery|positioning|mvp|gtm|retention|ops
    monthly_cost_usd: int = 0      # the worker's monthly wage (the burn)
    why: str = &amp;quot;&amp;quot;                  # why this seat must exist
"&gt;&lt;CODE&gt;# submission/state/schema.py
class OrgRole(BaseModel):
    id: str
    title: str
    kind: str = "digital_worker"   # human | digital_worker | hybrid
    mandate: str = ""              # what this seat is accountable for
    reports_to: Optional[str] = None
    kpis: List[str] = Field(default_factory=list)
    tools: List[str] = Field(default_factory=list)
    deployment_hint: str = ""      # which model class fits this worker
    lifecycle_stage: str = ""      # discovery|positioning|mvp|gtm|retention|ops
    monthly_cost_usd: int = 0      # the worker's monthly wage (the burn)
    why: str = ""                  # why this seat must exist
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Because every field is structured, the converter has something real to map - it is not parsing prose back into fields, it is re-shaping records it already trusts. &lt;CODE&gt;kind&lt;/CODE&gt; becomes the human/digital split; &lt;CODE&gt;deployment_hint&lt;/CODE&gt; becomes the portable &lt;CODE&gt;model_class&lt;/CODE&gt;; &lt;CODE&gt;reports_to&lt;/CODE&gt; becomes the org chart's edges; &lt;CODE&gt;mandate&lt;/CODE&gt;, &lt;CODE&gt;kpis&lt;/CODE&gt;, and &lt;CODE&gt;tools&lt;/CODE&gt; become the worker's brief. The blueprint also carries derived economics (&lt;CODE&gt;monthly_burn_usd&lt;/CODE&gt;, &lt;CODE&gt;leverage_ratio&lt;/CODE&gt;, &lt;CODE&gt;monthly_savings_usd&lt;/CODE&gt;) that ride into the bundle unchanged.&lt;/P&gt;
&lt;H2&gt;How the org gets designed&lt;/H2&gt;
&lt;P&gt;That blueprint is itself the output of a Foundry agent. &lt;CODE&gt;design_org&lt;/CODE&gt; in &lt;CODE&gt;submission/agents/org_designer.py&lt;/CODE&gt; runs on the org-designer deployment (a stronger model, because it shapes the whole run), asks for a structured roster, and parses it through the same tolerant &lt;CODE&gt;_extract_json&lt;/CODE&gt; from Part 2 - falling back to a deterministic blueprint when there are no credentials:&lt;/P&gt;
&lt;PRE class="language-python" tabindex="0" contenteditable="false" data-lia-code-value="# submission/agents/org_designer.py
def design_org(brief, source=&amp;quot;pitch&amp;quot;, source_ref=&amp;quot;&amp;quot;, summary_hint=&amp;quot;&amp;quot;):
    client = get_foundry_client()
    deployment = model_for(&amp;quot;orgdesigner&amp;quot;) or model_for(&amp;quot;narrator&amp;quot;)
    if not (client and deployment and is_live()):
        return _finalize(_fallback_blueprint(brief), brief, source, source_ref, summary_hint)
    resp = create_chat_completion(deployment, [...], max_completion_tokens=8000)
    parsed = _extract_json(resp.choices[0].message.content or &amp;quot;&amp;quot;)
    if parsed and len(parsed.get(&amp;quot;roles&amp;quot;, [])) &amp;gt;= 2:
        return _finalize(parsed, brief, source, source_ref, summary_hint)
    return _finalize(_fallback_blueprint(brief), brief, source, source_ref, summary_hint)
"&gt;&lt;CODE&gt;# submission/agents/org_designer.py
def design_org(brief, source="pitch", source_ref="", summary_hint=""):
    client = get_foundry_client()
    deployment = model_for("orgdesigner") or model_for("narrator")
    if not (client and deployment and is_live()):
        return _finalize(_fallback_blueprint(brief), brief, source, source_ref, summary_hint)
    resp = create_chat_completion(deployment, [...], max_completion_tokens=8000)
    parsed = _extract_json(resp.choices[0].message.content or "")
    if parsed and len(parsed.get("roles", [])) &amp;gt;= 2:
        return _finalize(parsed, brief, source, source_ref, summary_hint)
    return _finalize(_fallback_blueprint(brief), brief, source, source_ref, summary_hint)
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;CODE&gt;_finalize&lt;/CODE&gt; is where the model's creative roster meets deterministic mechanics: it normalises every role, prices each seat, and computes the headline stats. The model decides &lt;EM&gt;who&lt;/EM&gt; the company needs; the code decides &lt;EM&gt;what they cost&lt;/EM&gt;. That division - which we have now seen at the gate (Part 2), in consequences (Part 3), and here - is the spine of the whole project, and it is why an exported bundle's economics are trustworthy even though a model drew the org.&lt;/P&gt;
&lt;H2&gt;The org binds to the quest&lt;/H2&gt;
&lt;P&gt;The designed org does not sit in a corner - it is stamped onto the quest line. &lt;CODE&gt;bind_world_to_org&lt;/CODE&gt; in &lt;CODE&gt;worker_factory.py&lt;/CODE&gt; walks the stages and assigns each one the digital worker whose lifecycle stage matches, so every chapter has an owning worker before play begins:&lt;/P&gt;
&lt;PRE class="language-python" tabindex="0" contenteditable="false" data-lia-code-value="# submission/agents/worker_factory.py
def bind_world_to_org(world, org):
    bindings = {}
    for stage in world.stages:
        worker = _match_worker_for_stage(stage, org)
        if worker:
            stage.assigned_worker_id = worker.id
            stage.assigned_worker_title = worker.title
            bindings[stage.id] = worker.title
    return bindings
"&gt;&lt;CODE&gt;# submission/agents/worker_factory.py
def bind_world_to_org(world, org):
    bindings = {}
    for stage in world.stages:
        worker = _match_worker_for_stage(stage, org)
        if worker:
            stage.assigned_worker_id = worker.id
            stage.assigned_worker_title = worker.title
            bindings[stage.id] = worker.title
    return bindings
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;This is why the export is meaningful: the org in the bundle is the same org that executed the run. The worker that owns the GTM chapter in the game is the worker the bundle hands the receiving platform for GTM. Nothing is invented at export time.&lt;/P&gt;
&lt;H2&gt;The bridge: export, don't import&lt;/H2&gt;
&lt;P&gt;The temptation, when you have a game and a real platform, is to wire them together - run the platform's workers inside the game. That is the wrong move for two reasons. First, the game's reasoning core must stay 100% Microsoft Foundry (the rubric rule, and the architectural spine of this series). Second, the repo must run after &lt;CODE&gt;git clone&lt;/CODE&gt; with no proprietary dependencies. So the bridge is &lt;STRONG&gt;export, not import&lt;/STRONG&gt;: the game emits a neutral bundle; any platform ingests it.&lt;/P&gt;
&lt;img /&gt;&lt;!-- mermaid source:
flowchart LR
    A[Player pitch / profile URL] --&amp;gt; B[Org Designer&amp;lt;br/&amp;gt;Foundry gpt-5 family]
    B --&amp;gt; C[OrgBlueprint&amp;lt;br/&amp;gt;in game state]
    C --&amp;gt; D[GET /api/org/export&amp;lt;br/&amp;gt;workforce_bundle.json]
    D --&amp;gt; E[Any digital-worker platform&amp;lt;br/&amp;gt;maps + reviews]
    E --&amp;gt; F[Human approval gate]
    F --&amp;gt; G[Provisioned workers,&amp;lt;br/&amp;gt;teams, KPIs, workflows]
--&gt;
&lt;P&gt;No platform-specific code lives in the game repo. The converter is pure and offline - it turns the in-game &lt;CODE&gt;OrgBlueprint&lt;/CODE&gt; into a platform-neutral &lt;CODE&gt;workforce_bundle&lt;/CODE&gt; and ships a CLI that runs in simulation after a fresh clone.&lt;/P&gt;
&lt;H2&gt;The converter is pure and offline&lt;/H2&gt;
&lt;P&gt;The module that does the work, &lt;CODE&gt;submission/tools/export_org_blueprint.py&lt;/CODE&gt;, is deliberately dependency-free: no platform SDK, no network, no credentials. It splits the chartered roles into humans and digital workers and emits one spec per worker:&lt;/P&gt;
&lt;PRE class="language-python" tabindex="0" contenteditable="false" data-lia-code-value="# submission/tools/export_org_blueprint.py
def org_to_workforce_bundle(org):
    roles   = org.get(&amp;quot;roles&amp;quot;) or []
    humans  = [r for r in roles if r.get(&amp;quot;kind&amp;quot;) == &amp;quot;human&amp;quot;]
    workers = [r for r in roles if r.get(&amp;quot;kind&amp;quot;) != &amp;quot;human&amp;quot;]
    worker_specs = [{
        &amp;quot;worker_key&amp;quot;: _slug(role.get(&amp;quot;id&amp;quot;) or role.get(&amp;quot;title&amp;quot;, &amp;quot;&amp;quot;)),
        &amp;quot;name&amp;quot;: role.get(&amp;quot;title&amp;quot;, &amp;quot;Digital Worker&amp;quot;),
        &amp;quot;kind&amp;quot;: role.get(&amp;quot;kind&amp;quot;, &amp;quot;digital_worker&amp;quot;),
        &amp;quot;system_message&amp;quot;: _system_message(role, org),
        &amp;quot;model_class&amp;quot;: _MODEL_CLASS.get(role.get(&amp;quot;deployment_hint&amp;quot;, &amp;quot;&amp;quot;), &amp;quot;fast&amp;quot;),
        &amp;quot;tools&amp;quot;: role.get(&amp;quot;tools&amp;quot;) or [], &amp;quot;kpis&amp;quot;: role.get(&amp;quot;kpis&amp;quot;) or [],
        &amp;quot;reports_to&amp;quot;: _slug(role.get(&amp;quot;reports_to&amp;quot;) or &amp;quot;&amp;quot;),
        # ... seniority, monthly_cost_usd, why ...
    } for role in workers]
    # ... company, economics, team, provisioning ...
"&gt;&lt;CODE&gt;# submission/tools/export_org_blueprint.py
def org_to_workforce_bundle(org):
    roles   = org.get("roles") or []
    humans  = [r for r in roles if r.get("kind") == "human"]
    workers = [r for r in roles if r.get("kind") != "human"]
    worker_specs = [{
        "worker_key": _slug(role.get("id") or role.get("title", "")),
        "name": role.get("title", "Digital Worker"),
        "kind": role.get("kind", "digital_worker"),
        "system_message": _system_message(role, org),
        "model_class": _MODEL_CLASS.get(role.get("deployment_hint", ""), "fast"),
        "tools": role.get("tools") or [], "kpis": role.get("kpis") or [],
        "reports_to": _slug(role.get("reports_to") or ""),
        # ... seniority, monthly_cost_usd, why ...
    } for role in workers]
    # ... company, economics, team, provisioning ...
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Because it is pure, the same function backs both the live HTTP endpoint and a no-server CLI, and it runs in simulation after a fresh clone - the export is forkable like everything else in this series.&lt;/P&gt;
&lt;H2&gt;The bundle: a contract, not a dump&lt;/H2&gt;
&lt;P&gt;The export is a single JSON document with a stable format tag (&lt;CODE&gt;campaign.workforce_bundle&lt;/CODE&gt;, versioned), designed so both a human approver and a downstream LLM can parse and act on it:&lt;/P&gt;
&lt;PRE class="language-json" tabindex="0" contenteditable="false" data-lia-code-value="{
  &amp;quot;format&amp;quot;: &amp;quot;campaign.workforce_bundle&amp;quot;,
  &amp;quot;version&amp;quot;: 1,
  &amp;quot;company&amp;quot;: { &amp;quot;summary&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;operating_model&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;source&amp;quot;: &amp;quot;pitch&amp;quot; },
  &amp;quot;economics&amp;quot;: { &amp;quot;headcount&amp;quot;: 6, &amp;quot;digital_worker_count&amp;quot;: 5,
                 &amp;quot;human_count&amp;quot;: 1, &amp;quot;monthly_burn_usd&amp;quot;: 23625, &amp;quot;leverage_ratio&amp;quot;: 5.0 },
  &amp;quot;team&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;purpose&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;members&amp;quot;: [&amp;quot;...&amp;quot;], &amp;quot;owner&amp;quot;: &amp;quot;operator&amp;quot; },
  &amp;quot;humans&amp;quot;: [ { &amp;quot;id&amp;quot;: &amp;quot;operator&amp;quot;, &amp;quot;title&amp;quot;: &amp;quot;Founder / Operator&amp;quot;, &amp;quot;mandate&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;kpis&amp;quot;: [&amp;quot;...&amp;quot;] } ],
  &amp;quot;workers&amp;quot;: [
    {
      &amp;quot;worker_key&amp;quot;: &amp;quot;strategy_positioning_lead&amp;quot;,
      &amp;quot;name&amp;quot;: &amp;quot;Strategy &amp;amp; Positioning Lead&amp;quot;,
      &amp;quot;role&amp;quot;: &amp;quot;strategist&amp;quot;,
      &amp;quot;kind&amp;quot;: &amp;quot;digital_worker&amp;quot;,
      &amp;quot;system_message&amp;quot;: &amp;quot;&amp;lt;worker_identity&amp;gt;...generated starter prompt...&amp;lt;/worker_identity&amp;gt;&amp;quot;,
      &amp;quot;model_class&amp;quot;: &amp;quot;reasoning&amp;quot;,
      &amp;quot;tools&amp;quot;: [&amp;quot;...&amp;quot;], &amp;quot;kpis&amp;quot;: [&amp;quot;...&amp;quot;], &amp;quot;reports_to&amp;quot;: &amp;quot;operator&amp;quot;
    }
  ],
  &amp;quot;org_chart_mermaid&amp;quot;: &amp;quot;graph TD\n  ...&amp;quot;,
  &amp;quot;provisioning&amp;quot;: {
    &amp;quot;status&amp;quot;: &amp;quot;pending_human_approval&amp;quot;,
    &amp;quot;note&amp;quot;: &amp;quot;Nothing in this bundle is provisioned. The receiving platform must
             present it for explicit human approval before creating anything.&amp;quot;
  }
}
"&gt;&lt;CODE&gt;{
  "format": "campaign.workforce_bundle",
  "version": 1,
  "company": { "summary": "...", "operating_model": "...", "source": "pitch" },
  "economics": { "headcount": 6, "digital_worker_count": 5,
                 "human_count": 1, "monthly_burn_usd": 23625, "leverage_ratio": 5.0 },
  "team": { "name": "...", "purpose": "...", "members": ["..."], "owner": "operator" },
  "humans": [ { "id": "operator", "title": "Founder / Operator", "mandate": "...", "kpis": ["..."] } ],
  "workers": [
    {
      "worker_key": "strategy_positioning_lead",
      "name": "Strategy &amp;amp; Positioning Lead",
      "role": "strategist",
      "kind": "digital_worker",
      "system_message": "&amp;lt;worker_identity&amp;gt;...generated starter prompt...&amp;lt;/worker_identity&amp;gt;",
      "model_class": "reasoning",
      "tools": ["..."], "kpis": ["..."], "reports_to": "operator"
    }
  ],
  "org_chart_mermaid": "graph TD\n  ...",
  "provisioning": {
    "status": "pending_human_approval",
    "note": "Nothing in this bundle is provisioned. The receiving platform must
             present it for explicit human approval before creating anything."
  }
}
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Three design choices make it portable:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;A generated &lt;CODE&gt;system_message&lt;/CODE&gt; per worker, same shape for every role&lt;/STRONG&gt; - so a receiving platform (or its own org-architect agent) can parse, refine, and version it instead of re-deriving prompts.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;A &lt;CODE&gt;model_class&lt;/CODE&gt; hint (&lt;CODE&gt;reasoning&lt;/CODE&gt; / &lt;CODE&gt;fast&lt;/CODE&gt; / &lt;CODE&gt;creative&lt;/CODE&gt;)&lt;/STRONG&gt;, not a hard model name - the receiver maps it onto its own fleet.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;A &lt;CODE&gt;provisioning.status&lt;/CODE&gt; of &lt;CODE&gt;pending_human_approval&lt;/CODE&gt;&lt;/STRONG&gt; baked into the artifact itself. The bundle carries its own gate: the game's verification-gate pattern (Part 2), extended across the system boundary.&lt;/LI&gt;
&lt;/OL&gt;
&lt;img /&gt;&lt;!-- mermaid source:
flowchart TB
    ORG[&amp;quot;OrgBlueprint (game state)&amp;quot;] --&amp;gt; CONV[&amp;quot;org_to_workforce_bundle()&amp;quot;]
    CONV --&amp;gt; B[&amp;quot;workforce_bundle.json&amp;quot;]
    B --&amp;gt; CO[&amp;quot;company + economics&amp;quot;]
    B --&amp;gt; HU[&amp;quot;humans[] (operator)&amp;quot;]
    B --&amp;gt; WK[&amp;quot;workers[]&amp;lt;br/&amp;gt;system_message, model_class,&amp;lt;br/&amp;gt;tools, kpis, reports_to&amp;quot;]
    B --&amp;gt; MM[&amp;quot;org_chart_mermaid&amp;quot;]
    B --&amp;gt; PV[&amp;quot;provisioning.status =&amp;lt;br/&amp;gt;pending_human_approval&amp;quot;]
--&gt;
&lt;H2&gt;Every worker carries its own starter prompt&lt;/H2&gt;
&lt;P&gt;The single most portable field is &lt;CODE&gt;system_message&lt;/CODE&gt;. Every worker - whatever its role - gets a generated starter prompt in the &lt;EM&gt;same&lt;/EM&gt; XML shape, so a receiving platform (or its own org-architect agent) can parse, refine, and version it instead of re-deriving prompts from scratch:&lt;/P&gt;
&lt;PRE class="language-python" tabindex="0" contenteditable="false" data-lia-code-value="# submission/tools/export_org_blueprint.py - _system_message
return (
    f&amp;quot;&amp;lt;worker_identity&amp;gt;\n&amp;quot;
    f&amp;quot;  &amp;lt;role&amp;gt;{role.get('title')}&amp;lt;/role&amp;gt;\n&amp;quot;
    f&amp;quot;  &amp;lt;mission&amp;gt;{role.get('mandate', '')}&amp;lt;/mission&amp;gt;\n&amp;quot;
    f&amp;quot;  &amp;lt;reports_to&amp;gt;{reports_to}&amp;lt;/reports_to&amp;gt;\n&amp;quot;
    f&amp;quot;  &amp;lt;kpis&amp;gt;{kpis}&amp;lt;/kpis&amp;gt;\n&amp;quot;
    f&amp;quot;  &amp;lt;guardrails&amp;gt;\n&amp;quot;
    f&amp;quot;    - Work only within this mandate; escalate judgment calls to {reports_to}.\n&amp;quot;
    f&amp;quot;    - No legal or financial commitments without explicit human approval.\n&amp;quot;
    f&amp;quot;  &amp;lt;/guardrails&amp;gt;\n&amp;quot;
    f&amp;quot;&amp;lt;/worker_identity&amp;gt;&amp;quot;
)
"&gt;&lt;CODE&gt;# submission/tools/export_org_blueprint.py - _system_message
return (
    f"&amp;lt;worker_identity&amp;gt;\n"
    f"  &amp;lt;role&amp;gt;{role.get('title')}&amp;lt;/role&amp;gt;\n"
    f"  &amp;lt;mission&amp;gt;{role.get('mandate', '')}&amp;lt;/mission&amp;gt;\n"
    f"  &amp;lt;reports_to&amp;gt;{reports_to}&amp;lt;/reports_to&amp;gt;\n"
    f"  &amp;lt;kpis&amp;gt;{kpis}&amp;lt;/kpis&amp;gt;\n"
    f"  &amp;lt;guardrails&amp;gt;\n"
    f"    - Work only within this mandate; escalate judgment calls to {reports_to}.\n"
    f"    - No legal or financial commitments without explicit human approval.\n"
    f"  &amp;lt;/guardrails&amp;gt;\n"
    f"&amp;lt;/worker_identity&amp;gt;"
)
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Those guardrails are not decoration. Every exported worker ships with "no legal or financial commitments without explicit human approval" baked into its own identity - the human gate is written into the worker's prompt, not just the bundle's status field.&lt;/P&gt;
&lt;H2&gt;The org chart travels as text&lt;/H2&gt;
&lt;P&gt;There is a fitting symmetry with this whole series, which has leaned on Mermaid for every diagram: the bundle ships the org chart &lt;EM&gt;as Mermaid source&lt;/EM&gt;, generated by &lt;CODE&gt;org_to_mermaid&lt;/CODE&gt;. A receiver can render it, diff it, or hand it to a model - it is text, not a picture:&lt;/P&gt;
&lt;PRE class="language-python" tabindex="0" contenteditable="false" data-lia-code-value="# submission/tools/export_org_blueprint.py - org_to_mermaid
lines = [&amp;quot;graph TD&amp;quot;]
lines.append(&amp;quot;  classDef human fill:#f6d55c,stroke:#5b8cff,stroke-width:3px&amp;quot;)
lines.append(&amp;quot;  classDef digital fill:#3caea3,stroke:#2dd4bf&amp;quot;)
for role in roles:
    cls = &amp;quot;human&amp;quot; if role[&amp;quot;kind&amp;quot;] == &amp;quot;human&amp;quot; else &amp;quot;digital&amp;quot;
    lines.append(f'  n_{_slug(role[&amp;quot;id&amp;quot;])}[&amp;quot;{title}&amp;quot;]:::{cls}')
for role in roles:                       # reporting lines
    if role.get(&amp;quot;reports_to&amp;quot;):
        lines.append(f&amp;quot;  n_{_slug(role['reports_to'])} --&amp;gt; n_{_slug(role['id'])}&amp;quot;)
"&gt;&lt;CODE&gt;# submission/tools/export_org_blueprint.py - org_to_mermaid
lines = ["graph TD"]
lines.append("  classDef human fill:#f6d55c,stroke:#5b8cff,stroke-width:3px")
lines.append("  classDef digital fill:#3caea3,stroke:#2dd4bf")
for role in roles:
    cls = "human" if role["kind"] == "human" else "digital"
    lines.append(f'  n_{_slug(role["id"])}["{title}"]:::{cls}')
for role in roles:                       # reporting lines
    if role.get("reports_to"):
        lines.append(f"  n_{_slug(role['reports_to'])} --&amp;gt; n_{_slug(role['id'])}")
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Humans and digital workers get different CSS classes, so the rendered chart shows at a glance who is a person and who is a digital worker - the same human/digital distinction the economics priced, carried into the picture.&lt;/P&gt;
&lt;H2&gt;The economics travel with the org&lt;/H2&gt;
&lt;P&gt;A workforce plan that does not say what it costs is a wish list. The bundle carries an &lt;CODE&gt;economics&lt;/CODE&gt; block - headcount, digital-worker count, human count, monthly burn, and a leverage ratio - computed by the game's &lt;CODE&gt;worker_economics&lt;/CODE&gt; model when the org was designed, not invented at export time:&lt;/P&gt;
&lt;PRE class="language-json" tabindex="0" contenteditable="false" data-lia-code-value="&amp;quot;economics&amp;quot;: {
  &amp;quot;headcount&amp;quot;: 6, &amp;quot;digital_worker_count&amp;quot;: 5, &amp;quot;human_count&amp;quot;: 1,
  &amp;quot;monthly_burn_usd&amp;quot;: 23625, &amp;quot;monthly_inference_usd&amp;quot;: 1200, &amp;quot;leverage_ratio&amp;quot;: 5.0
}
"&gt;&lt;CODE&gt;"economics": {
  "headcount": 6, "digital_worker_count": 5, "human_count": 1,
  "monthly_burn_usd": 23625, "monthly_inference_usd": 1200, "leverage_ratio": 5.0
}
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Each worker also carries its own &lt;CODE&gt;monthly_cost_usd&lt;/CODE&gt;, so a receiving platform can show a real budget before it provisions anything - one human operator leveraging five digital workers at a burn a solo founder could actually carry. That leverage ratio (digital workers per human) is the headline number the whole game is about: how much execution one person can direct. Exporting it means the off-ramp inherits the argument, not just the boxes and arrows.&lt;/P&gt;
&lt;H2&gt;Pricing the workforce&lt;/H2&gt;
&lt;P&gt;Those numbers are not vibes. &lt;CODE&gt;submission/agents/worker_economics.py&lt;/CODE&gt; prices each seat from the human salary it replaces - a deliberate game-balance fraction, so burn is a constraint the player actually feels rather than a rounding error:&lt;/P&gt;
&lt;PRE class="language-python" tabindex="0" contenteditable="false" data-lia-code-value="# submission/agents/worker_economics.py
WORKER_COST_FRACTION_OF_HUMAN = 0.75   # a worker costs 3/4 of the human it replaces

def worker_cost_from_human(human_median_usd):
    return int(round(max(0, human_median_usd) * WORKER_COST_FRACTION_OF_HUMAN))
"&gt;&lt;CODE&gt;# submission/agents/worker_economics.py
WORKER_COST_FRACTION_OF_HUMAN = 0.75   # a worker costs 3/4 of the human it replaces

def worker_cost_from_human(human_median_usd):
    return int(round(max(0, human_median_usd) * WORKER_COST_FRACTION_OF_HUMAN))
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Each worker's &lt;CODE&gt;monthly_cost_usd&lt;/CODE&gt; is three quarters of the present-world salary for that seat; the much cheaper real compute (&lt;CODE&gt;inference_usd&lt;/CODE&gt;) is tracked separately for the efficiency story. Sum the workers and you get &lt;CODE&gt;monthly_burn_usd&lt;/CODE&gt;; divide digital workers by human operators and you get &lt;CODE&gt;leverage_ratio&lt;/CODE&gt;. When a receiving platform reads the bundle, those are the figures it shows before provisioning - a real budget for one operator running a digital team, derived the same way whether the org was designed on Foundry or in simulation.&lt;/P&gt;
&lt;H2&gt;The export endpoint and the button&lt;/H2&gt;
&lt;P&gt;The bridge is one endpoint and one button. &lt;CODE&gt;GET /api/org/export&lt;/CODE&gt; reads the chartered org from state, converts it, logs an &lt;CODE&gt;ORG_EXPORTED&lt;/CODE&gt; event to the replay log (Part 4), and returns the bundle as a download. The Digital Workforce panel in the UI has an &lt;STRONG&gt;Export workforce bundle&lt;/STRONG&gt; button that calls it - so "you played the game; now your org is a deployable workforce" is one click.&lt;/P&gt;
&lt;PRE class="language-python" tabindex="0" contenteditable="false" data-lia-code-value="@app.get(&amp;quot;/api/org/export&amp;quot;)
def export_org():
    state = store.load()
    if not state.org or not state.org.roles:
        raise HTTPException(status_code=404, detail=&amp;quot;No chartered org to export.&amp;quot;)
    bundle = org_to_workforce_bundle(state.org.model_dump())
    store.log_event(&amp;quot;ORG_EXPORTED&amp;quot;, &amp;quot;org_designer&amp;quot;,
                    f&amp;quot;Exported {len(bundle['workers'])} workers, pending approval.&amp;quot;)
    return JSONResponse(content=bundle,
        headers={&amp;quot;Content-Disposition&amp;quot;: 'attachment; filename=&amp;quot;workforce_bundle.json&amp;quot;'})
"&gt;&lt;CODE&gt;@app.get("/api/org/export")
def export_org():
    state = store.load()
    if not state.org or not state.org.roles:
        raise HTTPException(status_code=404, detail="No chartered org to export.")
    bundle = org_to_workforce_bundle(state.org.model_dump())
    store.log_event("ORG_EXPORTED", "org_designer",
                    f"Exported {len(bundle['workers'])} workers, pending approval.")
    return JSONResponse(content=bundle,
        headers={"Content-Disposition": 'attachment; filename="workforce_bundle.json"'})
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Because the converter is dependency-free, it also runs from the command line with no server and no credentials:&lt;/P&gt;
&lt;PRE class="language-bash" tabindex="0" contenteditable="false" data-lia-code-value="python3 submission/tools/export_org_blueprint.py \
  --pitch &amp;quot;Low-cost 3D-printed solar cells for off-grid homes&amp;quot;
# -&amp;gt; workforce_bundle.json : 5 digital workers + 1 human, pending approval
"&gt;&lt;CODE&gt;python3 submission/tools/export_org_blueprint.py \
  --pitch "Low-cost 3D-printed solar cells for off-grid homes"
# -&amp;gt; workforce_bundle.json : 5 digital workers + 1 human, pending approval
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H2&gt;The CLI: same converter, no server&lt;/H2&gt;
&lt;P&gt;Because the converter is pure, the same &lt;CODE&gt;org_to_workforce_bundle&lt;/CODE&gt; function powers a no-server CLI - &lt;CODE&gt;export_org_blueprint.py&lt;/CODE&gt; - which can either read a saved game state or design a fresh org from a pitch and export it, all in simulation, no credentials:&lt;/P&gt;
&lt;PRE class="language-python" tabindex="0" contenteditable="false" data-lia-code-value="# submission/tools/export_org_blueprint.py - _main
if args.pitch:
    from agents.org_designer import design_org
    org = design_org(args.pitch, source=&amp;quot;pitch&amp;quot;, source_ref=args.pitch)
else:
    org = json.load(open(state_path)).get(&amp;quot;org&amp;quot;) or {}   # from a played game
bundle = org_to_workforce_bundle(org)
print(json.dumps(bundle, indent=2))
"&gt;&lt;CODE&gt;# submission/tools/export_org_blueprint.py - _main
if args.pitch:
    from agents.org_designer import design_org
    org = design_org(args.pitch, source="pitch", source_ref=args.pitch)
else:
    org = json.load(open(state_path)).get("org") or {}   # from a played game
bundle = org_to_workforce_bundle(org)
print(json.dumps(bundle, indent=2))
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;That one entry point is the whole forkability story for the bridge: &lt;CODE&gt;--pitch "..."&lt;/CODE&gt; designs an org and prints a deployable workforce bundle on a fresh clone, with no Azure, no server, and no platform SDK anywhere in the path. The endpoint and the CLI share the exact same converter, so what you can click in the live app you can also pipe in a shell.&lt;/P&gt;
&lt;H2&gt;Best practice: the receiver re-gates, the bundle is a draft&lt;/H2&gt;
&lt;P&gt;A portable bundle is an &lt;EM&gt;input&lt;/EM&gt;, not an order. On the receiving side, the right pattern is an org-architect worker that treats the bundle as a &lt;STRONG&gt;draft blueprint&lt;/STRONG&gt;: it maps each entry's &lt;CODE&gt;model_class&lt;/CODE&gt; onto the platform's current model tiers, matches incoming worker mandates against existing templates (reuse before invent), re-renders the org chart in its own conventions, fills gaps the game did not model (departments, OKR cascades), and then presents the result for explicit human approval - exactly the CEO-gate pattern, one system later.&lt;/P&gt;
&lt;P&gt;That symmetry is the point. The game gates artifacts behind a human; the bundle declares itself pending; the receiver gates provisioning behind a human. The human-at-the-root law (Part 2) survives the trip across the boundary.&lt;/P&gt;
&lt;img /&gt;&lt;!-- mermaid source:
flowchart LR
    G1[&amp;quot;Game CEO gate&amp;lt;br/&amp;gt;(Part 2)&amp;quot;] --&amp;gt; B[&amp;quot;bundle:&amp;lt;br/&amp;gt;pending_human_approval&amp;quot;]
    B --&amp;gt; RCV[&amp;quot;Receiving platform&amp;lt;br/&amp;gt;org-architect worker&amp;quot;]
    RCV --&amp;gt; MAP[&amp;quot;map model_class -&amp;gt; fleet&amp;lt;br/&amp;gt;reuse templates, fill gaps&amp;quot;]
    MAP --&amp;gt; G2[&amp;quot;Receiver human gate&amp;quot;]
    G2 --&amp;gt; PROV[&amp;quot;provision workers,&amp;lt;br/&amp;gt;teams, KPIs&amp;quot;]
--&gt;
&lt;H2&gt;Why this matters beyond the game&lt;/H2&gt;
&lt;P&gt;A reasoning agent that only produces prose is a better chatbot. A reasoning agent that produces a &lt;STRONG&gt;structured, portable, gated plan another system can execute&lt;/STRONG&gt; is the beginning of an operating loop. The game is a teaching tool and a playable argument; the bundle is the off-ramp where the argument becomes useful - the designed workforce stops being a screen and becomes something a platform can stand up, behind its own approval gate.&lt;/P&gt;
&lt;H2&gt;Responsible AI&lt;/H2&gt;
&lt;P&gt;The bundle is inert by construction. Its &lt;CODE&gt;provisioning.status&lt;/CODE&gt; is &lt;CODE&gt;pending_human_approval&lt;/CODE&gt; and its note says, in the artifact itself, that nothing is provisioned until a human signs off. Nothing in it is executable on import; it is a description, not a command. Combined with the receiver re-gating provisioning, that means no chain of automated steps can stand up a workforce without a person in the loop - the same reliability story this whole series is built on, carried one boundary further.&lt;/P&gt;
&lt;H2&gt;The whole series, in one artifact&lt;/H2&gt;
&lt;P&gt;It is worth seeing the bundle as the place every earlier post converges. The org inside it was &lt;EM&gt;decomposed&lt;/EM&gt; from a pitch (Part 1) and designed on a Foundry model. Every artifact that filled it out passed a human &lt;EM&gt;verification gate&lt;/EM&gt; (Part 2). The CEO decisions that shaped which workers exist are the &lt;EM&gt;binding memory&lt;/EM&gt; the workforce learned from (Part 3). The whole thing was produced by a stack that runs &lt;EM&gt;local-first and fully traced&lt;/EM&gt;, so the &lt;CODE&gt;ORG_EXPORTED&lt;/CODE&gt; event sits in the same replay log as everything that led to it (Part 4). And now it leaves the game as a portable, gated plan (Part 5). The bundle is not a feature bolted on at the end; it is the receipt for the entire loop.&lt;/P&gt;
&lt;H2&gt;Where this lives in the repo&lt;/H2&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Concern&lt;/th&gt;&lt;th&gt;File&lt;/th&gt;&lt;th&gt;Key symbol&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Pure offline converter + CLI&lt;/td&gt;&lt;td&gt;&lt;CODE&gt;submission/tools/export_org_blueprint.py&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;&lt;CODE&gt;org_to_workforce_bundle&lt;/CODE&gt;, &lt;CODE&gt;_system_message&lt;/CODE&gt;, &lt;CODE&gt;org_to_mermaid&lt;/CODE&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Export endpoint + replay event&lt;/td&gt;&lt;td&gt;&lt;CODE&gt;submission/tools/server.py&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;&lt;CODE&gt;GET /api/org/export&lt;/CODE&gt;, &lt;CODE&gt;ORG_EXPORTED&lt;/CODE&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;The org being exported&lt;/td&gt;&lt;td&gt;&lt;CODE&gt;submission/agents/org_designer.py&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;&lt;CODE&gt;design_org&lt;/CODE&gt;, &lt;CODE&gt;OrgBlueprint&lt;/CODE&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;colgroup&gt;&lt;col style="width: 33.33%" /&gt;&lt;col style="width: 33.33%" /&gt;&lt;col style="width: 33.33%" /&gt;&lt;/colgroup&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H2&gt;Try it&lt;/H2&gt;
&lt;P&gt;Charter an org in the game, then export it:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;A class="lia-external-url" href="https://worldforge-game.agreeableground-34b354cf.eastus2.azurecontainerapps.io/" target="_blank" rel="noopener"&gt;Play the live app&lt;/A&gt;&lt;/STRONG&gt; -&amp;gt; design your workforce -&amp;gt; &lt;STRONG&gt;Export workforce bundle&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;Or from the CLI, no credentials:&lt;/P&gt;
&lt;PRE class="language-bash" tabindex="0" contenteditable="false" data-lia-code-value="git clone https://github.com/princepspolycap/agentsleague-afterbuild
cd agentsleague-afterbuild &amp;amp;&amp;amp; python3 -m venv .venv &amp;amp;&amp;amp; source .venv/bin/activate
pip install -r submission/requirements.txt
python3 submission/tools/export_org_blueprint.py --pitch &amp;quot;Your idea here&amp;quot;
"&gt;&lt;CODE&gt;git clone https://github.com/princepspolycap/agentsleague-afterbuild
cd agentsleague-afterbuild &amp;amp;&amp;amp; python3 -m venv .venv &amp;amp;&amp;amp; source .venv/bin/activate
pip install -r submission/requirements.txt
python3 submission/tools/export_org_blueprint.py --pitch "Your idea here"
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H2&gt;Key takeaways&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;The most useful agent output is a structured plan another system can execute, not prose.&lt;/LI&gt;
&lt;LI&gt;Bridge by export, not import: emit a neutral, versioned bundle; keep proprietary platforms out of the reasoning repo.&lt;/LI&gt;
&lt;LI&gt;Carry the human gate across the boundary - the bundle declares itself &lt;CODE&gt;pending_human_approval&lt;/CODE&gt;, and the receiver re-gates provisioning.&lt;/LI&gt;
&lt;LI&gt;Use a &lt;CODE&gt;model_class&lt;/CODE&gt; hint, not a hard model name, so the receiver maps onto its own fleet.&lt;/LI&gt;
&lt;LI&gt;One endpoint, one button: "you played the game; now your org is a deployable workforce."&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The dungeon is open, the workforce is designed, and now it is portable. A mission too big to command gets aligned one company at a time - and the org you charter in a browser game can walk out as a plan a real platform will run, with a human still holding the seal.&lt;/P&gt;
&lt;HR /&gt;
&lt;P&gt;&lt;EM&gt;Part 5 of 5. Start over at Part 1, or clone the repo and pitch your own company.&lt;/EM&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Play it: &lt;A class="lia-external-url" href="https://worldforge-game.agreeableground-34b354cf.eastus2.azurecontainerapps.io/" target="_blank" rel="noopener"&gt;worldforge-game...azurecontainerapps.io&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;Code: &lt;A href="https://github.com/princepspolycap/agentsleague-afterbuild" target="_blank" rel="noopener"&gt;github.com/princepspolycap/agentsleague-afterbuild&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;Live battle replay: &lt;A href="https://www.youtube.com/watch?v=Xj5LqH6k0U4" target="_blank" rel="noopener"&gt;Agents League - Reasoning Agents&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;</description>
      <pubDate>Thu, 02 Jul 2026 08:25:44 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/from-game-to-operations-exporting-a-foundry-designed-workforce/ba-p/4530300</guid>
      <dc:creator>Princeps</dc:creator>
      <dc:date>2026-07-02T08:25:44Z</dc:date>
    </item>
    <item>
      <title>GitHub Copilot App Canvas Is a Runtime</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/github-copilot-app-canvas-is-a-runtime/ba-p/4531462</link>
      <description>&lt;P&gt;There is a quiet shift happening in how we build software with AI. We are moving from&amp;nbsp;&lt;EM&gt;writing static code&lt;/EM&gt; to &lt;EM&gt;orchestrating living systems&lt;/EM&gt; where developers and AI agents co-create, observe, and evolve a solution in real time. This post is a working theory of what &lt;STRONG&gt;&lt;A class="lia-external-url" href="https://github.com/github/app" target="_blank"&gt;GitHub Copilot App&lt;/A&gt; Canvas&lt;/STRONG&gt; is actually &lt;EM&gt;for&lt;/EM&gt;, grounded in a real, runnable demo you can clone today: &lt;A href="https://github.com/leestott/agent-runtime-canvas" target="_blank"&gt;leestott/agent-runtime-canvas&lt;/A&gt;.&lt;/P&gt;
&lt;FIGURE&gt;&lt;A href="https://raw.githubusercontent.com/leestott/agent-runtime-canvas/main/canvas-demo.png" target="_blank" rel="noopener noreferrer"&gt; &lt;IMG style="max-width: 100%; height: auto; border-radius: 8px;" src="https://raw.githubusercontent.com/leestott/agent-runtime-canvas/main/canvas-demo.png" alt="The Agent Runtime canvas: top control bar (Step / Run / Pause / Inject failure / Clear failure / Reset), an activity-spotlight banner, and the Requirement, Constraints, and Agents panels." /&gt; &lt;/A&gt;
&lt;FIGCAPTION&gt;The Agent Runtime canvas open beside the chat — control bar, activity spotlight, requirement &amp;amp; constraints, and the live agent roster.&lt;/FIGCAPTION&gt;
&lt;/FIGURE&gt;
&lt;P&gt;The headline claim, which the rest of this post defends with code:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;STRONG&gt;Traditional UIs are for &lt;EM&gt;using&lt;/EM&gt; software. Canvas is for &lt;EM&gt;shaping&lt;/EM&gt; software while it runs.&lt;/STRONG&gt;&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H2&gt;1. The misconception worth getting out of the way&lt;/H2&gt;
&lt;P&gt;The first instinct most engineers have when they see Canvas is to build a UI with it&amp;nbsp; a dashboard, a DevOps board, an admin panel. That is the wrong mental model, and it leads to disappointment. A Kanban board rendered in Canvas is just a worse version of a tool that already exists.&lt;/P&gt;
&lt;P&gt;Canvas is not where your &lt;EM&gt;users&lt;/EM&gt; live. It is where your &lt;EM&gt;system&lt;/EM&gt; becomes visible to you and to the AI while you are still figuring it out. The distinction matters:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;You don't build Canvas &lt;EM&gt;instead of&lt;/EM&gt; your UI.&lt;/STRONG&gt; You use Canvas to figure out, test, and evolve the UI and the system &lt;EM&gt;before and during&lt;/EM&gt; building it.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Canvas solves problems your final UI should never try to solve in a visible way&lt;/STRONG&gt;&amp;nbsp;agent coordination, intermediate state, test validation, failure propagation. These are observability concerns, not end-user features.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Canvas is intended for test validation and the implementation of agent-driven solutions&lt;/STRONG&gt;&amp;nbsp; not for shipping a production control panel.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;A useful analogy: &lt;STRONG&gt;Figma is Human-to-Human&lt;/STRONG&gt;&amp;nbsp; one person designs a static artifact for another person to read. &lt;STRONG&gt;Canvas is Human-to-AI-to-System&lt;/STRONG&gt;&amp;nbsp;a shared surface where a human, an AI agent, and a &lt;EM&gt;running&lt;/EM&gt; system all act on the same live model. Figma shows you a picture of the software. Canvas &lt;EM&gt;is&lt;/EM&gt; a runtime where things actually execute.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;2. The positioning, stated plainly&lt;/H2&gt;
&lt;P&gt;Here is the thesis the demo is built to prove:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;Canvas redefines software development by shifting from writing static code to orchestrating living systems, where developers and AI co-create, observe, and evolve solutions in real time. Instead of building UIs for users, we build interactive environments for agents — turning debugging, testing, and execution into a continuous, visual feedback loop that accelerates innovation and brings ideas to production faster than ever.&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Read that again with the demo in mind, because the demo is not a slide, it is a working Copilot CLI extension that renders exactly this loop.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;3. What we built: the Agent Runtime canvas&lt;/H2&gt;
&lt;P&gt;&lt;A href="https://github.com/leestott/agent-runtime-canvas" target="_blank"&gt;agent-runtime-canvas&lt;/A&gt; is a GitHub Copilot CLI &lt;STRONG&gt;canvas extension&lt;/STRONG&gt; called &lt;STRONG&gt;Agent Runtime&lt;/STRONG&gt;. It turns Canvas into a runtime observability and control plane for a multi-agent software system that is being designed, tested, and evolved in real time.&lt;/P&gt;
&lt;P&gt;The canvas renders a single living &lt;STRONG&gt;SystemModel&lt;/STRONG&gt; that &lt;EM&gt;both humans and the AI agent edit at the same time&lt;/EM&gt;. The agent drives it through five canvas actions; the human drives it through panel controls. Every change streams to the iframe over Server-Sent Events (SSE), so the system visibly evolves through interaction.&lt;/P&gt;
&lt;H3&gt;The seven panels: a system you can watch think&lt;/H3&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Panel&lt;/th&gt;&lt;th&gt;What it makes observable&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;Requirement &amp;amp; constraints&lt;/STRONG&gt;&lt;/td&gt;&lt;td&gt;The feature under design plus editable policies and constraints&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;Agents&lt;/STRONG&gt;&lt;/td&gt;&lt;td&gt;Active agents, their responsibilities, and live state (idle / working / done / error / blocked)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;Task Flow&lt;/STRONG&gt;&lt;/td&gt;&lt;td&gt;The dependency graph of tasks across agents, with live status&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;Artifacts&lt;/STRONG&gt;&lt;/td&gt;&lt;td&gt;The intermediate outputs each task emits&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;Validation&lt;/STRONG&gt;&lt;/td&gt;&lt;td&gt;Test cases, pass/fail, expected vs. actual, and the reasoning behind each verdict&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;Live State&lt;/STRONG&gt;&lt;/td&gt;&lt;td&gt;The shared memory objects the agents read and write — directly human-editable&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;STRONG&gt;Timeline&lt;/STRONG&gt;&lt;/td&gt;&lt;td&gt;A change-over-time log, including before→after state diffs&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;None of these are things you would put in front of an end user. &lt;EM&gt;All&lt;/EM&gt; of them are things you desperately want to see while you and an AI are co-designing an agentic system.&lt;/P&gt;
&lt;H3&gt;The five agent actions&lt;/H3&gt;
&lt;P&gt;The AI co-creates and evolves the system by calling five actions, declared in the canvas extension:&lt;/P&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Action&lt;/th&gt;&lt;th&gt;Effect&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;decompose_system&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Break a requirement into collaborating agents + a task-flow graph&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;execute_workflow&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Coordinate agents to advance tasks (&lt;CODE&gt;step&lt;/CODE&gt; / &lt;CODE&gt;run&lt;/CODE&gt; / &lt;CODE&gt;pause&lt;/CODE&gt; / &lt;CODE&gt;resume&lt;/CODE&gt; / &lt;CODE&gt;reset&lt;/CODE&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;validate_output&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Run evaluation tests, return structured pass/fail + reasoning&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;update_system_design&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Modify architecture/logic: requirement, constraints, agents, tasks&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;track_state&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Persist/update a shared state object, recording the diff on the timeline&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;P&gt;The critical detail is that &lt;STRONG&gt;human controls and agent actions funnel through the exact same store&lt;/STRONG&gt;. There is no separate "AI view" and "human view" — one model, two kinds of participant.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;4. How it actually works (the parts that matter)&lt;/H2&gt;
&lt;P&gt;The extension is deliberately small and dependency-free. It uses only Node's built-in modules plus &lt;CODE&gt;&lt;a href="javascript:void(0)" data-lia-user-mentions="" data-lia-user-uid="2798636" data-lia-user-login="github" class="lia-mention lia-mention-user"&gt;github&lt;/a&gt;/copilot-sdk&lt;/CODE&gt;, which the CLI auto-resolves. Three files do the work:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE&gt;.github/extensions/agent-runtime/
  extension.mjs   # wiring: loopback HTTP server, SSE, /control, 5 canvas actions
  store.mjs       # durable SystemModel + execution engine + validation
  ui.mjs          # iframe renderer (system view, validation, state, timeline)
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H3&gt;One shared model, broadcast on every mutation&lt;/H3&gt;
&lt;P&gt;The heart of the demo is the &lt;CODE&gt;SystemStore&lt;/CODE&gt;. It is an &lt;CODE&gt;EventEmitter&lt;/CODE&gt;: every mutation bumps a version, appends a timeline entry, persists to disk, and broadcasts a fresh snapshot to all connected panels. This is the single line that makes "humans and AI edit the same live system" true rather than aspirational:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE&gt;// store.mjs — every change is versioned, logged, persisted, and broadcast.
_commit(eventType, summary, detail) {
  this.model.version += 1;
  this.model.updatedAt = now();
  if (eventType) {
    this.model.timeline.unshift({
      id: uid("ev"), ts: now(), type: eventType, summary, detail: detail || null,
    });
    this.model.timeline = this.model.timeline.slice(0, 200);
  }
  this._queueSave();          // best-effort JSON persistence under ~/.copilot
  this.emit("change", this.model);  // fan out to every SSE client
  return this.model;
}
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H3&gt;The agent action and the human button hit the same method&lt;/H3&gt;
&lt;P&gt;In &lt;CODE&gt;extension.mjs&lt;/CODE&gt;, the canvas action handler and the iframe's &lt;CODE&gt;/control&lt;/CODE&gt; POST both call &lt;CODE&gt;store.execute(...)&lt;/CODE&gt;. That symmetry is the whole point — neither the human nor the AI is privileged:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE&gt;// extension.mjs — a human control POST maps onto the same store method
// the AI agent calls through the execute_workflow canvas action.
function applyControl(store, body) {
  switch (body.action) {
    case "execute":  return store.execute(body.mode || "step", body);
    case "validate": return store.validate(body.tests);
    case "decompose":return store.decompose(body.requirement, body);
    case "inject_failure": return store.injectFailure(body.taskKey);
    case "edit_state":     return store.editState(body.key, body.value);
    // ...requirement, constraints, clear_failures, update_design
  }
}
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H3&gt;Execution you can watch one task at a time&lt;/H3&gt;
&lt;P&gt;The engine advances the task graph through a visible &lt;EM&gt;begin→dwell→finish&lt;/EM&gt; lifecycle so the active agent is always observable. A ready task is one whose dependencies are all &lt;CODE&gt;done&lt;/CODE&gt;:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE&gt;// store.mjs — the scheduler only starts a task when its deps are satisfied.
_readyTask() {
  return this.model.tasks.find(
    (t) =&amp;gt;
      t.status === "pending" &amp;amp;&amp;amp;
      t.deps.every((d) =&amp;gt; {
        const dep = this.model.tasks.find((x) =&amp;gt; x.id === d);
        return dep &amp;amp;&amp;amp; dep.status === "done";
      }),
  );
}
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;When a task finishes, its agent emits an artifact and writes to shared state; when a dependency fails, the engine walks the graph to a fixpoint and marks every downstream task &lt;CODE&gt;blocked&lt;/CODE&gt;. That is failure propagation you can &lt;EM&gt;see&lt;/EM&gt; — exactly the kind of thing a production UI would (correctly) hide, and exactly the kind of thing you need exposed while designing the system.&lt;/P&gt;
&lt;H3&gt;Validation as a first-class, re-runnable citizen&lt;/H3&gt;
&lt;P&gt;The default evaluation suite asserts properties of the &lt;EM&gt;running&lt;/EM&gt; system, not of static code — every test returns an expected value, an actual value, and a human -readable reason:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE&gt;// store.mjs — tests assert properties of the live system model.
_defaultTests() {
  const t = (name, target, assertion) =&amp;gt; ({ id: uid("test"), name, target, assertion });
  return [
    t("All tasks reach a terminal state", "tasks", "no_pending"),
    t("No tasks failed", "tasks", "none_failed"),
    t("Every completed task emitted an artifact", "artifacts", "artifact_per_done"),
    t("Design state populated before build", "state", "design_before_build"),
    t("Decision recorded by Reviewer", "state", "has_decision"),
  ];
}
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;This is the "continuous, visual feedback loop" from the thesis, made concrete: decompose → execute → validate → redesign → re-validate, with the Timeline recording every before→after transition.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;5. Run it yourself&lt;/H2&gt;
&lt;P&gt;You need a &lt;STRONG&gt;GitHub Copilot CLI / app with canvas support&lt;/STRONG&gt; (the &lt;CODE&gt;canvas-renderer&lt;/CODE&gt; capability) and this repo opened as your workspace. There is no &lt;CODE&gt;npm install &lt;/CODE&gt;the SDK is auto-resolved and the extension uses only built-in Node modules.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Clone and open the workspace.&lt;/STRONG&gt;
&lt;PRE&gt;&lt;CODE&gt;git clone https://github.com/leestott/agent-runtime-canvas.git
cd agent-runtime-canvas&lt;/CODE&gt;&lt;/PRE&gt;
The extension auto-discovers from &lt;CODE&gt;.github/extensions/agent-runtime/&lt;/CODE&gt;.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Open the canvas with a requirement.&lt;/STRONG&gt; Ask Copilot:
&lt;BLOCKQUOTE&gt;Open the Agent Runtime canvas with the requirement "Add CSV export to the reports page".&lt;/BLOCKQUOTE&gt;
&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Walk the loop.&lt;/STRONG&gt; Decompose into five agents and a six-task graph, press &lt;STRONG&gt;Run ▶&lt;/STRONG&gt;, watch the spotlight track the active agent, press &lt;STRONG&gt;Run tests ✓&lt;/STRONG&gt; for 5/5 green, then &lt;STRONG&gt;Inject failure ⚡&lt;/STRONG&gt; to watch downstream tasks go &lt;EM&gt;blocked&lt;/EM&gt; and validation drop to 4/5 — and recover.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;State persists per &lt;CODE&gt;documentId&lt;/CODE&gt; under &lt;CODE&gt;~/.copilot/extensions/agent-runtime/artifacts/&lt;/CODE&gt;, so a reload resumes exactly where you left off. The companion &lt;A href="https://github.com/leestott/agent-runtime-canvas/blob/main/demoscript.md" target="_blank"&gt;demoscript.md&lt;/A&gt; in the repo gives you a tight, timed walkthrough.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;6. Why this is an observability story&lt;/H2&gt;
&lt;P&gt;Once you accept that Canvas is a runtime rather than a UI, the most compelling use case becomes &lt;STRONG&gt;observability of agentic systems&lt;/STRONG&gt;. Agentic software is notoriously hard to debug: the interesting behavior lives in intermediate state, coordination order, and the moments where one agent's failure cascades into another's. A production UI is designed to &lt;EM&gt;hide&lt;/EM&gt; all of that. A Canvas is designed to &lt;EM&gt;surface&lt;/EM&gt; it,&amp;nbsp; temporarily, while you are shaping the system — and then get out of the way.&lt;/P&gt;
&lt;P&gt;This reframes Canvas alongside the broader Microsoft and GitHub agent tooling story. As teams adopt the &lt;A href="https://github.com/github/copilot-sdk" target="_blank"&gt;GitHub Copilot SDK&lt;/A&gt; and patterns like the open &lt;A href="https://modelcontextprotocol.io/" target="_blank"&gt;Model Context Protocol&lt;/A&gt; to wire agents into real systems, the gap is rarely "can the agent act?" it is "can a human&amp;nbsp;&lt;EM&gt;see&lt;/EM&gt; what the agent did, judge it, and steer it?" Canvas is a candidate answer to that second question. When you take agents toward production on Azure with services like &lt;A href="https://learn.microsoft.com/azure/ai-foundry/" target="_blank"&gt;Microsoft Foundry&lt;/A&gt;, the same instinct applies: build the evaluation and observability loop first, and let it shape the system before you commit a single end-user pixel.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;7. The open question: why can't Canvas be multi-user?&lt;/H2&gt;
&lt;P&gt;There is an obvious next frontier, and it is worth stating as an honest open question rather than a finished feature. Everything that makes Canvas valuable also makes it a natural &lt;EM&gt;collaborative&lt;/EM&gt; surface:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;It is a &lt;STRONG&gt;shared space&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;It is &lt;STRONG&gt;visual&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;It is &lt;STRONG&gt;collaborative&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Multiple participants — &lt;STRONG&gt;human and AI&lt;/STRONG&gt; — interact with the same surface.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;If Figma earned its place by making Human-to-Human design multiplayer, the provocative question is whether a project- or repo-scoped Canvas can make Human-to-AI-to-System development multiplayer too: several engineers and several agents shaping one running system on one surface. The demo here is single-user by design, but its architecture — one shared store, versioned, broadcast to every subscriber — is already the shape you would need. That is a genuine research direction, and worth experimenting with as licensing and access broaden.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;8. Honest limitations&lt;/H2&gt;
&lt;P&gt;In the spirit of building credibility rather than hype:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;This is a demonstration.&lt;/STRONG&gt; The decomposition, artifacts, and state are synthesized to make the runtime loop legible — it models an agentic system rather than running arbitrary production agents.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;It is single-user and single-machine.&lt;/STRONG&gt; The loopback HTTP server and per-document store are local by design; multi-user is an aspiration, not a shipped capability.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Access is gated.&lt;/STRONG&gt; Canvas support requires a Copilot CLI/app build with the &lt;CODE&gt;canvas-renderer&lt;/CODE&gt; capability. Licensing and preview access are the biggest practical blockers to wider experimentation today.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Persistence is best-effort.&lt;/STRONG&gt; State is written to a local JSON artifact; treat it as demo durability, not a database.&lt;/LI&gt;
&lt;/UL&gt;
&lt;HR /&gt;
&lt;H2&gt;Key takeaways&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Don't build a UI in Canvas.&lt;/STRONG&gt; Use Canvas to shape, test, and evolve a system — and the UI — while it runs.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Traditional UIs are for using software; Canvas is for shaping software while it runs.&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Canvas is Human-to-AI-to-System&lt;/STRONG&gt;, a runtime where things execute — not a static design surface.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Its strongest use case is observability and validation&lt;/STRONG&gt; of agentic systems: surface the intermediate state your production UI should hide.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;The shared-model architecture&lt;/STRONG&gt; — one versioned store broadcast to every participant — is what makes human + AI co-editing real, and what hints at a multi-user future.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;Next steps&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;Clone and run the demo: &lt;A href="https://github.com/leestott/agent-runtime-canvas" target="_blank"&gt;github.com/leestott/agent-runtime-canvas&lt;/A&gt;.&lt;/LI&gt;
&lt;LI&gt;Read the extension source under &lt;A href="https://github.com/leestott/agent-runtime-canvas/tree/main/.github/extensions/agent-runtime" target="_blank"&gt;&lt;CODE&gt;.github/extensions/agent-runtime/&lt;/CODE&gt;&lt;/A&gt; — start with &lt;CODE&gt;store.mjs&lt;/CODE&gt;.&lt;/LI&gt;
&lt;LI&gt;Explore the building blocks: the &lt;A href="https://github.com/github/copilot-sdk" target="_blank"&gt;GitHub Copilot SDK&lt;/A&gt;, the &lt;A href="https://modelcontextprotocol.io/" target="_blank"&gt;Model Context Protocol&lt;/A&gt;, and &lt;A href="https://learn.microsoft.com/azure/ai-foundry/" target="_blank"&gt;Microsoft Foundry&lt;/A&gt; for taking agentic systems toward production.&lt;/LI&gt;
&lt;LI&gt;Try the multi-user thought experiment: fork the store, add a second subscriber, and ask what changes when two humans and two agents share one surface.&lt;/LI&gt;
&lt;/UL&gt;</description>
      <pubDate>Mon, 29 Jun 2026 07:00:00 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/github-copilot-app-canvas-is-a-runtime/ba-p/4531462</guid>
      <dc:creator>Lee_Stott</dc:creator>
      <dc:date>2026-06-29T07:00:00Z</dc:date>
    </item>
    <item>
      <title>Master the Command Line with GitHub Copilot CLI:</title>
      <link>https://techcommunity.microsoft.com/t5/educator-developer-blog/master-the-command-line-with-github-copilot-cli/ba-p/4531566</link>
      <description>&lt;P&gt;If you are a student aiming to become an AI engineer or a software developer, the terminal is about to become your most powerful classroom. &lt;A class="lia-external-url" href="https://github.com/features/copilot/cli/" target="_blank"&gt;https://github.com/features/copilot/cli/&lt;/A&gt;&amp;nbsp;brings an AI agent directly into your command line, and its &lt;EM&gt;slash commands&lt;/EM&gt; (typed as &lt;CODE&gt;/something&lt;/CODE&gt;) are the shortcuts that unlock its real capabilities.&lt;/P&gt;
&lt;P&gt;The problem most students hit is simple: they install a powerful tool and then only ever use 10% of it. They type questions, get answers, and never discover the commands that turn Copilot CLI from a chatbot into a genuine pair programmer. This post fixes that. We will walk through the most useful slash commands, explain &lt;STRONG&gt;why&lt;/STRONG&gt; you would reach for each one, and give you concrete student scenarios for every command.&lt;/P&gt;
&lt;H2&gt;Why This Matters Now&lt;/H2&gt;
&lt;P&gt;AI-assisted development is no longer optional in the industry. Employers increasingly expect graduates to be fluent with AI developer tools, not just programming languages. Learning the Copilot CLI slash commands early gives you two advantages:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Speed:&lt;/STRONG&gt; You spend less time context-switching between docs, terminal, and editor.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Good habits:&lt;/STRONG&gt; Commands like code review and security review teach you professional workflows while you are still learning.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Everything below is grounded in the actual command set shipped in Copilot CLI. To see the full, current list at any time, just type &lt;CODE&gt;/help&lt;/CODE&gt; inside the CLI.&lt;/P&gt;
&lt;H2&gt;How to Run a Slash Command&lt;/H2&gt;
&lt;P&gt;Slash commands are typed at the Copilot CLI prompt. Start a command with a forward slash and the CLI shows you an autocomplete menu:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE&gt;# Launch the CLI
copilot

# Then, at the prompt, type a slash to browse commands
/

# Or jump straight to one
/model
/plan
/review&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;A few related shortcuts are worth memorising on day one:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;?&lt;/CODE&gt; — show quick help&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;@&lt;/CODE&gt; — mention files so Copilot reads them&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;#&lt;/CODE&gt; — mention GitHub issues and pull requests&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;!&lt;/CODE&gt; — execute a raw shell command without leaving the prompt&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;The Most Useful Slash Commands for Students&lt;/H2&gt;
&lt;P&gt;The table below groups the highest-value commands by the job you are trying to do. Each row includes a realistic student scenario so you know exactly when to reach for it.&lt;/P&gt;
&lt;H3&gt;Learning and Planning&lt;/H3&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Command&lt;/th&gt;&lt;th&gt;What it does&lt;/th&gt;&lt;th&gt;Student scenario: why use it&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/plan&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Creates an implementation plan before any code is written.&lt;/td&gt;&lt;td&gt;You have a coursework project ("build a sentiment classifier") but no idea where to start. Run &lt;CODE&gt;/plan&lt;/CODE&gt; to get a step-by-step roadmap you can follow and learn from, instead of diving in blind.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/research&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Runs a deep research investigation using GitHub search and web sources.&lt;/td&gt;&lt;td&gt;For a dissertation or capstone, you need to compare approaches (e.g. "vector databases for RAG"). Use &lt;CODE&gt;/research&lt;/CODE&gt; to gather grounded, cited findings rather than guessing.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/ask&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Asks a quick side question without adding it to the conversation history.&lt;/td&gt;&lt;td&gt;Mid-project you forget what a Python decorator does. Ask with &lt;CODE&gt;/ask&lt;/CODE&gt; so your main task context stays clean and focused.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/model&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Selects which AI model to use (or &lt;CODE&gt;auto&lt;/CODE&gt; to let Copilot pick).&lt;/td&gt;&lt;td&gt;A simple formatting fix needs a fast model; a tricky algorithm needs a stronger one. Learn to match the model to the task — a real engineering skill.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H3&gt;Writing and Reviewing Code&lt;/H3&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Command&lt;/th&gt;&lt;th&gt;What it does&lt;/th&gt;&lt;th&gt;Student scenario: why use it&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/diff&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Reviews the changes made in the current directory.&lt;/td&gt;&lt;td&gt;Before submitting an assignment, run &lt;CODE&gt;/diff&lt;/CODE&gt; to see exactly what changed — catch that debug &lt;CODE&gt;print()&lt;/CODE&gt; you forgot to remove.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/review&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Runs a code review agent to analyse your changes.&lt;/td&gt;&lt;td&gt;No teaching assistant available at 2am? &lt;CODE&gt;/review&lt;/CODE&gt; gives you professional-style feedback on bugs and logic errors so you learn before the deadline, not after grading.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/security-review&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Analyses staged and unstaged changes for security vulnerabilities.&lt;/td&gt;&lt;td&gt;Building a web app for a module? Run &lt;CODE&gt;/security-review&lt;/CODE&gt; to spot issues like injection flaws — and start building the security mindset employers want.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/pr&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Operates on pull requests for the current branch.&lt;/td&gt;&lt;td&gt;Contributing to a group project or open source? Use &lt;CODE&gt;/pr&lt;/CODE&gt; to manage pull requests and learn the collaboration workflow used in every real engineering team.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/ide&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Connects Copilot to an IDE workspace.&lt;/td&gt;&lt;td&gt;You prefer working in VS Code. Connect with &lt;CODE&gt;/ide&lt;/CODE&gt; so Copilot understands your open files and editor context.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H3&gt;Managing Your Work Session&lt;/H3&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Command&lt;/th&gt;&lt;th&gt;What it does&lt;/th&gt;&lt;th&gt;Student scenario: why use it&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/resume&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Switches to a different saved session.&lt;/td&gt;&lt;td&gt;You worked on a lab yesterday and want to continue today. &lt;CODE&gt;/resume&lt;/CODE&gt; brings back the full context instead of starting from scratch.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/context&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Shows context-window token usage and a visualization.&lt;/td&gt;&lt;td&gt;Copilot seems to be "forgetting" earlier details. Check &lt;CODE&gt;/context&lt;/CODE&gt; to understand how much conversation history fits — a core concept for any aspiring AI engineer.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/compact&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Summarises conversation history to reduce context usage.&lt;/td&gt;&lt;td&gt;Long debugging session running out of context? &lt;CODE&gt;/compact&lt;/CODE&gt; condenses it so you can keep going without losing the thread.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/undo&lt;/CODE&gt; / &lt;CODE&gt;/rewind&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Rewinds the last turn and reverts file changes.&lt;/td&gt;&lt;td&gt;Copilot made an edit that broke your tests. &lt;CODE&gt;/undo&lt;/CODE&gt; safely rolls it back so you can experiment fearlessly.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/usage&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Displays session usage metrics and statistics.&lt;/td&gt;&lt;td&gt;Curious how much you are relying on the AI? &lt;CODE&gt;/usage&lt;/CODE&gt; helps you stay aware of your consumption and learning balance.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H3&gt;Setting Up and Extending the Environment&lt;/H3&gt;
&lt;DIV class="styles_lia-table-wrapper__h6Xo9 styles_table-responsive__MW0lN"&gt;&lt;table border="1" style="border-width: 1px;"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Command&lt;/th&gt;&lt;th&gt;What it does&lt;/th&gt;&lt;th&gt;Student scenario: why use it&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/init&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Initialises Copilot instructions for the current repository.&lt;/td&gt;&lt;td&gt;Starting a new project repo? &lt;CODE&gt;/init&lt;/CODE&gt; sets up custom instructions so Copilot follows your project's conventions consistently.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/mcp&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Manages Model Context Protocol (MCP) server configuration.&lt;/td&gt;&lt;td&gt;Want Copilot to query a database or external tool? &lt;CODE&gt;/mcp&lt;/CODE&gt; connects MCP servers — a cutting-edge skill for AI engineering portfolios.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/agent&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Browses and selects specialised agents.&lt;/td&gt;&lt;td&gt;Different tasks suit different agents. &lt;CODE&gt;/agent&lt;/CODE&gt; lets you pick the right specialist for the job.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;CODE&gt;/memory&lt;/CODE&gt;&lt;/td&gt;&lt;td&gt;Shows memory status, or enables/disables memory across sessions.&lt;/td&gt;&lt;td&gt;Want Copilot to remember your preferences (e.g. "I use Python type hints")? Manage that with &lt;CODE&gt;/memory&lt;/CODE&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/DIV&gt;
&lt;H2&gt;A Realistic Student Workflow, End to End&lt;/H2&gt;
&lt;P&gt;Here is how these commands fit together for a typical assignment — building a small machine learning script. Notice how the commands chain into a professional development loop:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE&gt;# 1. Plan the work before touching code
/plan

# 2. Pick an appropriate model for the task
/model

# 3. Let Copilot reference your data file
@data/train.csv

# 4. After Copilot writes code, see what changed
/diff

# 5. Get an automated code review
/review

# 6. Check for security issues before you submit
/security-review

# 7. If an edit broke something, roll it back
/undo&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;This loop —&amp;gt; plan, build, review, secure, iterate, is exactly the cycle used by professional engineering teams. By practising it now with Copilot CLI, you are rehearsing the workflow you will use in your first job.&lt;/P&gt;
&lt;H2&gt;Responsible Use: Learn With AI, Not Instead Of It&lt;/H2&gt;
&lt;P&gt;A quick but important note for students. AI assistance is a learning accelerator, not a replacement for understanding. Keep these principles in mind:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Read the explanations, not just the code.&lt;/STRONG&gt; Use &lt;CODE&gt;/ask&lt;/CODE&gt; and &lt;CODE&gt;/review&lt;/CODE&gt; to understand &lt;EM&gt;why&lt;/EM&gt; something works.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Check your institution's policy.&lt;/STRONG&gt; Many courses have rules about AI use in assessed work,&amp;nbsp; make sure you comply and cite appropriately.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Never paste secrets.&lt;/STRONG&gt; Keep API keys, passwords, and personal data out of prompts.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Verify before you trust.&lt;/STRONG&gt; Run the code, read the security review, and confirm claims against official documentation.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;Key Takeaways&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;Slash commands turn Copilot CLI from a Q&amp;amp;A box into a full development partner.&lt;/LI&gt;
&lt;LI&gt;Start with &lt;CODE&gt;/plan&lt;/CODE&gt;, &lt;CODE&gt;/diff&lt;/CODE&gt;, &lt;CODE&gt;/review&lt;/CODE&gt;, and &lt;CODE&gt;/security-review&lt;/CODE&gt; they build professional habits immediately.&lt;/LI&gt;
&lt;LI&gt;Use &lt;CODE&gt;/model&lt;/CODE&gt;, &lt;CODE&gt;/context&lt;/CODE&gt;, and &lt;CODE&gt;/compact&lt;/CODE&gt; to understand how AI systems actually work under the hood.&lt;/LI&gt;
&lt;LI&gt;Type &lt;CODE&gt;/help&lt;/CODE&gt; any time to see the complete, current command list for your version.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2&gt;Next Steps and Resources&lt;/H2&gt;
&lt;UL&gt;
&lt;LI&gt;Read the official guide: &lt;A href="https://docs.github.com/copilot/how-tos/use-copilot-agents/use-copilot-cli" target="_blank"&gt;Use GitHub Copilot CLI&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;Explore the broader docs: &lt;A href="https://docs.github.com/en/copilot" target="_blank"&gt;GitHub Copilot documentation&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;Open the CLI and run &lt;CODE&gt;/help&lt;/CODE&gt; to browse every command interactively.&lt;/LI&gt;
&lt;LI&gt;Pick one assignment this week and run the full plan → review → security-review loop on it.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The fastest way to learn is to try. Launch Copilot CLI, type a single &lt;CODE&gt;/&lt;/CODE&gt;, and start exploring. Your future engineering self will thank you.&lt;/P&gt;</description>
      <pubDate>Sun, 28 Jun 2026 11:26:35 GMT</pubDate>
      <guid>https://techcommunity.microsoft.com/t5/educator-developer-blog/master-the-command-line-with-github-copilot-cli/ba-p/4531566</guid>
      <dc:creator>Lee_Stott</dc:creator>
      <dc:date>2026-06-28T11:26:35Z</dc:date>
    </item>
  </channel>
</rss>

