<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Microsoft Azure - Medium]]></title>
        <description><![CDATA[Any language. Any platform. Our team is focused on making the world more amazing for developers and IT operations communities with the best that Microsoft Azure can provide. If you want to contribute in this journey with us, contact us at medium@microsoft.com - Medium]]></description>
        <link>https://medium.com/microsoftazure?source=rss----8bec1183ada9---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Microsoft Azure - Medium</title>
            <link>https://medium.com/microsoftazure?source=rss----8bec1183ada9---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 05 Jun 2026 06:46:27 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/microsoftazure" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[The NEW Bicep Like and Distinct Functions ✨]]></title>
            <link>https://medium.com/microsoftazure/the-new-bicep-like-and-distinct-functions-6536a0004b11?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/6536a0004b11</guid>
            <category><![CDATA[microsoft]]></category>
            <category><![CDATA[azure]]></category>
            <category><![CDATA[bicep]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[infrastructure-as-code]]></category>
            <dc:creator><![CDATA[Brian Veldman]]></dc:creator>
            <pubDate>Mon, 01 Jun 2026 14:11:14 GMT</pubDate>
            <atom:updated>2026-06-01T14:11:13.309Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*zalpbcu41fNDXZFu.png" /></figure><p>With the release of Azure Bicep v0.43.1, two new functions have been introduced: like() and distinct(). In this blog, I will explain how these new functions work and showcase several useful real world scenarios where you can use them in your Bicep deployments. 💪🏻</p><h3>Like Function</h3><p>The like() function in Bicep is used to compare a string against a pattern. It returns true when the value matches the specified pattern and false when it does not. Let’s start with a simple example:</p><pre>param parInput string = &#39;Hello, World!&#39;<br> <br>output outOutput bool = like(parInput, &#39;*World*&#39;)</pre><p>In this example, the like() function checks whether the value of parInput contains the word World. The wildcard character *means that any characters before or after World are allowed. Since the string Hello, World! contains the word World, the output will return true.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Zidhd_sSlPQzvOWGSvmRSw.png" /></figure><p>In this example, the like() function is used to check whether the workloadName variable contains the value prod. The workloadName is dynamically created by combining the string xyz- with the value of the parEnvironment parameter. The result of this comparison is stored in the applyLock variable. If the workload name contains prod, the expression evaluates to true. As a result, the resource lock is deployed.</p><pre>param parEnvironment string<br><br>var workloadName = &#39;xyz-${parEnvironment}&#39;<br>var applyLock = like(workloadName, &#39;*prod*&#39;)<br><br>resource lock &#39;Microsoft.Authorization/locks@2020-05-01&#39; = if (applyLock) {<br> name: &#39;cannot-delete&#39;<br> properties: {<br>  level: &#39;CanNotDelete&#39;<br>  notes: &#39;Production protection&#39;<br> }<br>}</pre><p>We can see that the output is true because our parEnvironment variable has been assigned the value prod.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3Z2HwyJ0YWimAmh78WCQJg@2x.png" /></figure><p>In this example, we use the like() function to determine whether the parEnvironment parameter contains the value prod. The parameter is limited to the values prod, test, and acc by using the allowed decorator.</p><pre>@allowed([<br>  &#39;prod&#39;<br>  &#39;test&#39;<br>  &#39;acc&#39;<br>])<br>param parEnvironment string<br><br>module appi &#39;br/public:avm/res/insights/component:0.7.1&#39; = if (like(parEnvironment, &#39;*prod*&#39;)) {<br>  params: {<br>    name: &#39;appi-${parEnvironment}&#39;<br>    workspaceResourceId: &#39;idHere&#39;<br>  }<br>}</pre><h3>Distinct Function</h3><p>The next function is distinct(). This function can be very useful when working with arrays that may contain duplicate values. The distinct() function returns a new array that contains only the unique elements from the input array. Any duplicate values are removed automatically.</p><p>Let’s start with a simple example:</p><pre>param fruits array = [<br> &#39;apples&#39;<br> &#39;bananas&#39;<br> &#39;apples&#39;<br>]<br><br>var normalizedFruits = distinct(fruits)<br><br>output ouFruits array = normalizedFruits</pre><p>In this example, the fruits array contains the value apples twice. The distinct() function filters out the duplicate value and creates a new array that only contains unique entries. This function is especially useful when processing tags, role assignments, IP ranges, or any other configuration where duplicate values should be avoided.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pbCh2YbTmzP1ZaZ4z4Vlpw@2x.png" /></figure><p>In this example, the distinct() function is used to remove duplicate IP ranges from an array of IP groups. Each IP group contains a name and a list of IP addresses. First, a new array called ipAddresses is created using a for expression. This extracts the first IP address from each IP group object. Next, the distinct() function filters out duplicate IP ranges and stores only the unique values in the normalizedIpGroupsvariable.</p><pre>param ipGroups array = [<br>  {<br>    name: &#39;ipGroup1&#39;<br>    ipAddresses: [<br>      &#39;192.168.10.0/24&#39;<br>    ]<br>  }<br>  {<br>    name: &#39;ipGroup2&#39;<br>    ipAddresses: [<br>      &#39;192.168.5.0/24&#39;<br>    ]<br>  }<br>  {<br>    name: &#39;ipGroup3&#39;<br>    ipAddresses: [<br>      &#39;192.168.10.0/24&#39;<br>    ]<br>  }<br>]<br><br>var ipAddresses = [for ipGroup in ipGroups: ipGroup.ipAddresses[0]]<br>var normalizedIpGroups = distinct(ipAddresses)<br><br>module ipGroup &#39;br/public:avm/res/network/ip-group:0.4.0&#39; = [<br>  for ipGroup in normalizedIpGroups: {<br>    params: {<br>      name: ipGroup.name<br>      ipAddresses: ipGroup.ipAddresses<br>    }<br>  }<br>]</pre><p>This can be very useful in scenarios where multiple teams or workloads provide overlapping IP ranges. By removing duplicate entries before deployment, you can avoid unnecessary resources and keep your configuration cleaner and easier to maintain.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yM8rMgMHsTRxU023-BcJ3g.png" /></figure><p>That’s all for today. As you could see, the new Azure Bicep functions help you create cleaner, more flexible, and easier to maintain deployments. Whether you are validating naming conventions with like() or removing duplicate values with distinct(), these functions can simplify many real world deployment scenarios. The Azure Bicep code is available in my GitHub repository: <a href="https://github.com/brianveldman/azure-bicep">GitHub — brianveldman/azure-bicep</a>. Feel free to star the repository and clap for this story and let me know if you have any feedback. I look forward to seeing you in the next session. Until then, take care! ❤️</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6536a0004b11" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoftazure/the-new-bicep-like-and-distinct-functions-6536a0004b11">The NEW Bicep Like and Distinct Functions ✨</a> was originally published in <a href="https://medium.com/microsoftazure">Microsoft Azure</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Best MCR Base Image for Your Language? SBI Scans Nightly So You Don’t Have To]]></title>
            <link>https://medium.com/microsoftazure/the-best-mcr-base-image-for-your-language-sbi-scans-nightly-so-you-dont-have-to-62f17587a45e?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/62f17587a45e</guid>
            <category><![CDATA[supply-chain-security]]></category>
            <category><![CDATA[container-images]]></category>
            <category><![CDATA[container-security]]></category>
            <category><![CDATA[devsecops]]></category>
            <category><![CDATA[secure-containers]]></category>
            <dc:creator><![CDATA[Maninderjit (Mani) Bindra]]></dc:creator>
            <pubDate>Mon, 01 Jun 2026 14:11:09 GMT</pubDate>
            <atom:updated>2026-06-01T14:11:07.682Z</atom:updated>
            <content:encoded><![CDATA[<p>Every container you deploy starts with a base image. That image is the foundation — and if it ships with known vulnerabilities, every application you layer on top inherits them.</p><p>Yet choosing the “right” base image is still largely guesswork for most teams. Developers pull from untrusted registries, pick popular tags, assume “latest” means “safest,” and move on. The reality is harsher: industry reports consistently show that public container images often ship with known vulnerabilities, and software supply chain attacks continue to rise year over year.</p><p>The base image decision is made once but amplified across every build, every deployment, every environment. A single unpatched CVE in your base image becomes a fleet-wide exposure.</p><p>We built <a href="https://github.com/microsoft/sbi"><strong>SBI</strong> (<strong>Secure Base Image Recommendations</strong>)</a> to replace guesswork with data — specifically for <strong>Microsoft Container Registry</strong> (<strong>MCR</strong>) images.</p><h3>Introducing SBI — Secure Base Image Recommendations</h3><p><a href="https://github.com/microsoft/sbi"><strong>SBI</strong></a> is an open-source (MIT) tool that nightly scans <strong>configured</strong> <strong>MCR</strong> <strong>container</strong> <strong>base images</strong> for <strong>vulnerabilities</strong> and generates ranked recommendation reports. It answers a simple question: <em>for my language and target OS, which base image has the fewest vulnerabilities and the smallest footprint?</em></p><h3>How It Works</h3><p>Every night at 02:00 UTC, a <a href="https://github.com/microsoft/sbi/blob/main/.github/workflows/nightly-scan.yml">GitHub Actions workflow</a> runs the full pipeline:</p><ol><li><strong>Discover</strong> — Enumerate image tags from MCR</li><li><strong>Pull &amp; Analyze</strong> — Pull images, generate SBOMs with <a href="https://github.com/anchore/syft">Syft</a> to catalog installed packages and detect language runtimes</li><li><strong>Scan</strong> — Run <a href="https://github.com/aquasecurity/trivy">Trivy</a> vulnerability scanning</li><li><strong>Verify</strong> — Execute runtime commands <em>inside each container</em> to confirm detected language versions (e.g., python3 --version, dotnet --info)</li><li><strong>Store</strong> — Persist results in a SQLite database</li><li><strong>Report</strong> — Generate ranked reports, commit and push to the repository</li></ol><h3>The Ranking Algorithm</h3><p>Images are ranked <strong>per language, per base OS</strong> using this sort order:</p><ol><li>Fewest <strong>critical</strong> vulnerabilities</li><li>Fewest <strong>high</strong> vulnerabilities</li><li>Fewest <strong>total</strong> vulnerabilities</li><li><strong>Smallest image size</strong></li></ol><p>This means the #1 image in each section is the best-ranked option under SBI’s criteria: lowest known vulnerability count, then smallest size.</p><h3>What’s Covered</h3><p>The nightly scan currently covers <strong>37+ image sources</strong> across:</p><ul><li><strong>Languages:</strong> .NET, Python, Node.js, Java, Go</li><li><strong>Base/No-Runtime:</strong> Minimal and distroless images for deploying static binaries (Go, Rust, etc.)</li><li><strong>Base OSes:</strong> Azure Linux, Ubuntu, Debian</li></ul><p>See the <a href="https://github.com/microsoft/sbi/blob/main/docs/daily_recommendations.md">latest report</a> for the full list of scanned images.</p><h3>Why No Website?</h3><p>SBI started as a side project — we got tired of manually researching which base images to recommend to teams. We needed something quick and automated, not a product with a web frontend to maintain.</p><p>Plain files committed to a Git repo turned out to be the right answer: developers read markdown on GitHub, CI/CD pipelines fetch JSON via raw URLs, and security teams clone the repo and run jq locally. No servers, no hosting, no additional attack surface — just the data.</p><h3>Three Report Formats — Something for Everyone</h3><p>SBI generates three report formats nightly, each designed for a different audience and workflow.</p><h3>📄 Markdown Report — Language-Specific Recommendations</h3><p><a href="https://github.com/microsoft/sbi/blob/main/docs/daily_recommendations.md"><strong>View the latest report →</strong></a></p><p>The markdown report is a human-readable set of ranked tables, organized by language and base OS. Need the best Python image on Azure Linux? The best .NET image on Ubuntu? Just scroll to your language section and pick the top-ranked option.</p><p>Each language section is ranked by base OS. For example, in the Go section:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/869/1*hALdTxDN6TwoBa5OXQfBqg.png" /><figcaption>Go and Java recommendations from the markdown report — ranked by vulnerabilities, then size</figcaption></figure><p>Each entry includes the image digest and a <strong>pinned reference</strong> (image@sha256:...). For base images in your Dockerfile, you&#39;ll typically want the tag (e.g., :3.12) so you automatically pick up security patches when MCR pushes them. The pinned digest is valuable when deploying final images to a cluster or container app, where you want an exact, immutable reference.</p><p>The report also includes a <strong>“Base / No Runtime”</strong> section for minimal and distroless images — useful when deploying statically compiled binaries (Go, Rust) where you don’t need a language runtime at all:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/834/1*0cXkRfJFD34mxJ-FzO7Dpw.png" /><figcaption>Base / No Runtime section of markdown report</figcaption></figure><h3>📊 JSON Report — For Automation</h3><p><a href="https://github.com/microsoft/sbi/blob/main/docs/daily_recommendations.json"><strong>View the latest report →</strong></a></p><p>The JSON report provides the same per-language, per-OS rankings in a machine-readable format — a flat array of image objects with language and baseOS fields for easy filtering. Each entry includes:</p><ul><li>pinnedReference — the digest-pinned image reference</li><li>stableTag — the human-friendly tag</li><li>dockerfileFrom — ready to drop into a FROM line</li><li>Vulnerability counts, size, creation date</li></ul><p>This makes it straightforward to integrate into CI/CD pipelines, policy engines, or tooling. For instance, a tool or AI agent could read the JSON, detect the languages in your workspace, and recommend the best base images automatically.</p><h3>🔍 Detailed JSON Report — For Deeper Analysis</h3><p><a href="https://github.com/microsoft/sbi/blob/main/docs/daily_recommendations_detail.json"><strong>View the latest report →</strong></a><strong> </strong>(large file — use “View raw” or clone the repo)</p><p>Once you’ve narrowed down top-ranked images from the markdown or JSON reports, the detailed report lets you validate that choice. For <strong>every</strong> scanned image (not just top-N), it provides:</p><ul><li><strong>Full vulnerability breakdown:</strong> CVE ID, severity, CVSS score, affected package, package version, fixed version (if available), and description</li><li><strong>Complete system package inventory:</strong> Every RPM/DEB/APK package installed</li><li><strong>Package managers detected:</strong> pip, npm, etc.</li></ul><p>The report documentation includes <strong>ready-to-use </strong><strong>jq commands</strong> for common security workflows:</p><pre># List all images with critical vulnerabilities<br>jq &#39;.images[] | select(.vulnerabilitySummary.critical &gt; 0) |<br>  {name, critical: .vulnerabilitySummary.critical}&#39; \<br>  docs/daily_recommendations_detail.json<br><br># Show CVEs with available fixes for a specific image<br>jq &#39;.images[] | select(.name | contains(&quot;python:3.12&quot;)) |<br>  .vulnerabilities[] | select((.fixedVersion // &quot;&quot;) != &quot;&quot;) |<br>  {id, severity, packageName, fixedVersion}&#39; \<br>  docs/daily_recommendations_detail.json</pre><p>When comparing image alternatives, the package inventories and vulnerability details help you make an informed shortlist decision. For example, two images might have similar vulnerability counts, but one has fixes available for its CVEs while the other doesn’t — that matters when choosing between them.</p><h3>How to Use SBI in Practice</h3><p><strong>Pick a base image for your language:</strong> Browse the <a href="https://github.com/microsoft/sbi/blob/main/docs/daily_recommendations.md">markdown report</a>, find your language section, and pick the top-ranked image for your Dockerfile.</p><p><strong>Automate recommendations:</strong> Feed the <a href="https://github.com/microsoft/sbi/blob/main/docs/daily_recommendations.json">JSON report</a> into your tooling — a tool or agent can detect languages in a workspace and recommend the best available base images.</p><p><strong>Compare alternatives in depth:</strong> Use the <a href="https://github.com/microsoft/sbi/blob/main/docs/daily_recommendations_detail.json">detailed JSON report</a> to drill into package inventories and vulnerability details when narrowing down your shortlist.</p><p><strong>Run it yourself:</strong> SBI is distributed as a Go CLI. Local scanning requires <a href="https://docs.docker.com/get-docker/">Docker</a>, <a href="https://github.com/anchore/syft#installation">Syft</a>, and <a href="https://github.com/aquasecurity/trivy#get-trivy">Trivy</a> — or just use the included <a href="https://github.com/microsoft/sbi/tree/main/.devcontainer"><strong>devcontainer</strong></a> which comes preinstalled with everything:</p><pre>go install github.com/microsoft/sbi@latest<br>sbi scan --verbose</pre><h3>Verifying MCR Image Integrity</h3><p>Images on <strong>MCR</strong> are <strong>signed</strong> by Microsoft. Before deploying to production, it’s recommended to <strong>verify the integrity</strong> of the images you use.</p><p><strong>How it works:</strong> When Microsoft publishes an image, a cryptographic signature is generated that binds the publisher’s identity to the image digest. A verification tool like <a href="https://notaryproject.dev/"><strong>Notation</strong></a><strong> </strong>(from the CNCF Notary Project) checks that the signature matches a trusted certificate and that the image content hasn’t been modified since signing. If either the identity or the content doesn’t match, verification fails — telling you the image may have been tampered with.</p><h3>Verifying with Notation</h3><p>Install<strong> </strong><a href="https://notaryproject.dev/docs/user-guides/installation/cli/"><strong>Notation</strong></a><strong>,</strong> then set up Microsoft’s Supply Chain root certificate and a trust policy:</p><pre># 1. Download Microsoft&#39;s Supply Chain root certificate<br>curl -Lo msft_supply_chain_cert.crt \<br>  &quot;https://www.microsoft.com/pkiops/certs/Microsoft%20Supply%20Chain%20RSA%20Root%20CA%202022.crt&quot;</pre><pre># 2. Add it to Notation&#39;s trust store<br>notation cert add --type ca --store microsoft msft_supply_chain_cert.crt</pre><pre># 3. Create a trust policy for MCR repositories<br>cat &lt;&lt;EOF &gt; trustpolicy.json<br>{<br>    &quot;version&quot;: &quot;1.0&quot;,<br>    &quot;trustPolicies&quot;: [<br>        {<br>            &quot;name&quot;: &quot;mcrtrustpolicy&quot;,<br>            &quot;registryScopes&quot;: [<br>                &quot;mcr.microsoft.com/azurelinux/base/core&quot;,<br>                &quot;mcr.microsoft.com/azurelinux/distroless/base&quot;,<br>                &quot;mcr.microsoft.com/azurelinux/distroless/minimal&quot;,<br>                &quot;mcr.microsoft.com/azurelinux/base/python&quot;,<br>                &quot;mcr.microsoft.com/azurelinux/base/nodejs&quot;,<br>                &quot;mcr.microsoft.com/azurelinux/distroless/python&quot;,<br>                &quot;mcr.microsoft.com/azurelinux/distroless/nodejs&quot;,<br>                &quot;mcr.microsoft.com/dotnet/aspnet&quot;,<br>                &quot;mcr.microsoft.com/dotnet/runtime&quot;,<br>                &quot;mcr.microsoft.com/dotnet/sdk&quot;,<br>                &quot;mcr.microsoft.com/oss/go/microsoft/golang&quot;,<br>                &quot;mcr.microsoft.com/openjdk/jdk&quot;<br>            ],<br>            &quot;signatureVerification&quot;: {<br>                &quot;level&quot;: &quot;strict&quot;<br>            },<br>            &quot;trustStores&quot;: [&quot;ca:microsoft&quot;],<br>            &quot;trustedIdentities&quot;: [&quot;*&quot;]<br>        }<br>    ]<br>}<br>EOF</pre><pre># 4. Import the trust policy<br>notation policy import trustpolicy.json</pre><pre># 5. Verify an image (use the pinned digest from the SBI report)<br>notation verify mcr.microsoft.com/azurelinux/base/python:3.12@sha256:485299b016fe5ae745ffee27f0b8a850576841205ed1d420c9a84b126198e320</pre><pre># Successfully verified signature for <br># mcr.microsoft.com/azurelinux/base/python@sha256:485299b...</pre><p>The registryScopes above <strong>include</strong> repositories currently scanned by <strong>SBI</strong>. Add any other <strong>MCR</strong> repository you use. The root certificate reference comes from <a href="https://techcommunity.microsoft.com/blog/containers/announcing-image-signing-for-windows-containers/3792097">Microsoft&#39;s image signing announcement</a>.</p><p>For <strong>Kubernetes</strong> environments, <a href="https://github.com/ratify-project/ratify"><strong>Ratify</strong></a> can enforce signature verification at admission time — ensuring only verified images are deployed to your clusters.</p><p>For more details, see Microsoft’s documentation:</p><ul><li><a href="https://learn.microsoft.com/en-us/azure/container-registry/overview-sign-verify-artifacts">Overview of signing and verifying OCI artifacts</a></li><li><a href="https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tutorial-verify-with-ratify-aks">Verify container image signatures with Ratify and Azure Policy</a></li></ul><h3>Why SBI</h3><ul><li><strong>Data-driven:</strong> Objective ranking based on real vulnerability scans, not opinions or popularity</li><li><strong>Fresh daily:</strong> Nightly scans mean vulnerability data is always current — even if an MCR image hasn’t been updated in days, newly disclosed CVEs affecting it will show up in the next report</li><li><strong>Community-extensible:</strong> Want an MCR image added to the nightly scan? Submit a PR adding it to config/repositories.json — after merge, the next nightly run will pick it up</li><li><strong>Not limited to MCR:</strong> The SBI repository is configured to scan MCR images by default, but the tool itself supports any OCI-compliant registry. Fork it and point it at Docker Hub, GitHub Container Registry, or your private registry</li></ul><h3>Get Started</h3><p>Your container’s security posture starts with the base image. Stop guessing — let data drive that decision.</p><ul><li>📦 <strong>Repo:</strong> <a href="https://github.com/microsoft/sbi">github.com/microsoft/sbi</a></li><li>📄 <strong>Latest markdown report:</strong> <a href="https://github.com/microsoft/sbi/blob/main/docs/daily_recommendations.md">daily_recommendations.md</a></li><li>📊 <strong>Latest JSON report:</strong> <a href="https://github.com/microsoft/sbi/blob/main/docs/daily_recommendations.json">daily_recommendations.json</a></li><li>🔍 <strong>Latest detailed report:</strong> <a href="https://github.com/microsoft/sbi/blob/main/docs/daily_recommendations_detail.json">daily_recommendations_detail.json</a> (large file — use “View raw” or clone the repo)</li></ul><p><strong>Want an MCR repository scanned?</strong> <a href="https://github.com/microsoft/sbi/pulls">Open a PR</a> adding it to config/repositories.json.</p><p><strong>Use a different registry?</strong> Fork the repo, update repositories.json with your image sources, and set up the nightly workflow for your own registry.</p><p>Contributions are welcome — whether it’s adding new image sources, improving language detection, or extending report formats. <a href="https://github.com/microsoft/sbi">Check out the repo</a> to get started. If you find it useful, a ⭐ helps others discover it.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=62f17587a45e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoftazure/the-best-mcr-base-image-for-your-language-sbi-scans-nightly-so-you-dont-have-to-62f17587a45e">The Best MCR Base Image for Your Language? SBI Scans Nightly So You Don’t Have To</a> was originally published in <a href="https://medium.com/microsoftazure">Microsoft Azure</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Inspecting AKS East-West Traffic with Next-Generation Firewalls: Solving a Problem Kubernetes…]]></title>
            <link>https://medium.com/microsoftazure/inspecting-aks-east-west-traffic-with-next-generation-firewalls-solving-a-problem-kubernetes-bfe9f10cddd8?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/bfe9f10cddd8</guid>
            <dc:creator><![CDATA[Stephane Eyskens]]></dc:creator>
            <pubDate>Mon, 01 Jun 2026 14:11:02 GMT</pubDate>
            <atom:updated>2026-06-01T14:11:00.655Z</atom:updated>
            <content:encoded><![CDATA[<h3>Inspecting AKS East-West Traffic with Next-Generation Firewalls: Solving a Problem Kubernetes Already Solved</h3><h3>Introducing the article</h3><p>This article explores the challenges and architectural trade-offs of enforcing Next-Generation Firewall (NGFW) inspection for East-West traffic inside Azure Kubernetes Service (AKS), particularly when using Azure CNI Overlay. While Kubernetes and the CNCF ecosystem already provide mature cloud-native security capabilities such as network policies, mTLS, runtime protection, and workload isolation, some organizations still require traditional firewall inspection between internal services.</p><p>The article explains why this requirement is difficult to implement with Azure CNI Overlay, since pod-to-pod traffic remains encapsulated and invisible to Azure networking constructs such as route tables and NSGs. It then presents several architectural approaches to force traffic through Azure Firewall, including the use of Application Gateway as an internal reverse proxy combined with Istio Gateway API resources, as well as an alternative design based on Private Link Service (PLS).</p><p>The discussion highlights the technical feasibility while maintaining a deliberately ironic tone toward applying traditional perimeter-security thinking to modern cloud-native environments.</p><h4>Explaining the problem statement and trying to persuade CISO first</h4><p>Kubernetes and the broader <strong>Cloud Native Computing Foundation (CNCF)</strong> landscape offer many tools and products to control layer 4 and layer 7 traffic efficiently. AKS itself ships with Advanced Container Networking Services, which allows you to control and observe your network traffic at scale.</p><p>However, some CISO departments only swear by Next-Generation firewalls, <em>including for East-West traffic inside the cluster</em>. While this requirement makes sense for North-South (Ingress/Egress), it is rather less interesting to inspect traffic and leverage IDPS features for pod-to-pod communication, where both sides of the communication are 100% under your control. Having a good security posture like, ensuring an end to end follow up from the supply chain to the running container, using the following methods:</p><ul><li>SAST and DAST (e.g. Snyk, JFrog Xray) to detect and remediate vulnerabilities.</li><li>Applying strict policies enforced by Gatekeeper, making sure that containers do not run as root, have read-only file systems, restricted capabilities, etc., effectively minimizing the potential impact of a malicious activity.</li><li>Ensuring runtime security using solutions such as Defender for containers, CrowdStrike or CNCF solutions such as Falco, to detect and suspicious activity in real-time.</li><li>Adopting the least privilege approach and identity-level controls such as mTLS, fine-grained authorizations and token validation using built-in addons such as Istio.</li><li>Applying native network policies with K8s, Calico or Cilium to prevent unexpected lateral movements.</li><li>Making sure internet ingress traffic is proxied and inspected by a WAF (e.g Cloudflare, Application Gateway, Imperva, etc.) and egress traffic is routed to a next-gen firewall.</li><li>Leverage NSGs to rule Azure-level traffic in addition to the next gen firewalls.</li><li>Running private clusters.</li></ul><p>All the above, among other things, should in theory satisfy most security requirements. Additionally, you can offload data to Azure data services for apps you build yourself, which means that you can leverage native Azure security and governance tools to handle data concerns.</p><p>At last, in the Cloud and although Kubernetes was not built for this, it is also rather easy to work with dedicated clusters as we can easily provision them. You can decide to govern them all using fleet managers to ensure consistency across clusters.</p><p>Working with dedicated clusters allows you to drastically reduce the blast radius should any incident, security-related or not, occur.</p><p>However, despites the numerous possibilities, some security teams, about 12 years after the launch of Kubernetes and 13 years after the launch of Docker, still don’t get it and only see security through firewalls. Nothing else exist but firewalls.</p><p>So, if your CISO department were to momentarily or permanently lose its senses and you still had to address these next-gen firewalls pressing requirements, you may first try some of the following:</p><ol><li>Do not use K8s, just use plain VMs and forget about cloud native. You may as well stay on-premises and do business as usual. A bit radical but efficient!</li><li>Send your CISO staff to trainings.</li></ol><p>If they still don’t get it (most likely), I’m afraid you’ll have to read the next section.</p><h3>You couldn’t escape!</h3><p>If your attempt to convince CISO failed miserably, I’m afraid you’ll have to resort to one of the following options:</p><ol><li>Leverage specialized products such as Palo Alto CN Series. This type of products live inside the cluster and let you define K8s-friendly policies and keep your single pane of glasses whether dealing with containers or not.</li><li>Use Azure-native constructs, and, that’s what I’m going to focus on.</li></ol><p>First things first, using Azure CNI or CNI Overlay is already a game changer. With Azure CNI, the regular Azure network controls can be applied as with plain virtual machines or any other VNET-friendly PaaS service. With CNI Overlay, pod-to-pod traffic as well as pod-to-load balancer traffic is completely encapsulated within the overlay layer, making this traffic <strong>insensitive </strong>to route tables and network security groups. Simply put, Azure doesn’t even see this traffic. Many companies prefer CNI Overlay over CNI because it consumes much less IP addresses.</p><p>Since the real challenge is with CNI Overlay, I will only focus on this.</p><p>Regardless of the chosen network interface, dealing with North-South is easy:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/694/1*OPFb2_dHNqAra3U27a0Vew.png" /><figcaption>Simplified view of North-South traffic handling</figcaption></figure><p>Traffic coming from the outside is typically proxied by a Web Application Firewall (WAF) forwarded or not to a next gen firewall which ultimately forwards the traffic to the AKS’s internal load balancer (ILB) used by our ingress controllers and/or our K8s gateways. For API-related traffic, we may also add an API gateway behind the WAF, in the hub or in the spoke before hitting the ILB. The rule of thumb here is to avoid exposing AKS directly to internet.</p><p>For cluster egress traffic, internet-bound or not, we can easily route everything to a next gen firewall. The CNI we use in AKS makes no difference since all these IPs and FQDNs are external to the cluster so, all can be caught by the usual Azure plumbing. All of the above is business as usual, nothing new but just a refresh.</p><p>Now, what if we want our Backend-for-Frontend (BFF), behind a WAF, to go through a firewall before it can talk to the actual backend?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/446/1*tCt83R7b_ZWrg1GZ2I48vg.png" /><figcaption>East-West traffic through firewall</figcaption></figure><p>Both, our frontend and backend layers are AKS namespaces. The WAF (not shown above), proxies the BFF. We want our BFF to transit to a next-gen firewall before it can talk to the actual backend.</p><p>Well, by default, we can’t because both the BFF and the backend pods are part of the pod CIDR range, which in turn, is part of the overlay network, regardless of the node they are running onto. So, even splitting nodes into different node pools mapped to different subnets doesn’t change anything, since both pods will anyway remain in that CIDR range that is not even seen by Azure. The same consideration applies to the AKS service range of course. Since Azure cannot “see” those IPs, none of the traditional network components (route tables, NSGs, etc.) can come to the rescue. So, the above setup simply doesn’t work. Beware that this works with Kubenet because, unlike CNI Overlay, when pods are distributed across nodes and subnets, Azure sees the node IP instead of the pod IP. However, since Kubenet is on the deprecation path, its use is strongly discouraged.</p><p>You may think, ok, let’s use a service of type <strong>LoadBalancer </strong>instead<strong> </strong>of a <strong>ClusterIP </strong>one<strong> </strong>with an external IP, as illustrated below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/578/1*iZE20DXyMmTRMjuhtBurvg.png" /><figcaption>Trying to leverage the ILB</figcaption></figure><p>Although the IP address you define originates from a subnet of your choice, and is, as such, not part of the cluster itself, it remains totally invisible to Azure since the CNI Overlay plumbing encapsulates it…So, you can’t put a route table on the frontend subnet with a route targeting the load balancer one because when the BFF is calling the ILB IP, it’d still be seen as “internal” traffic. Additionally, you would not be able to specify a return route on the backend subnet since the pods running in the frontend subnet are part of the pod CIDR range…so no luck with this setup either.</p><p>The reason why ILB is considered internal is because the IPs provisioned on the load balancer are not true network interfaces. Therefore, we need something else. One of the options is to use Application Gateway but this time as a mere reverse-proxy (WAF is not required) to proxy the ILB. Here is an end-to-end example using Application Gateway, Istio and the native support of K8s gateway CRD (in preview as of 05/2026 when used together with Istio).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FmEk__IRKRt8XrL9PER3sQ.png" /><figcaption>Using Application Gateway, Istio and Calico or Cilium</figcaption></figure><p>The entry point is one WAF-enabled Application Gateway instance to inspect incoming internet traffic. In our example, the UI components as well as the BFF are internet facing. You may decide to split them should you want parallel channels for internal and external access. Note that this is also feasible with a single frontend layer.</p><p>Another Application Gateway instance using internal listeners only is used to proxy the internal frontend layer materialized by IP addresses exposed on the ILB. You use K8s gateways for HTTP and API traffic. In the above diagram, I’m only considering a single application but you could use a similar technique with one or two main K8s gateways per application, each having its own listeners on the Application Gateway. In this single app example, all the API endpoints can be behind a single gateway resource and my HTTP endpoints behind another one. My API routes use prefixes (e.g. /apis/api1) behind the same FQDN. This allows for a one-shot configuration at the level of Application Gateway.</p><p>You should also make sure to control internal traffic so that only the ingress-related namespaces are allowed to talk to other namespaces. Similarly, you should prevent backend namespaces to directly target the ILB IPs using either Calico or Cilium policies since they would bypass the Application Gateway. In other words, you must combine cloud-native controls with Azure appliances such as Azure Firewall. Now, because the traffic flows over Application Gateway, you can easily use route tables and NSGs as shown below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7yI_eyoMOzw2F0anvtJPqA.png" /><figcaption>Steering traffic to Azure Firewall</figcaption></figure><p>In practice, this means that traffic flows from the Application Gateway to the gateway pods running on nodes connected to the ingress subnet through Azure Firewall. A route table applied to the ingress subnet ensures the return route. Communication between the gateway pod and the actual backend pods, such as the BFF or backend services, remains encapsulated within the overlay network. When the BFF invokes a backend service, it must use the FQDN exposed through the Application Gateway, which in turn directs the traffic through Azure Firewall. The relationship between the gateway pod and the backend pods is established through the HTTPRoute CRD. By locking down traffic internally, you should make sure to only allow the BFF to talk back to Application Gateway and nothing else. Other AKS subnets could also route traffic destined to Application Gateway to Azure Firewall, which in this case, requires a return route on the gateway subnet (red routes in the diagram). Note that return routes in general are only required if you do not apply SNAT at the level of the firewall.</p><p>In practice, the above setup requires a few FQDNs to be published to Application Gateway:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/713/1*T_xxiiAGl1kHCq8JTU9G6Q.png" /><figcaption>Sample Application Gateway configuration</figcaption></figure><p>where FQDNs should target the private frontend IP of the Application Gateway. Then you should define your backends and use routing rules to map the frontend FQDN to the one known by AKS. For example, bff.eyskens.internal forwards to bff-aks.eyskens.internal, which uses one of the ILB IPs as shown below.</p><pre>gatewayClassName: istio<br>  infrastructure:<br>    annotations: <br>      service.beta.kubernetes.io/azure-load-balancer-internal: &quot;true&quot;<br>      service.beta.kubernetes.io/azure-load-balancer-internal-subnet: &quot;ingress&quot;<br>      service.beta.kubernetes.io/azure-load-balancer-ipv4: &quot;10.0.1.8&quot;</pre><p>The gateway should allow HTTPRoute resources to reference whenever needed. Here is an example of such route:</p><pre>apiVersion: gateway.networking.k8s.io/v1<br>kind: HTTPRoute<br>metadata:<br>  name: bff<br>  namespace: frontend<br>spec:<br>  parentRefs:<br>  - name: bff-gateway<br>    namespace: ingress<br>  hostnames: [&quot;bff-aks.eyskens.internal&quot;]<br>  rules:</pre><p>The above snippet will be considered a match whenever bff-aks.eyskens.internal is called by the Application Gateway.</p><p>Next, when the BFF calls a backend service, it does it using the FQDN published on Application Gateway, such as for example api.eyskens.internal/apis/api1. You could decide to use the same technique to the backend layer itself if required or let them call each other internally.</p><p>The downside of this approach is an additional complexity, compared to simply using the built-in tools. Moreover, the Application Gateway generates extra costs.</p><p>As an alternative, you could use <strong>Private Link Service (PLS)</strong>, to expose private endpoints mapped to the ILB IPs. This way, traffic destined to those private endpoints can be steered to Azure Firewall. Most of the previous setup considerations also apply here.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/487/1*kWxq3bqo1Ep--FB5GUZNXQ.png" /><figcaption>Use Private Link Service (PLS) to map private endpoints to ILB IPs</figcaption></figure><p>With the above setup, all FQDNs should target the private endpoints that are used by PLS to forward traffic to the ILB IPs. The benefit of this approach is that PLS is free of charge. Private endpoints are not but they’re cheaper than Application Gateway. The only potential change compared to the previous approach, is the way you handle routing to and from private endpoints since these are special beast (see this post <a href="https://medium.com/microsoftazure/top-asymmetric-routing-issues-and-unexpected-firewall-bypass-in-azure-7456a1c1a9ff">https://medium.com/microsoftazure/top-asymmetric-routing-issues-and-unexpected-firewall-bypass-in-azure-7456a1c1a9ff</a> for more info). Regardless, you should make sure that the subnet holding the private endpoints is configured with the appropriate network policy.</p><p>Note that if you are mostly dealing with APIs, you may as well consider using Azure API Management (APIM) instead of Application Gateway and use exactly the same routing methods. APIM would also allow you to deal more efficiently with APIs than Application Gateway.</p><h4>Conclusion</h4><p>Ultimately, trying to force traditional Next-Generation Firewall patterns onto Kubernetes East-West traffic often results in significant architectural complexity to solve a problem the cloud-native ecosystem already addresses more elegantly through identity, policy, workload isolation, runtime security, and observability. While Azure-native constructs such as Application Gateway, API Management, Azure Firewall, and Private Link Service can technically satisfy stringent network inspection requirements, they introduce additional costs, routing considerations, operational overhead, and design constraints. In most cases, organizations should first evaluate whether modern Kubernetes-native security controls already provide the required level of protection before reproducing legacy datacenter patterns inside AKS. However, when governance or compliance requirements leave no room for negotiation, the approaches described in this article can provide a pragmatic path forward.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bfe9f10cddd8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoftazure/inspecting-aks-east-west-traffic-with-next-generation-firewalls-solving-a-problem-kubernetes-bfe9f10cddd8">Inspecting AKS East-West Traffic with Next-Generation Firewalls: Solving a Problem Kubernetes…</a> was originally published in <a href="https://medium.com/microsoftazure">Microsoft Azure</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[This is why you should start using Azure SRE Agents! ]]></title>
            <link>https://medium.com/microsoftazure/this-is-why-you-should-start-using-azure-sre-agents-3bbf757d0541?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/3bbf757d0541</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[azure]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[microsoft]]></category>
            <dc:creator><![CDATA[Brian Veldman]]></dc:creator>
            <pubDate>Mon, 11 May 2026 17:22:35 GMT</pubDate>
            <atom:updated>2026-05-11T17:22:38.430Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wgXrTyQkP6P1pEnE7TenMw.png" /></figure><p>Azure SRE Agent helps you maintain the health and performance of your Azure resources through AI-powered monitoring and assistance. Agents continuously watch your resources for problems, provide troubleshooting help, and suggest remediation steps in a natural-language chat interface. To ensure accuracy and control, any action that an agent takes on your behalf requires your approval. In this blog I will show you the power of Azure SRE agents, how to get started! While we could do everything using ClickOps why not automate using Azure Bicep? 💪🏻</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/768/1*Exjz-DS-8DmwIAjj2add_A.gif" /><figcaption>Diagram of how the Bicep Azure SRE Agent deployment looks like ❤</figcaption></figure><p>The main.bicep template serves as the entry point for the Bicep configuration and defines the parameters, variables, and core resources used throughout the deployment. It orchestrates the provisioning of key Azure components such as Log Analytics, Application Insights, a managed identity, and the Azure SRE agent. Additionally, it configures role based access control assignments and sets up the necessary permissions and context for the SRE agent to monitor, analyze, and interact with resources within the specified scope.</p><pre>metadata name = &#39;Azure SRE Deployment&#39;<br>metadata description = &#39;Deploys Azure SRE resources&#39;<br>metadata owner = &#39;Brian Veldman&#39;<br>metadata version = &#39;1.0.0&#39;<br><br>targetScope = &#39;resourceGroup&#39;<br><br>@description(&#39;Solution name for resource naming&#39;)<br>param parSolution string = &#39;infra&#39;<br><br>@description(&#39;Deployment environment&#39;)<br>param parEnvironment string = &#39;prod&#39;<br><br>@description(&#39;Deployment number for uniqueness&#39;)<br>param parDeploymentNumber string = &#39;001&#39;<br><br>@description(&#39;Deployment location&#39;)<br>@allowed([<br>  &#39;eastus2&#39;<br>  &#39;swedencentral&#39;<br>  &#39;australiaeast&#39;<br>])<br>param parLocation string = &#39;swedencentral&#39;<br><br>@description(&#39;Model provider&#39;)<br>param parDefaultModelProvider string = &#39;Anthropic&#39;<br><br>@description(&#39;User object id&#39;)<br>param parUserObjectId string = deployer().objectId<br><br>@allowed([<br>  &#39;Low&#39;<br>  &#39;Medium&#39;<br>  &#39;High&#39;<br>])<br>param parAccessLevel string = &#39;Low&#39;<br><br>@description(&#39;Defining our variables&#39;)<br>var varShortEnvironmentMapping = {<br>  swedencentral: &#39;swc&#39;<br>  eastus2: &#39;eus2&#39;<br>  australiaeast: &#39;aue&#39;<br>}<br>var varShortEnvironment = varShortEnvironmentMapping[parLocation] ?? parLocation<br><br>@description(&#39;Deploy Log Analytics Workspace&#39;)<br>resource workspace &#39;Microsoft.OperationalInsights/workspaces@2023-09-01&#39; = {<br>  name: &#39;log-${parSolution}-${parEnvironment}-${varShortEnvironment}-${parDeploymentNumber}&#39;<br>  location: parLocation<br>  properties: {<br>    sku: {<br>      name: &#39;PerGB2018&#39;<br>    }<br>    retentionInDays: 30<br>    features: {<br>      enableLogAccessUsingOnlyResourcePermissions: true<br>    }<br>  }<br>}<br><br>@description(&#39;Deploy Application Insights&#39;)<br>resource appInsights &#39;Microsoft.Insights/components@2020-02-02&#39; = {<br>  name: &#39;appi-${parSolution}-${parEnvironment}-${varShortEnvironment}-${parDeploymentNumber}&#39;<br>  location: parLocation<br>  kind: &#39;web&#39;<br>  properties: {<br>    Application_Type: &#39;web&#39;<br>    Request_Source: &#39;SreAgent&#39;<br>    WorkspaceResourceId: workspace.id<br>  }<br>}<br><br>@description(&#39;User assigned identity for the agent&#39;)<br>resource identity &#39;Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30&#39; = {<br>  name: &#39;id-${parSolution}-${parEnvironment}-${varShortEnvironment}-${parDeploymentNumber}&#39;<br>  location: parLocation<br>}<br><br>@description(&#39;Deploy SRE Agent&#39;)<br>#disable-next-line BCP081<br>resource agent &#39;Microsoft.App/agents@2025-05-01-preview&#39; = {<br>  name: &#39;sre-${parSolution}-${parEnvironment}-${varShortEnvironment}-${parDeploymentNumber}&#39;<br>  location: parLocation<br>  identity: {<br>    type: &#39;SystemAssigned, UserAssigned&#39;<br>    userAssignedIdentities: {<br>      &#39;${identity.id}&#39;: {}<br>    }<br>  }<br>  properties: {<br>    knowledgeGraphConfiguration: {<br>      managedResources: []<br>      identity: identity.id<br>    }<br>    actionConfiguration: {<br>      mode: &#39;review&#39;<br>      identity: identity.id<br>      accessLevel: parAccessLevel<br>    }<br>    logConfiguration: {<br>      applicationInsightsConfiguration: {<br>        appId: appInsights.properties.AppId<br>        connectionString: appInsights.properties.ConnectionString<br>      }<br>    }<br>    defaultModel: {<br>      provider: parDefaultModelProvider<br>      name: &#39;Automatic&#39;<br>    }<br>  }<br>}<br><br>@description(&#39;Assign SRE Agent Administrator role to the user at agent scope&#39;)<br>resource agentAdminRole &#39;Microsoft.Authorization/roleAssignments@2022-04-01&#39; = {<br>  name: guid(agent.id, parAccessLevel, &#39;agent-admin&#39;)<br>  scope: agent<br>  properties: {<br>    roleDefinitionId: resourceId(&#39;Microsoft.Authorization/roleDefinitions&#39;, &#39;e79298df-d852-4c6d-84f9-5d13249d1e55&#39;)<br>    principalId: parUserObjectId<br>    principalType: &#39;User&#39;<br>  }<br>}</pre><p>Customize the code to align with your specific requirements, then execute it. After a few minutes, all the necessary resources will be deployed. This can be done using: New-AzResourceGroupDeployment -Name deploymentName -TemplateFile .\main.bicep.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mZgW_YFo_XLcFSVhGs1aCw.png" /></figure><p>We can see the Azure resources deployed within the resource group.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vvyV9Zf0ijS2b1zG7FBySg.png" /></figure><p>To start using the Azure SRE agent we just deployed, go to the <a href="https://sre.azure.com/">SRE Azure portal</a>, and click on the name of the agent.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Cdg5BnGz-1Tv4_4okHnuHA.png" /></figure><p>When reviewing the Azure SRE resource, we can provide the agent with context to enable more effective investigations. The more context it has, the better it can correlate changes, dependencies, and issues across your environment. In this case, the SRE agent does not yet have any information about my applications, so it will not be able to answer questions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8o4NBedTMcnxRNRrqwjr2g.png" /></figure><p>For the first example, I will provide the Azure SRE agent with context about a specific resource group within my subscription. The agent analyzes Azure resources to understand the service architecture, dependencies, and runtime context of the system.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4EmmccRDvdGDNJVmZj_ENA.png" /></figure><p>I checked the ZTA resource group because this is a proof of concept I am running, and I want to grant the Azure SRE agent access to it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*n5oeYB_Vjjkx4JZWNFxLmQ.png" /></figure><p>Next, it is up to you to decide which permissions the agent receives. You can choose between Reader and Privileged access. Privileged access includes both read and write permissions, allowing the agent to diagnose issues and perform remediation actions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7_9ROdCeq2rRWGOoKud8dw.png" /></figure><p>After waiting a couple of seconds, the permissions have been added. You can remove them at any time if needed. For now, this is enough. It is time to test our SRE agent.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VgIMa9dWlrLnQhcRM84zlQ.png" /></figure><p>For the best and full experience I visit sre.azure.com From there I can select the SRE agent we deployed using Bicep. 💪🏻</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y7mJ0WzSRUaZ75KfrqEqMw.png" /></figure><p>From here, we can interact with the SRE agent. For this example, users have reported that the Azure Web App in Canada Central is not functioning, which is why I will ask the Azure SRE agent to investigate and determine how to resolve the issue.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VUBYsSOeK-wreA8_k9hTaQ.png" /></figure><p>Within seconds, it detects that the Azure App Service is in a stopped state. It then requests permission to start the Azure App Service, since the Azure SRE agent is running in read only mode and any action it wants to perform must be approved. Before proceeding, I want to verify in the Azure portal that the Azure App Service is not running.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*G4-qPuui_MTYYY5DeCzbqA.png" /></figure><p>When checking the Azure App Service in the Azure Portal, it appears that it is not running… 😱</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yMZb7fmRka8VTUV-av35hw.png" /></figure><p>Next, we can approve the action to allow the SRE agent to start the Azure App Service to remediate the issue.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bOmYKRlGFl06D6mjwYOdvA.png" /></figure><p>And just like that, the Azure App Service is running. This means users can now access the web app. 💪🏻</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F9z1j2mHFx7c7FTpwh4DKQ.png" /></figure><p>We also receive the root cause analysis, which shows that Brian Veldman stopped the Azure App Service four minutes before we started interacting with the Azure SRE agent. It also provides recommended next steps to help prevent these types of issues in the future.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*szEDzwtZM3Z0Pv0sik3AFA.png" /></figure><p>From a monitoring perspective, we can see what users are asking the Azure SRE agents. All logs are sent to Log Analytics and are also visible in Azure Application Insights.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QjSOJFkkzAMwbXjpGDGMMA.png" /></figure><p>When reviewing one of the end to end transactions, we can see the message the user sent: <em>“Users are complaining that my Azure Web App is not accessible in Canada Central.”</em> This is correct and aligns with the session we previously conducted to resolve the issue and perform the root cause analysis.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rJibnkfzRQRafrh-5MqcEQ.png" /></figure><p>So, as you saw, the Azure SRE agents are super powerful! However, what we did until now was manually asking the Azure SRE agent to check the Web App issue. In production scenarios, you want to do this in an automated way. This is where Azure SRE Agents Incident Management kicks in. You can connect your incident platform, like Azure Monitor. 😍</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dIBev-9TB-SrTzVFQ69XsQ@2x.png" /></figure><h4>Azure SRE Agents pricing</h4><p>From a billing perspective there are two things to consider:</p><ul><li>First, there is the always on flow, which represents the fixed cost of keeping the agent running. This is billed per hour as long as the agent is active, regardless of whether it is doing any work. It ensures that the agent is continuously available, monitoring and ready to respond. This is a fixed baseline which costs 4 AAU (Azure Agent Units) per hour, which means 2.920 AAU per month (730 hours x 4 AAU/h) = ~<strong>€253.46</strong></li><li>Second, there is the active flow, which represents the variable, usage based cost. This is billed in Azure Agent Units based on the actual work performed by the agent, such as processing events, triggering actions, or generating responses. You only incur these costs when the agent is actively handling tasks.</li></ul><p>For this example it costed me ~3 EUROS for 2/3 hours;</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HRDNIlzbIac97kDroGb9DQ.png" /></figure><h4>Azure SRE Agents + Service Provider Tenant = ❤️</h4><p>Can we use SRE agents to manage multi-tenant Azure resources using Lighthouse? Yes. By assigning the appropriate permissions through the service provider offer, we can connect to customer resources, resource groups, or subscriptions and perform analysis using the Azure SRE agent hosted in the service provider tenant.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wW6SvbR5UtepGVq79rfXug.png" /></figure><p>That’s all for today. As you could see Azure SRE Agent helps you maintain the health and performance of your Azure resources through AI-powered monitoring and assistance. The Azure Bicep code is available in my GitHub repository: <a href="https://github.com/brianveldman/azure-bicep">GitHub — brianveldman/azure-bicep</a>. Feel free to star the repository and clap for this story. Also, let me know if you have any feedback. I look forward to our next session. That’s all for today, until then, take care! ❤️</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3bbf757d0541" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoftazure/this-is-why-you-should-start-using-azure-sre-agents-3bbf757d0541">This is why you should start using Azure SRE Agents! 😍</a> was originally published in <a href="https://medium.com/microsoftazure">Microsoft Azure</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The 10 Commandments of Azure Development]]></title>
            <link>https://medium.com/microsoftazure/the-10-commandments-of-azure-development-008f8cd7a2cd?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/008f8cd7a2cd</guid>
            <dc:creator><![CDATA[Stephane Eyskens]]></dc:creator>
            <pubDate>Fri, 24 Apr 2026 13:50:03 GMT</pubDate>
            <atom:updated>2026-04-24T13:50:02.616Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/256/1*KDLn4NkLluJa1n8a-nzjlQ.png" /><figcaption>The 10 Commandments of Azure Development</figcaption></figure><h3>I. Embrace the broader ecosystem</h3><p>In Azure and AKS, your code is only part of the system, the platform’s SDKs, services, and tools are just as critical. Use local debuggers, emulators, and CI/CD pipelines, and treat infrastructure with the same curiosity as your own code because it will be your own code one day.</p><h3>II. Design for horizontal scaling</h3><p>Ban in-memory sessions, caches, and tokens from your code, and design business transactions to survive horizontal scale.</p><h3>III. Design for failure</h3><p>Transient errors are mainstream. Design your applications so they <strong>expect timeouts, retries, restarts, and partial outages</strong>. Make applications multi-region aware and do not rely solely on infrastructure for resilience.</p><h3>IV. Instrument early</h3><p>Adopt <strong>OpenTelemetry </strong>early, or observability will always lag behind reality.</p><h3>VI. Master OAuth and OIDC early</h3><p>They are mainstream in the cloud, and no modern application can be built without them.</p><h3>VII. Breathe Event-Driven Architecture</h3><p>Whatever the architecture style you choose, you will eventually build a distributed system.</p><h3>VIII. Breathe API-Driven Architecture</h3><p>Whatever the architecture style you choose, you will eventually rely on APIs.</p><h3>IX. Master containers</h3><p>Containers are on your way no matter what.</p><h3>X. Read the Azure Cloud Native Architecture Mapbook</h3><p><strong>You should see the whole picture:</strong> to truly understand Azure and AKS — application development and beyond — step back, think holistically, identify tradeoffs and deepen your architectural views.</p><p>Check out my new book <a href="https://www.amazon.com/Azure-Cloud-Native-Architecture-Mapbook/dp/1805805053">https://www.amazon.com/Azure-Cloud-Native-Architecture-Mapbook/dp/1805805053</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/160/1*XJjMgaN2zZBGuDQVDbXv2Q.png" /><figcaption>The Azure Cloud Native Architecture Mapbook</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=008f8cd7a2cd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoftazure/the-10-commandments-of-azure-development-008f8cd7a2cd">The 10 Commandments of Azure Development</a> was originally published in <a href="https://medium.com/microsoftazure">Microsoft Azure</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The 10 Commandments of Azure Solution Architecture]]></title>
            <link>https://medium.com/microsoftazure/the-10-commandments-of-azure-solution-architecture-1d3c1346e2dc?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/1d3c1346e2dc</guid>
            <dc:creator><![CDATA[Stephane Eyskens]]></dc:creator>
            <pubDate>Mon, 06 Apr 2026 15:49:32 GMT</pubDate>
            <atom:updated>2026-04-06T15:49:31.104Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/256/1*unjAbRIUDzK2b4OKgpx0EQ.png" /><figcaption>The 10 Commandments of Azure Solution Architecture</figcaption></figure><h3>I. Think workload types, not services</h3><p>Azure is too vast to approach service‑by‑service. Categorize workloads into <strong>Systems of Engagement (SoE), Systems of Record (SoR), Systems of Insights (SoIn), Systems of Intelligence (SoI), and Systems of Integration (SoInt) </strong>to see the bigger picture. Connect the Azure services to these workload types to gain clarity.</p><h3>II. Let non‑functional requirements drive architecture decisions</h3><p>In the cloud, there are a thousand ways to achieve the same outcome but it is not magically scalable, performant, or secure. You must make it so!</p><h3>III. Breathe Event-Driven and API-Driven architecture styles</h3><p>Whatever the architecture style you choose, you will eventually build a distributed system that will contain APIs.</p><h3>IV. Return to fundamentals</h3><p>In the cloud, there are a thousand ways to achieve the same outcome (again ). Only strong fundamentals (eg: ACID vs BASE, discrete events vs telemetry, streaming vs batch processing, request/reply vs asynchronous, etc.) make the right way obvious and help you pick the right technologies.</p><h3>V. Understand the platform rules</h3><p>What you can design is largely shaped by how the underlying platforms are governed. Know the rules before you start drawing. Be disruptive if rules don’t make sense.</p><h3>VI. Master OAuth and OIDC early</h3><p>They are mainstream in the cloud, and no modern solution can be built without them.</p><h3>VII. Master Azure, Kubernetes and OpenShift networking fundamentals</h3><p>No modern solution exists independently of its network architecture.<br>Understanding Azure, Kubernetes and OpenShift networking is essential to grasp how workloads integrate, communicate, and sometimes even how components of the <em>same</em> system interact. Core concepts such as <strong>north–south</strong> and <strong>east–west</strong> traffic are foundational, non-negotiable.</p><h3>VIII. Anticipate capacity limits</h3><p>This page <a href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits">https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits</a> should be your primary reference and single source of truth before designing any solution.</p><h3>IV. Do not hide behind abstraction</h3><p>An <strong><em>Azure </em></strong>Solution Architect is <strong><em>specialized by design</em></strong> as opposed to a generalist<strong>. </strong>High-level abstraction is not enough to shine.</p><h3>X. Read the Azure Cloud Native Architecture Mapbook</h3><p><strong>You should see the whole picture:</strong> to truly understand Azure Solution Architecture and beyond — step back, think holistically, identify tradeoffs and deepen your architectural views.</p><p>Check out my new book <a href="https://www.amazon.com/Azure-Cloud-Native-Architecture-Mapbook/dp/1805805053">https://www.amazon.com/Azure-Cloud-Native-Architecture-Mapbook/dp/1805805053</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/160/1*XJjMgaN2zZBGuDQVDbXv2Q.png" /><figcaption>The Azure Cloud Native Architecture Mapbook</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1d3c1346e2dc" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoftazure/the-10-commandments-of-azure-solution-architecture-1d3c1346e2dc">The 10 Commandments of Azure Solution Architecture</a> was originally published in <a href="https://medium.com/microsoftazure">Microsoft Azure</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Integrating Azure Bastion in Azure Virtual WAN setup]]></title>
            <link>https://medium.com/microsoftazure/integrating-azure-bastion-in-azure-virtual-wan-setup-2d4e61712dc6?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/2d4e61712dc6</guid>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[security]]></category>
            <category><![CDATA[azure]]></category>
            <category><![CDATA[networking]]></category>
            <category><![CDATA[microsoft]]></category>
            <dc:creator><![CDATA[Brian Veldman]]></dc:creator>
            <pubDate>Mon, 06 Apr 2026 15:49:23 GMT</pubDate>
            <atom:updated>2026-04-06T15:49:21.580Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*c2hfbXCntnYbwHFn.png" /></figure><p>Azure Virtual WAN is already in place and all branch sites are connected successfully. BGP peering is up, routes are propagating as expected and end to end connectivity is stable. You have also completed the migration from on-premises to Azure including the older management virtual machines that were previously used for administrative access. With that groundwork done you now want to modernize remote access by introducing Azure Bastion. After all keeping Windows Server jump hosts just to reach other virtual machines no longer makes much sense when Bastion can provide secure browser based access without exposing workloads directly. But when you kick off the Azure Bastion deployment it does not complete. Instead the deployment fails and an error is shown:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*zkIXYxbBoSuRiU5Wjhc_-w.png" /></figure><h4>Why do I get this error message?</h4><p>When we look into the following diagram we see the Azure Virtual WAN architecture. This service acts as a global networking layer that connects multiple virtual networks through a centralized hub. At the center of the architecture there is a VWAN Hub which functions as the main routing and connectivity point for the environment. Traffic between all connected networks flows through this hub, enabling centralized routing, connectivity, and network management. The dashed lines between the hub and the spokes represent the connections from each virtual network to the VWAN hub. This hub and spoke model ensures that communication between the networks is centrally managed and routed through the hub.</p><p>However this architecture introduces a challenge when Azure Bastion is used together with Azure Virtual WAN. Azure Bastion requires direct outbound connectivity to the public internet in order to operate correctly. In a Virtual WAN topology network traffic is typically routed through the Virtual Hub. Because the Bastion subnet has a default route of 0.0.0.0/0, its outbound traffic is also routed through the Virtual Hub instead of going directly to the internet. As a result Azure Bastion cannot meet its requirement for direct internet connectivity, which leads to compatibility issues and can cause the Bastion deployment to fail.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KYOTeIj84Ayiw-A2XqxaQA.gif" /></figure><p>This is exactly the effect shown in the diagram above. To demonstrate this behavior, an Azure Virtual Machine was deployed in the Azure Bastion VNet in order to inspect the effective routes on the Network Interface Card. By reviewing the effective routes on the NIC, it becomes clear how the routing is handled in the Virtual WAN topology and how the default route influences the path that outbound traffic follows. This helps illustrate why traffic from the Bastion subnet is routed through the Virtual Hub instead of going directly to the public internet.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bKFyjFTHBAuPg1I5U8PNWg.png" /></figure><p>But why does this happen? The behavior originates from the Propagate Default Route setting within the Virtual WAN Virtual Network Connection towards the Azure Bastion VNet. When this setting is enabled, the Virtual WAN hub propagates the default route 0.0.0.0/0 to the connected virtual networks. This means that all outbound traffic that does not match a more specific route is automatically sent to the Virtual Hub. Because of this behavior, traffic from the Azure Bastion VNet would be routed through Azure Virtual WAN instead of going directly to the public internet. Since Azure Bastion requires direct outbound connectivity to the internet, this routing behavior causes a problem. To solve this, the Propagate Default Route setting was disabled on the Azure Bastion VNet connection. This ensures that the 0.0.0.0/0 route is not learned from the Virtual WAN hub, allowing outbound traffic from the Azure Bastion VNet to break out directly to the internet.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/931/1*FCDoJD8yZHci2i7XYZSkXA.png" /></figure><p>After applying this change we can verify the behavior again on the test virtual machine. When checking the effective routes on the network interface card we can now see that the 0.0.0.0/0 route forwards to the Internet service tag.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/697/1*mT82r5KRAtITIsDqmhSmgA.png" /></figure><p>When deploying Azure Bastion again, our deployment succeeds! We can now succesfully use Azure Bastion within our Azure vWAN setup! 😍</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mXzU6UEylt8VZKwHPuLpDA.png" /></figure><p>From here you now know how to integrate Azure Bastion within an Azure Virtual WAN setup. This approach ensures that Bastion keeps the required direct internet connectivity while the rest of the environment continues to benefit from the centralized connectivity provided by Azure Virtual WAN. One of the advantages of this solution is the operational simplicity. It allows administrators to access virtual machines directly through the Azure Portal instead of having to deploy and manage separate jumpbox virtual machines. This reduces management overhead while still providing a secure and convenient way to connect to workloads inside the environment. Feel free to clap for this story. Also, let me know if you have any feedback. I look forward to our next session. That’s all for today, until then, take care! ❤️</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2d4e61712dc6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoftazure/integrating-azure-bastion-in-azure-virtual-wan-setup-2d4e61712dc6">Integrating Azure Bastion in Azure Virtual WAN setup</a> was originally published in <a href="https://medium.com/microsoftazure">Microsoft Azure</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Agentic AI development for Power BI Semantic Models using GitHub Copilot and Power BI Modeling MCP…]]></title>
            <link>https://medium.com/microsoftazure/agentic-development-for-power-bi-semantic-models-using-github-copilot-and-power-bi-modeling-mcp-0d1ec2efc6c4?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/0d1ec2efc6c4</guid>
            <category><![CDATA[microsoft-fabric]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <category><![CDATA[power-bi]]></category>
            <category><![CDATA[semantic-model]]></category>
            <dc:creator><![CDATA[Inderjit Rana]]></dc:creator>
            <pubDate>Tue, 24 Mar 2026 18:04:37 GMT</pubDate>
            <atom:updated>2026-03-09T13:52:00.525Z</atom:updated>
            <content:encoded><![CDATA[<h3>Agentic AI development for Power BI Semantic Models using GitHub Copilot and Power BI Modeling MCP Server</h3><p>Power BI Copilot has already changed how we build reports. Natural language prompts now accelerate visual creation, summarization, and exploration. But semantic models — the backbone of analytics — remain largely manual, technical, and dependent on deep modeling expertise. This creates a bottleneck where report creation accelerates, but model development does not. In this post, I walk through an <strong>agentic development approach for Power BI semantic models</strong> using <strong>GitHub Copilot</strong> with <strong>Power BI Modeling MCP Server </strong>and show how AI can meaningfully participate in semantic model creation — without removing the human from the loop.</p><p>The diagram below illustrates the high‑level components and flow involved in developing Power BI semantic models using the Power BI Modeling MCP Server. This blog focuses on explaining the core concepts and architecture rather than providing step‑by‑step instructions. For a complete end‑to‑end walkthrough, please refer to the full demo available on YouTube — <a href="https://youtu.be/EKOG86ynOn0">https://youtu.be/EKOG86ynOn0</a></p><figure><img alt="Visual Studio Code + Power BI Modeling MCP Server + LLM" src="https://cdn-images-1.medium.com/max/1024/1*EIRJxnEFHIur2ZRIQhaSPQ.png" /><figcaption>Visual Studio Code + Power BI Modeling MCP Server + LLM</figcaption></figure><p>If you’d like to try this yourself using the same datasets shown in the demo, you’ll need to set up the <a href="https://github.com/isinghrana/fabric-samples-healthcare/tree/main/analytics-bi-directlake-starschema">Fabric CMS Medicare Part D sample from the GitHub repository</a> and have access to VS Code, GitHub Copilot, and the Power BI Modeling MCP Server.</p><h4><strong>Inspiration: Agentic AI for Power BI Development</strong></h4><p>The key enabler for this work is the <a href="https://github.com/microsoft/powerbi-modeling-mcp"><strong>Power BI Modeling MCP Server</strong></a>, exposed as a Visual Studio Code extension along with<strong> GitHub Copilot Agent mode</strong>. This extension allows semantic model operations to be executed through a MCP (Model Context Protocol), making them accessible to AI agents like GitHub Copilot.</p><p>The approach was heavily inspired by <a href="https://github.com/RuiRomano/pbip-demo-agentic-mcp"><strong>Rui Romano’s GitHub repository</strong></a>, which demonstrates <strong>fully agentic Power BI development</strong> — from semantic models to reports — using GitHub Copilot. That work proved the concept was possible. My focus here was narrower and more pragmatic: <strong>semantic model generation only</strong>. Semantic models are where business meaning, relationships, and measures are defined. If we want AI‑accelerated analytics to scale, <strong>semantic modeling must evolve beyond purely manual craftsmanship</strong>.</p><p>This experiment explored a simple question:</p><p><em>Can an AI agent, given the right context and tools, build a Power BI semantic model comparable to one created manually to accelerate development velocity?</em></p><h4><strong>Microsoft Fabric CMS Part D sample solution as the Playground</strong></h4><p>The experiment builds on an end‑to‑end Microsoft Fabric analytics solution maintained by <a href="https://www.linkedin.com/in/gregbeaumont/"><strong>Greg Beaumont</strong></a><strong> and I</strong>, which uses <strong>real CMS Medicare Part D dataset</strong>.</p><p>The solution includes:</p><ul><li>Data ingestion from the CMS website using <strong>Fabric Spark notebooks</strong></li><li>Storage in a <strong>Fabric Lakehouse</strong></li><li>Transformations via Spark Notebooks orchestrated using <strong>Fabric pipelines</strong></li><li>Consumption through <strong>Fabric data agents, Power BI Semantic Model and Power BI Reports</strong></li></ul><p>The architecture supports both <strong>manual</strong> and <strong>automated</strong> setup paths, highly recommended checking out the repository if not already familiar with it — <a href="https://github.com/isinghrana/fabric-samples-healthcare/tree/main/analytics-bi-directlake-starschema">fabric-samples-healthcare/analytics-bi-directlake-starschema at main · isinghrana/fabric-samples-healthcare</a></p><p>Screenshot of the Semantic Model created manually as part of the sample in the GitHub Repo</p><figure><img alt="Semantic Model — Manually Created" src="https://cdn-images-1.medium.com/max/1024/1*BdwBeMYRaeTxCsD9VwNzLA.jpeg" /><figcaption><strong>Manually Created Semantic Model</strong></figcaption></figure><h4>Agentic Development of Power BI Semantic Model for CMS Medicare Sample</h4><blockquote><strong>Crawl, Walk, Run: Scoping the Experiment</strong></blockquote><p>Early attempts to have an agent generate a semantic model <em>from scratch</em> ran into some challenge so I changed tactics:</p><ol><li><strong>Create a minimal baseline semantic model</strong> manually in the Fabric web interface</li><li>Switch to <strong>Visual Studio Code</strong></li><li><strong>Let GitHub Copilot, via the Power BI Modeling MCP Server, enhance the model using Agentic AI</strong></li></ol><blockquote><strong>Establishing the Baseline</strong></blockquote><p>Creation of baseline semantic model:</p><ul><li>Opened the Fabric Lakehouse using Fabric Web Interface</li><li>Create a new Semantic Model with core CMS fact and dimension tables</li></ul><p>The goal was not novelty — it was <strong>parity</strong>. The agent’s task was to take something basic and evolve it toward a usable Semantic Model for report creatin using Power BI Copilot.</p><blockquote><strong>VS Code + MCP Server: Enabling Agentic Development</strong></blockquote><p>With Visual Studio Code GitHub Copilot was used as the agent interface and <strong>Power BI Modeling MCP Server extension</strong> available as a tool (ensured it was started) executed the following two steps:</p><ol><li>Connect GitHub Copilot Agent to Fabric Workspace and Semantic Model using simple prompt — “<strong>Connect to semantic model ‘&lt;semantic-model-name&gt;’ in Fabric Workspace ‘&lt;fabric-workspace-name&gt;</strong>’”</li><li>Next GitHub Copilot prompt to start the semantic build out work — “<strong>Please us the instructions from `.\Semantic_Model_Implementation_Guidance.md` to build out a production ready semantic model which can be easily used to generate reports</strong>”.</li></ol><p>Prompt Text File available on GitHub <a href="https://github.com/isinghrana/fabric-samples-healthcare/blob/main/analytics-bi-directlake-starschema/scripts/pbi-agenticdev/prompt.txt">here</a> and Semantic Model Implementation Guidance markdown file available <a href="https://github.com/isinghrana/fabric-samples-healthcare/blob/main/analytics-bi-directlake-starschema/scripts/pbi-agenticdev/Semantic_Model_Implementation_Guidance.md">here</a></p><p>A few notes on the implementation guidance file:</p><ul><li>Framed strong <strong>business context first</strong> — clear analytical objectives, explicit business questions, and grounding in official CMS Medicare Part D documentation — gave the agent intent rather than just tasks.</li><li><strong>Clear objectives and questions</strong> were more important than verbose instructions, enabling the model to reason correctly about outcomes.</li><li>Technical guidance like give business user-friendly names for table and column names, data type formatting, hide technical columns like Surrogate Keys.</li><li>Couple notes in the Critical Section of guidance file were based on iterative attempts where failures were encountered, example newly created semantic model was not usable with “CalculationNeeded” error message so instead of having the model created in a bad state and then ask GitHub Copilot to fix it an explicit instruction was added so that GitHub Copilot creates Semantic Model in a usable state to begin with</li><li>A simple mandate to <strong>document every step in a log file with details on the step executed by agent (observed other patterns where planning step documents and get the details</strong></li></ul><h4><strong>Results: Surprisingly Close to Manual</strong></h4><p>The resulting AI generated semantic model was very similar to the manually created one.</p><ul><li>Contained sensible relationships, semantic tables and columns were given business user-friendly names</li><li>Included usable, well‑structured DAX measures</li><li>Usable for Report creation using Power BI Copilot</li></ul><figure><img alt="Semantic Model — AI Generated" src="https://cdn-images-1.medium.com/max/1024/1*H1OpFJTBBKIBmeMAqTU02Q.jpeg" /><figcaption><strong>AI Generated Semantic Model</strong></figcaption></figure><p>Resources:</p><ul><li>End to End <a href="https://youtu.be/EKOG86ynOn0">YouTube Video</a> for the Demo</li><li><a href="https://github.com/microsoft/powerbi-modeling-mcp">Power BI Modeling MCP Server</a></li><li><a href="https://github.com/RuiRomano/pbip-demo-agentic-mcp">Rui Romano Agentic PBI Development GitHub Repo</a></li><li><a href="https://github.com/isinghrana/fabric-samples-healthcare/tree/main/analytics-bi-directlake-starschema">Microsoft Fabric End-to-End Analytics Sample using CMS Medicare Part D Dataset</a></li></ul><p><strong>Related Reading</strong></p><p>As we move into a new era where AI is accelerating our day‑to‑day work, we’re seeing many innovative ways to apply it in practice. If using MCP with Visual Studio Code feels too much like traditional coding and isn’t of your, my colleague Greg Beaumont offers a great alternative. In his article (with a companion video), Greg shows how M365 Copilot can assess an existing Power BI semantic model and recommend targeted optimizations. The result is an AI‑generated set of actionable recommendations that Power BI developers can use to improve their semantic models faster and more efficiently. Read more here — <a href="https://gregbeaumont.com/2026/03/08/use-m365-copilot-to-improve-power-bi-semantic-models-power-query-and-report-speed/"><strong>Use M365 Copilot to improve Power BI semantic models, power query, and report speed</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0d1ec2efc6c4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoftazure/agentic-development-for-power-bi-semantic-models-using-github-copilot-and-power-bi-modeling-mcp-0d1ec2efc6c4">Agentic AI development for Power BI Semantic Models using GitHub Copilot and Power BI Modeling MCP…</a> was originally published in <a href="https://medium.com/microsoftazure">Microsoft Azure</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Managing Feature Flags and Dynamic Configuration in .NET Web App with Azure App Configuration]]></title>
            <link>https://medium.com/microsoftazure/managing-feature-flags-and-dynamic-configuration-in-net-web-app-with-azure-app-configuration-c85ef783ae3b?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/c85ef783ae3b</guid>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[azure-app-configuration]]></category>
            <category><![CDATA[azure]]></category>
            <dc:creator><![CDATA[Sai Nitesh Palamakula]]></dc:creator>
            <pubDate>Tue, 24 Mar 2026 18:04:34 GMT</pubDate>
            <atom:updated>2026-01-18T01:36:40.120Z</atom:updated>
            <content:encoded><![CDATA[<h3>Managing Feature Flags and Dynamic Configuration in .NET Web App with Azure App Configuration</h3><p>Have you been curious about feature rollouts — how do you enable features for specific users or toggle something off quickly without redeploying? Recently, I built a demo API to explore this concept using Azure App Configuration. The idea was simple: control features and manage user access dynamically, all without touching code or restarting services.</p><p>In this article, I’ll walk you through implementing dynamic configuration in a .NET API using Azure App Configuration, IOptionsSnapshot, and IFeatureManager</p><p><strong>The Problem</strong></p><p>Let’s say you’re building an API and need to:</p><p>· Enable a new feature for beta users only</p><p>·Quickly disable a feature that’s causing errors</p><p>· Manage which users can access certain functionality</p><p>· Make these changes instantly without redeployment</p><p>The traditional approach? Update appsettings.json, push to GitHub, wait for CI/CD pipelines, and deploy. But what if a feature breaks at midnight and you need to turn it off immediately?</p><p><strong>Why Azure App Configuration?</strong></p><p>Azure App Configuration is a managed service for storing application settings and feature flags centrally. The best part? Your app can pull updated values at runtime without restarting. Think of it as a remote control for your application’s behavior.</p><p><strong>Understanding IFeatureManager vs IOptionsSnapshot</strong></p><p>Before we dive into code, let me explain these two patterns because they solve different problems:</p><p><strong>IFeatureManager — Feature Flags (Boolean Toggles)</strong></p><p><strong>What it does:</strong> Controls whether a feature is ON or OFF.</p><p><strong>Use it when:</strong></p><p>· You need a simple yes/no decision</p><p>· Toggling entire features on/off</p><p>· A/B testing scenarios</p><p>· Emergency feature kill switches</p><p><strong>Example use case:</strong> “Should we show the new checkout flow?”</p><pre>var isEnabled = await _featureManager.IsEnabledAsync(&quot;ApplyDiscount&quot;);<br><br>if (isEnabled)<br>{<br>    // Execute feature logic<br>}</pre><p><strong>IOptionsSnapshot — Configuration Values (Complex Data)</strong></p><p><strong>What it does: </strong>Provides structured configuration data (strings, numbers, lists, objects).</p><p><strong>Use it when:</strong></p><p>· You need actual values, not just toggles</p><p>· Managing lists (allowed users, product IDs)</p><p>· Configuration thresholds or limits</p><p>· Structured settings that change frequently</p><p><strong>Example use case:</strong> “Which users are allowed to access this feature?”</p><pre>var allowedUsers = _optionsSnapshot.Value.AllowedUserIds;<br>if (allowedUsers.Contains(userId))<br>{<br>    // Grant access<br>}</pre><p><strong>Real-World Example</strong></p><p>Let’s say you have a discount feature. Here’s how you’d use both together:</p><pre>// Step 1: Check if discount feature is enabled (IFeatureManager)<br>var isDiscountEnabled = await _featureManager.IsEnabledAsync(&quot;ApplyDiscount&quot;);<br><br>if (isDiscountEnabled)<br>{<br>    // Step 2: Get the discount configuration (IOptionsSnapshot)<br>    var discountPercentage = _optionsSnapshot.Value.Percentage;<br>    var allowedUsers = _optionsSnapshot.Value.AllowedUserIds;<br>    <br>    // Step 3: Apply business logic<br>    if (allowedUsers.Contains(userId))<br>    {<br>        price = price * (1 - discountPercentage);<br>    }<br>}</pre><p><strong>IFeatureManager</strong> answers: “Is the discount feature turned on?”</p><p><strong>IOptionsSnapshot</strong> answers: “What’s the discount percentage and who’s eligible?”</p><p>This separation is powerful because you can:</p><p>· Toggle features on/off instantly without changing business logic</p><p>· Update configuration values (like discount percentage) without touching feature flags</p><p>· Combine both for granular control</p><p>Now let’s see how to implement this in a real API.</p><p><strong>Prerequisites</strong></p><p>Before we start:</p><p>· .NET 8.0 SDK</p><p>· Azure subscription (free tier is enough)</p><p>· Basic knowledge of ASP.NET Core</p><p><strong>Project Setup</strong></p><p><strong>Create Azure App Configuration Resource on Azure</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K5GFkL8eusFFgXQKIYj_iA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KARc2nVqMRqHNwDfeNjPXw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*h49q2n9s-InhhHA65zveww.png" /></figure><p>Capture the Connection String from the Azure portal:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/930/1*xETJm_bbxTqGEWxK-YuacQ.png" /></figure><p>Note: The code snippets added below can be referenced from my <a href="https://github.com/sainiteshGit/dotnet-demos/tree/main/TestAppConfig">GitHub repo</a></p><p>Create a new Web API project:</p><pre>dotnet new webapi -n TestAppConfig<br>cd TestAppConfig</pre><p>Install the required packages:</p><pre>dotnet add package Microsoft.Azure.AppConfiguration.AspNetCore<br>dotnet add package Microsoft.FeatureManagement.AspNetCore</pre><p>Local Configuration files:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IU_mdqXllMJ4aZg-zGUkeg.png" /></figure><p>Notice two sections:</p><ul><li>FeatureManagement — for feature flags (IFeatureManager)</li><li>DiscountSettings — for configuration values (IOptionsSnapshot)</li></ul><p><strong>Creating the Configuration Model</strong></p><p>First, let’s define a model for our settings. I’m keeping it simple with two lists — allowed users and products:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DTfKmAgXKshO2d_i5qxAxQ.png" /></figure><p>Here’s where it gets interesting. Open Program.cs and add the Azure connection:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2hFMpHOfwYcFYmIKVGmxIw.png" /></figure><p>Let me break down what’s happening here:</p><p><strong>Connection Setup</strong>: We check if an Azure connection string exists before attempting to use it. This way, the app works locally without Azure too.</p><p><strong>Refresh Strategy</strong>: The RegisterAll() method tells Azure to monitor all configuration keys. We set a 5-second refresh interval, meaning the app checks for updates every 5 seconds.</p><p><strong>Feature Management</strong>: AddFeatureManagement() registers the feature flag system, making IFeatureManager available for dependency injection.</p><p><strong>Options Pattern</strong>: Configure&lt;DiscountSettings&gt; binds our configuration section to the strongly-typed model, enabling IOptionsSnapshot&lt;DiscountSettings&gt;.</p><p><strong>Middleware</strong>: app.UseAzureAppConfiguration() is crucial — it enables automatic configuration refresh on incoming requests.</p><p><strong>Building the Controller</strong></p><p>Let’s create an endpoint that demonstrates both patterns:</p><p>This controller shows both patterns in action:</p><p>debug-config — Shows current feature flag state and configuration values</p><h4>Adding Feature Flags (IFeatureManager)</h4><p>In the Azure Portal:</p><ol><li>Navigate to your App Configuration resource</li><li>Open <strong>Feature Manager</strong> (this is specifically for IFeatureManager)</li><li>Click <strong>Create</strong></li><li>Enter name: ApplyDiscount</li><li>Toggle it ON or OFF as needed</li></ol><p><strong>Important:</strong> Feature flags go in Feature Manager, not Configuration Explorer. This is the section that feeds IFeatureManager.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2pAJfL8RvHz2PZ2tDBuJFA.png" /></figure><h4>Adding Configuration Values (IOptionsSnapshot)</h4><p>Go to <strong>Configuration Explorer</strong> (this is for IOptionsSnapshot data):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*t03kwdCTn_EV9YO-ziqJFw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*a9-pSEKidWjg36wlCXxpSw.png" /></figure><p><strong>The Content Type Detail</strong></p><p>Here’s something that wasn’t obvious from the docs — content type matters a lot for IOptionsSnapshot.</p><p><strong>When you set content type to application/json:</strong></p><p>· Azure parses your JSON value</p><p>· It creates hierarchical configuration keys internally</p><p>· IOptionsSnapshot can properly bind these to List&lt;string&gt;</p><p><strong>Without application/json:</strong></p><p>· Azure stores your value as a plain string:</p><p>· IOptionsSnapshot receives the literal text “[“user15”,”user16&quot;]”</p><p>· It can’t convert this string to a list automatically</p><p>· Your app falls back to local appsettings.json values</p><p>This detail cost me about 15 mins of debugging. I kept wondering why my Azure values weren’t showing up in IOptionsSnapshot, and it turned out to be just the missing content type setting.</p><p>Note: Feature flags (IFeatureManager) don’t need content type because they’re always booleans.</p><p>Make sure to build and run the project:</p><blockquote>dotnet build</blockquote><blockquote>dotnet run</blockquote><p><strong>Testing Without Any Values configured in Azure App Config:</strong></p><blockquote>curl <a href="http://localhost:5054/api/products/debug-config">http://localhost:5054/api/products/debug-config</a></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zDt01yj-8IgsacnugNs3Ag.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vZEK2AYold-x7cg-LFXg0w.png" /></figure><p>It picks from the local configuration file</p><h4>Testing the Hot Reload</h4><blockquote>curl <a href="http://localhost:5054/api/products/debug-config">http://localhost:5054/api/products/debug-config</a></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CMMMIUP9NMWl791iqdiF8w.png" /></figure><p>It picks from the Azure App Config Resource</p><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*t03kwdCTn_EV9YO-ziqJFw.png" /></figure><p>This shows how IFeatureManager and IOptionsSnapshot work together!</p><h4>Why IOptionsSnapshot is Request-Scoped</h4><p>One important detail: IOptionsSnapshot is <strong>request-scoped</strong>, meaning it gets fresh configuration values on each HTTP request.</p><p>Other options patterns:</p><ul><li><strong>IOptions</strong> — Singleton, never reloads (not useful for hot reload)</li><li><strong>IOptionsMonitor</strong> — Singleton, reloads but same instance across all requests</li><li><strong>IOptionsSnapshot</strong> — Scoped per request, perfect for hot reload in APIs</li></ul><p>That’s why we use IOptionsSnapshot for this scenario — it automatically picks up refreshed values on each request.</p><h3>Final Thoughts</h3><p>Azure App Configuration with IOptionsSnapshot and IFeatureManager gives you real-time control over your application’s behavior. Understanding when to use each pattern is key:</p><ul><li><strong>IFeatureManager</strong> — Boolean toggles (is feature on/off?)</li><li><strong>IOptionsSnapshot</strong> — Configuration data (what are the values?)</li></ul><p>The key points to remember:</p><p>Use RegisterAll() with SetRefreshInterval for automatic updates</p><ul><li>Always set content type to application/json for arrays and objects in IOptionsSnapshot</li><li>IOptionsSnapshot is request-scoped and perfect for hot reload</li><li>The middleware (UseAzureAppConfiguration) is what makes refresh work</li><li>Feature flags go in Feature Manager, configuration goes in Configuration Explorer</li></ul><p>This approach has made my demo API much more flexible. No more redeployments just to change a configuration value or toggle a feature. Hope this helps you implement something similar!</p><p>References:</p><ul><li><a href="https://github.com/sainiteshGit/dotnet-demos/tree/main/TestAppConfig">dotnet-demos/TestAppConfig at main · sainiteshGit/dotnet-demos</a></li><li><a href="https://learn.microsoft.com/en-us/azure/azure-app-configuration/quickstart-feature-flag-aspnet-core">Quickstart for adding feature flags to ASP.NET Core apps - Azure App Configuration</a></li><li><a href="https://learn.microsoft.com/en-us/azure/azure-app-configuration/overview">What is Azure App Configuration?</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c85ef783ae3b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoftazure/managing-feature-flags-and-dynamic-configuration-in-net-web-app-with-azure-app-configuration-c85ef783ae3b">Managing Feature Flags and Dynamic Configuration in .NET Web App with Azure App Configuration</a> was originally published in <a href="https://medium.com/microsoftazure">Microsoft Azure</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Chat History Providers in Microsoft Agent Framework — Making Agents Remember]]></title>
            <link>https://medium.com/microsoftazure/chat-history-providers-in-microsoft-agent-framework-making-agents-remember-f99476c88d3f?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/f99476c88d3f</guid>
            <category><![CDATA[database]]></category>
            <category><![CDATA[azure]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Sai Nitesh Palamakula]]></dc:creator>
            <pubDate>Tue, 24 Mar 2026 18:04:32 GMT</pubDate>
            <atom:updated>2026-02-01T07:54:50.569Z</atom:updated>
            <content:encoded><![CDATA[<h3>Chat History Providers in Microsoft Agent Framework — Making Agents Remember</h3><p>Been digging into the Microsoft Agent Framework lately, and I came across this feature that’s pretty fundamental for production agents: <strong>ChatHistoryProvider</strong>.</p><p>If you’re building anything beyond a quick prototype, you’ll probably need this.</p><h4>The Default Behavior (And Why It’s a Problem):</h4><p>So, here’s what happens out of the box — agents store conversation history in memory. Which is fine for testing. But the second your container recycles or your app restarts? Gone. All of it.</p><p>Think about a support bot that takes an order number, then ten minutes later has no idea what you were talking about. Or a multi-step workflow that can’t survive a deployment. That’s what you get with in-memory storage.</p><p>The framework solves this with ChatHistoryProvider — basically a pluggable backend for where conversations get saved.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vulKs_LrgV7ODlmxm1-K9Q.png" /></figure><h4>What’s Available?</h4><p>A few options ship with the framework:</p><p>· In-memory — the default, works for dev</p><p>· CosmosChatHistoryProvider — what I’m using</p><p>· Custom implementations — if you need something specific</p><p>I went with Cosmos DB because I wanted to explore the integration with cosmos database and is less code to maintain.</p><h4>Setting It Up:</h4><p>You will need Azure OpenAI and Azure CosmosDB resource created. Follow instructions here to create cosmos and Azure OpenAI</p><p><strong>Cosmos:</strong> <a href="https://learn.microsoft.com/en-us/azure/cosmos-db/quickstart-portal">https://learn.microsoft.com/en-us/azure/cosmos-db/quickstart-portal</a></p><p><strong>Azure OpenAI</strong>: <a href="https://learn.microsoft.com/en-us/microsoft-cloud/dev/tutorials/openai-acs-msgraph/02-openai-create-resource">https://learn.microsoft.com/en-us/microsoft-cloud/dev/tutorials/openai-acs-msgraph/02-openai-create-resource</a></p><p>Include the following packages in your .NET project:</p><p>Please refere this <a href="https://github.com/sainiteshGit/sample-ai-project/tree/master/msft-agent-framework-integrations/ChatHistoryProviderSample">GitHub repo</a> for the full code for below project</p><pre>&lt;PackageReference Include=&quot;Microsoft.Agents.AI&quot; Version=&quot;1.0.0-preview.260128.1&quot; /&gt;<br>&lt;PackageReference Include=&quot;Microsoft.Agents.AI.CosmosNoSql&quot; Version=&quot;1.0.0-preview.260128.1&quot; /&gt;<br>&lt;PackageReference Include=&quot;Microsoft.Extensions.AI.OpenAI&quot; Version=&quot;9.5.0-preview.1.25265.7&quot; /&gt;<br>&lt;PackageReference Include=&quot;Azure.AI.OpenAI&quot; Version=&quot;2.2.0-beta.1&quot; /&gt;</pre><p>The ChatHistoryProviderFactory is a delegate. Framework calls it when it needs a provider instance. Flexible pattern — you could route different users to different backends.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hO1tE7U9ezgFddT9yUepvA.png" /></figure><p><strong>Running the agent:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/633/1*ZbZ6IOXlxlQVSKN3mNSQsQ.png" /></figure><p>Messages get persisted automatically after that.</p><h4>Session Serialization</h4><p>This part is useful. You can serialize sessions:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/626/1*u-n2gn4meNAr9oJbF1FEhQ.png" /></figure><h4>Auth Options</h4><p>Connection string works for local dev</p><p>Managed identity for production</p><h4>Things to Watch Out For</h4><p>Partition key — Has to be /conversationId. The provider expects that exact path.</p><p>Resources don’t auto-create — If the database or container doesn’t exist, you get a 404. Create them first.</p><p>Preview packages — These are still preview, so APIs might shift between versions.</p><p>The above provided snippets is available in my <a href="https://github.com/sainiteshGit/sample-ai-project/tree/master/msft-agent-framework-integrations/ChatHistoryProviderSample">GitHub repo</a></p><p><strong>Running the Application:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*z6vd8vbVTyHFCw-CLNV0ZA.png" /></figure><h4>State in Cosmos Database:</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1006/1*2ylnEaQ6Eahtr8CkCiPiRg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/844/1*IjPKfSa9A9XW32B2OTJCUw.png" /></figure><h4>When Does This Make Sense</h4><p>· Multi-turn conversations where context matters</p><p>· Distributed deployments with multiple instances</p><p>· Anything that might restart or get recycled</p><p>· You need audit logs of conversations</p><p><strong>References</strong>:</p><ul><li><a href="https://learn.microsoft.com/en-us/azure/cosmos-db/gen-ai/azure-agent-service">Integration with Azure AI Agent Service - Azure Cosmos DB for NoSQL</a></li><li><a href="https://learn.microsoft.com/en-us/agent-framework/integrations/overview?pivots=programming-language-csharp">Agent Framework Integrations</a></li><li><a href="https://learn.microsoft.com/en-us/azure/cosmos-db/quickstart-portal">Quickstart - Azure portal - Azure Cosmos DB</a></li><li><a href="https://github.com/sainiteshGit/sample-ai-project/tree/master/msft-agent-framework-integrations/ChatHistoryProviderSample">sample-ai-project/msft-agent-framework-integrations/ChatHistoryProviderSample at master · sainiteshGit/sample-ai-project</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f99476c88d3f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoftazure/chat-history-providers-in-microsoft-agent-framework-making-agents-remember-f99476c88d3f">Chat History Providers in Microsoft Agent Framework — Making Agents Remember</a> was originally published in <a href="https://medium.com/microsoftazure">Microsoft Azure</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>