<?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 - 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/microsoft?source=rss----8bec1183ada9---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Microsoft - Medium</title>
            <link>https://medium.com/microsoft?source=rss----8bec1183ada9---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 17 Oct 2026 23:43:32 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/microsoft" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Explore deeper connections with unbounded variable-length paths in Microsoft Fabric Graph]]></title>
            <link>https://medium.com/microsoft/explore-deeper-connections-with-unbounded-variable-length-paths-in-microsoft-fabric-graph-c0e3e120e3e4?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/c0e3e120e3e4</guid>
            <category><![CDATA[microsoft-fabric]]></category>
            <dc:creator><![CDATA[Tushar Goyal]]></dc:creator>
            <pubDate>Wed, 14 Oct 2026 19:01:23 GMT</pubDate>
            <atom:updated>2026-10-14T19:01:22.337Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GDXHusIq_92ZdbPm0eGS-g.png" /></figure><p><a href="https://www.linkedin.com/in/justinpfine/">Justin Fine</a>, <a href="https://www.linkedin.com/in/idrismotiwala/">Idris Motiwala</a>, <a href="https://www.linkedin.com/in/goyal-tushar/">Tushar Goyal</a></p><p><strong>Microsoft Fabric Graph removes the previous hop limit for variable-length traversals, allowing graph structure to determine path depth.</strong></p><p>Graph analysis is often about discovering how entities connect when the number of relationships between them isn’t known in advance. A message might be part of a reply chain that is three levels deep — or thirty. A component might depend on another component through an unpredictable number of intermediate services. An organizational hierarchy might vary significantly across teams.</p><p>Microsoft Fabric Graph can now query unbounded variable-length paths, enabling traversals of relationships without specifying a fixed maximum number of hops while also being able to specify very large numbers for the upper bound.</p><p>Previously, variable-length traversals supported a low number of maximum hops. That limit worked well for many scenarios, but it required developers to choose an upper boundary even when the structure of the data should determine the traversal depth. With this update, a path can continue beyond this limit until the query finds a matching destination or no valid continuation remains.</p><h3><strong>What is a graph traversal?</strong></h3><p>A graph represents entities as nodes and the relationships between them as edges. For example, a social graph might include people, messages, posts, and forums as nodes. Relationships such as replied to, belongs to, or moderates connect those nodes.</p><p>A traversal follows relationships through the graph. A single-hop traversal answers a direct question, such as which post a message replies to. A multi-hop traversal follows a chain, such as identifying the original post in a reply thread or the upstream system supplying a dataset.</p><p>These chains don’t always have predictable depth. Requiring every query to specify a maximum can produce incomplete results when the selected limit is lower than the depth of the underlying data.</p><h3><strong>From bounded traversals to data-driven traversals</strong></h3><p>Before this update, a variable-length path could traverse up to predefined number of relationships. Developers could query a range of path lengths, but every query remained subject to that maximum.</p><p>Unbounded variable-length paths remove the ceiling. Instead of deciding in advance how deep the query should search, users can express the relationship pattern they want to follow and allow the graph structure to determine the required depth.</p><p>This change applies to scenarios such as:</p><ul><li>Conversation analysis: Follow reply chains back to their originating post.</li><li>Data lineage: Trace upstream or downstream dependencies across complex pipelines.</li><li>Dependency management: Identify transitive software, service, or infrastructure dependencies.</li><li>Organizational analysis: Navigate reporting or ownership hierarchies of varying depth.</li><li>Knowledge graphs: Follow semantic relationships until a relevant entity is found.</li><li>Fraud and security investigations: Explore chains of related accounts, devices, events, or transactions.</li><li>Supply-chain analysis: Trace materials, suppliers, and distribution relationships across multiple tiers.</li></ul><p>Queries can express the intent of retrieving unbounded paths, but not the use of unlimited system responses. They continue to operate within applicable service protections, including execution time, capacity, memory, and result-size constraints.</p><h3><strong>Following an unbounded reply chain</strong></h3><p>Consider a social network graph containing messages, posts, forums, and people. A message can reply to another message, which can reply to another message, eventually reaching the post that began the conversation.</p><p>The following query starts with a specific message and follows the REPLY_OF relationship for as many steps as needed to reach a post. It then identifies the forum containing that post and returns the forum’s moderator.</p><p>In this query, starting with this message, keep following the reply chain until you reach the original post. Then return the forum that contains the post and the person who moderates it.</p><pre>:params { messageId: 206158431836 } <br> <br>MATCH <br> (message:Message {id: $messageId}) <br> -[:REPLY_OF]-&gt;* <br> (post:Post) <br> &lt;-[:CONTAINER_OF]- <br> (forum:Forum) <br> -[:HAS_MODERATOR]-&gt; <br> (moderator:Person) <br>RETURN <br> forum.id AS forumId, <br> forum.title AS forumTitle, <br> moderator.id AS moderatorId, <br> moderator.firstName AS moderatorFirstName, <br> moderator.lastName AS moderatorLastName</pre><p>The query contains four logical steps:</p><ol><li><strong>Find the starting message. </strong>(message:Message {id: $messageId}) identifies the message supplied through the query parameter.</li><li><strong>Follow the complete reply chain. </strong>-[:REPLY_OF]-&gt;* repeatedly follows outgoing REPLY_OF relationships. The traversal isn’t restricted to a limited number of hops, so deeply nested conversations can still reach their originating post.</li><li><strong>Find the containing forum. </strong>(post:Post)&lt;-[:CONTAINER_OF]-(forum:Forum) identifies the forum associated with the post.</li><li><strong>Return the forum moderator. </strong>(forum:Forum)-[:HAS_MODERATOR]-&gt;(moderator:Person) connects the forum to its moderator, whose identifying information is returned.</li></ol><h3><strong>Bounded paths still matter</strong></h3><p>Unbounded paths expand what graph queries can express, but they don’t replace bounded traversal.</p><pre>MATCH (message:Message {id: $messageId})-[:REPLY_OF]-&gt;{5,23}(reply:Message) RETURN reply</pre><p>A bounded path remains the better choice when the business question has a natural maximum. For example, an application looking for professional connections within three degrees should state that limit. A query evaluating only immediate and secondary dependencies should also use a bounded range.</p><p>Use a bounded path when:</p><ul><li>The maximum useful depth is known.</li><li>Connections beyond a certain depth aren’t relevant.</li><li>Predictable query cost or latency is important.</li><li>The graph is dense and each additional hop could produce many more candidate paths.</li></ul><p>Use an unbounded path when:</p><ul><li>The required depth is unknown.</li><li>The query must reach the end of a hierarchy or chain.</li><li>An arbitrary upper limit could omit valid results.</li><li>The data provides a natural termination point, such as a root node or destination label.</li></ul><p>The best path expression is the narrowest one that completely answers the business question.</p><h3><strong>Design efficient unbounded traversals</strong></h3><p>Removing a fixed hop ceiling makes query design even more important. The number of possible paths can grow quickly in a densely connected graph, particularly when nodes have many outgoing relationships, here are some recommendations:</p><ul><li><strong>Start with a selective node</strong></li></ul><p>Anchor the traversal to a specific entity whenever possible. In the example, the message ID provides a precise starting point and avoids scanning reply chains for every message.</p><ul><li><strong>Specify relationship and node labels</strong></li></ul><p>A traversal that names REPLY_OF, Post, and Forum is more targeted than one that follows any relationship to any node. Expressing the intended graph structure constrains the search and makes the query easier to understand.</p><ul><li><strong>Apply filters early</strong></li></ul><p>Place selective conditions as close as possible to the relevant node or relationship pattern. Early filtering reduces the number of candidate paths that later stages must process.</p><ul><li><strong>Return only the required data</strong></li></ul><p>Project the properties needed by the application instead of returning every node, edge, or property encountered during traversal. Smaller results are easier to process and transfer.</p><ul><li><strong>Account for cycles</strong></li></ul><p>Some graphs contain relationships that can lead back to previously visited entities. Model traversal patterns carefully and use supported path modes (ASYCLIC, TRAIL, WALK, etc) or predicates when the scenario requires protection against repeated nodes or edges.</p><ul><li><strong>Test with representative data</strong></li></ul><p>A query that performs well on a small development graph can behave differently when applied to a dense production graph. Test using realistic path depths, relationship density, and result sizes. Monitor execution behavior before incorporating an unbounded traversal into a production workload.</p><h3><strong>Next steps</strong></h3><p>Explore unbounded variable-length paths with a scenario in which relationship depth varies across your data. Evaluate the query with representative graph density and path lengths before using it in a production workload.</p><ul><li><a href="https://learn.microsoft.com/fabric/graph/overview">Graph in Microsoft Fabric overview</a></li><li><a href="https://learn.microsoft.com/fabric/graph/gql-language-guide">GQL language guide for graph in Microsoft Fabric</a></li><li><a href="https://learn.microsoft.com/fabric/graph/gql-query-performance">Optimize GQL query performance for graph in Microsoft Fabric</a></li></ul><p><strong>Tags: #</strong>Graph, Graph Query Language (#GQL), data relationships, graph traversal, #graphsareeverywhere</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c0e3e120e3e4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoft/explore-deeper-connections-with-unbounded-variable-length-paths-in-microsoft-fabric-graph-c0e3e120e3e4">Explore deeper connections with unbounded variable-length paths in Microsoft Fabric Graph</a> was originally published in <a href="https://medium.com/microsoft">Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[More expressive graph analysis: GQL improvements in Microsoft Fabric Graph]]></title>
            <link>https://medium.com/microsoft/more-expressive-graph-analysis-gql-improvements-in-microsoft-fabric-graph-f461671fa4ce?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/f461671fa4ce</guid>
            <category><![CDATA[microsoft-fabric]]></category>
            <dc:creator><![CDATA[Tushar Goyal]]></dc:creator>
            <pubDate>Wed, 14 Oct 2026 19:01:16 GMT</pubDate>
            <atom:updated>2026-10-14T19:01:15.224Z</atom:updated>
            <content:encoded><![CDATA[<p><a href="https://www.linkedin.com/in/justinpfine/">Justin Fine</a>, <a href="https://www.linkedin.com/in/idrismotiwala/">Idris Motiwala</a>, <a href="https://www.linkedin.com/in/goyal-tushar/">Tushar Goyal</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zJOh7C3aCa2wLjSa6nY9zA.png" /></figure><p><strong>January–August 2026 updates expand how users find, inspect, compose, and analyze connections.</strong></p><p>Graph data helps organizations understand connections: how data moves between systems, how services depend on one another, how conversations develop, and how people or organizations relate. Graph Query Language (GQL) provides a standardized way to ask those questions in Microsoft Fabric Graph.</p><p>From January through August 2026, the GQL feature set expanded across path finding, traversal control, query composition, aggregation, and data handling. The result is broader analytical coverage for business users and more precise query tools for developers. This post explains each improvement and includes the associated syntax.</p><h3><strong>Find and control paths</strong></h3><h4><strong>Shortest paths with ANY SHORTEST</strong></h4><p>When several routes connect two entities, many applications need one shortest route rather than every possible route. ANY SHORTEST makes that intent explicit. This is useful for dependency analysis, recommendations, network routing, and investigations where fewer intermediate steps are preferred.</p><pre>MATCH ANY SHORTEST ({id: 1})-&gt;{,2}(d) <br>RETURN d.id AS dst</pre><h4><strong>Quantified edge patterns</strong></h4><p>Quantified edge patterns repeat a complete relationship pattern, including conditions on intermediate entities. In the following example, the repeated pattern requires the source person at each step to use Chrome. This gives developers more control than repeating an edge alone.</p><pre>MATCH p=(a:Person {id: 987})((x)-[k:knows]-&gt;() WHERE x.browserUsed = &#39;Chrome&#39;){2}(b:Person) <br>FOR n IN NODES(p) WITH OFFSET off <br>RETURN n.browserUsed <br>ORDER BY a.id, b.id, off <br>LIMIT 12</pre><h4><strong>Complete path modes</strong></h4><p>Path modes define whether a traversal can revisit nodes or edges.</p><ul><li>WALK permits repetition.</li><li>TRAIL prevents repeated edges.</li><li>SIMPLE prevents repeated interior nodes.</li><li>ACYCLIC prevents any repeated node.</li><li>DIFFERENT EDGES prevents one edge from satisfying more than one edge variable in the match.</li></ul><p>These choices help query results reflect the meaning of a route, hierarchy, or dependency chain.</p><pre>MATCH WALK (:Person {firstName: &quot;Juliana&quot;})-[:studyAt]-&gt;(:University)&lt;-[:studyAt]-(p:Person) <br>RETURN p.firstName AS name</pre><pre>MATCH TRAIL (:Person {firstName: &quot;Juliana&quot;})-[:studyAt]-&gt;(:University)&lt;-[:studyAt]-(p:Person) <br>RETURN p.firstName AS name</pre><pre>MATCH SIMPLE (x)-&gt;{2}(y) <br>RETURN COUNT(*) AS path_count</pre><pre>MATCH ACYCLIC (x:`node` {id: 1})-&gt;(y)-&gt;(z) <br>RETURN x.id, y.id, z.id <br>ORDER BY x.id, y.id, z.id</pre><pre>MATCH DIFFERENT EDGES (p:Person {name: &#39;Keanu Reeves&#39;})-[e:ACTED_IN]-&gt;(m:Movie) <br>RETURN m.title AS movie</pre><h4><strong>Unbounded variable-length path patterns</strong></h4><p>Variable-length paths previously had a limited maximum hop. Unbounded quantifiers allow the graph structure to determine depth when a chain has no meaningful fixed limit. The example follows one or more relationships while ACYCLIC prevents a node from being visited twice. Unbounded describes the path expression, not unlimited compute; selective starting points and representative performance testing remain important.</p><pre>MATCH ACYCLIC ()-[]-&gt;{1,}() <br>RETURN COUNT(*) AS total</pre><h3><strong>Inspect paths and graph elements</strong></h3><h4><strong>NODES, EDGES, and INNER_NODES</strong></h4><p>These functions expose the contents of a matched path. NODES returns all nodes, EDGES returns its relationships, and INNER_NODES returns the intermediate nodes without the endpoints. They help applications explain lineage, dependencies, and investigative findings instead of returning only the destination.</p><pre>MATCH p=({id: 1})-[]-&gt;{0,4}(z) <br>RETURN NODES(p) AS res_nodes, <br> INNER_NODES(p) AS res_inner_nodes <br>ORDER BY z.id</pre><h4><strong>ELEMENT_ID</strong></h4><p>ELEMENT_ID returns the identity of a graph element. It is useful when an application must compare, track, or reference a specific node or edge independently of its business properties.</p><pre>MATCH (x) <br>RETURN ELEMENT_ID(x) AS vid, x AS actual_id <br>ORDER BY x.id <br>LIMIT 5</pre><h4><strong>SOURCE and DESTINATION</strong></h4><p>SOURCE and DESTINATION identify the endpoints of an edge. This makes directional checks and edge-centric analysis easier, especially when a query starts from a relationship rather than a node.</p><pre>MATCH (x)-[e]-&gt;() <br>RETURN x.id, SOURCE(e).id AS s <br>ORDER BY e.src, e.dst <br>LIMIT 10</pre><pre>MATCH ()-[e]-&gt;(x) <br>RETURN false IN COLLECT_LIST(x = DESTINATION(e)) AS no</pre><h3><strong>Compose larger queries</strong></h3><h4><strong>NEXT</strong></h4><p>NEXT passes the output of one query stage into the next. Analysts can describe a multistage question in the order they reason about it: calculate a measure, filter the result, follow another relationship, and then summarize again.</p><pre>MATCH (m:Message)-[:hasCreator]-(p:Person) <br>RETURN p, AVG(m.length) AS avg_msg_length GROUP BY p <br>NEXT <br>FILTER avg_msg_length &gt; 100u <br>MATCH (p)-[:knows]-&gt;(:Person) <br>RETURN avg_msg_length, COUNT(*) AS connections <br>GROUP BY p, avg_msg_length</pre><h4><strong>EXISTS subqueries</strong></h4><p>EXISTS answers a yes-or-no question about another graph pattern. It can filter rows or participate inside an aggregate without requiring the outer query to return the matching details.</p><pre>MATCH (x) <br>WHERE EXISTS { <br> MATCH (y) <br> WHERE y.id = 5 <br> RETURN y <br>} <br>RETURN x.id AS xid <br>ORDER BY xid<br>MATCH (x) <br>RETURN COUNT(*) FILTER ( <br> WHERE EXISTS { MATCH (x)-[]-&gt;(y) RETURN y } <br>) AS count_with_out</pre><h4><strong>CALL subqueries</strong></h4><p>CALL runs a contained query for the current outer result. The example calculates each node’s outgoing degree in a focused block and then returns it with the node identifier.</p><pre>MATCH (x) <br>CALL { <br> MATCH (x)-[e]-&gt;(y) <br> RETURN COUNT(e) AS out_degree <br>} <br>RETURN x.id AS xid, out_degree <br>ORDER BY xid</pre><h4><strong>OPTIONAL CALL</strong></h4><p>OPTIONAL CALL preserves the outer row when the contained query has no match. This supports enrichment scenarios where related information is useful but not required.</p><pre>MATCH (x {id: 1}) <br>OPTIONAL CALL { <br> MATCH (y)-[]-&gt;(x) <br> RETURN y.id AS yid <br>} <br>RETURN x.id AS xid, yid <br>ORDER BY yid</pre><h4><strong>UNION DISTINCT</strong></h4><p>UNION DISTINCT combines compatible result sets and removes duplicate rows. It complements UNION ALL, which preserves duplicates, so the query can choose the correct set behavior.</p><pre>MATCH () LIMIT 3 <br>RETURN 42 AS x <br>UNION <br>MATCH () LIMIT 3 <br>RETURN 100u AS x</pre><h3><strong>Summarize connected data</strong></h3><h4><strong>Filtered and paged aggregates</strong></h4><p>Filtered aggregates calculate a summary over a selected subset. Paging controls such as LIMIT can be applied within the aggregate, giving developers precise control over which values contribute to the result.</p><pre>MATCH (m:Movie) <br>RETURN COUNT(*) FILTER (WHERE m.released &lt; 1980 LIMIT 10) AS filtered_count</pre><h4><strong>Nested aggregations</strong></h4><p>Nested aggregation supports layered questions, such as finding the minimum of averages calculated across groups or paths. This reduces the need to move intermediate results into application code.</p><pre>MATCH (a:`node`)-[e:`edge`]-&gt;{1,2}(b:`node`) <br>RETURN a.id AS id, MIN(AVG(e.weight)) AS min_average <br>GROUP BY id</pre><h4><strong>COLLECT_ONE, COLLECT_LIST, and COLLECT_ELEMENTS</strong></h4><p>Collection functions retain values or graph elements for evaluation as a group. COLLECT_ONE selects one value, COLLECT_LIST builds a list, and COLLECT_ELEMENTS gathers graph elements. They are useful for path-level checks, ordered output, and analysis across repeated relationships.</p><pre>MATCH (p:`node` {id: 1})-[e]-&gt;{2}(p1:`node` {id: 1}) <br>RETURN (COLLECT_ONE(e.weight) IN [e[0].weight, e[1].weight]) AS contained</pre><pre>MATCH ()-[e]-&gt;{1,2}() <br>RETURN COLLECT_LIST(ALL e.weight) AS w <br>ORDER BY w <br>LIMIT 20</pre><pre>MATCH ()-[a:ACTED_IN]-&gt;{0,4}() <br>WHERE SIZE(COLLECT_ELEMENTS(DISTINCT a.roles)) &gt; 4 <br>RETURN TO_JSON_STRING(a.roles) AS r</pre><h3><strong>Work with values and text</strong></h3><h4><strong>Dynamic nested data</strong></h4><p>Support for dynamic nested data lets queries work with richer values that do not fit a flat property model. This is useful when graph entities contain structured application payloads, nested attributes, or evolving schemas.</p><h4><strong>CAST</strong></h4><p>CAST converts a value to a supported target type. Explicit conversion makes comparisons and calculations more predictable when source data uses different numeric representations.</p><pre>RETURN CAST(42 AS DOUBLE) AS double_res, <br> CAST(42 AS UINT) AS uint_res, <br> CAST(42.5d AS INT) AS int_res</pre><h4><strong>RANGE</strong></h4><p>RANGE creates a numeric sequence. A generated sequence can support iteration, testing, bucketing, and list-oriented calculations within a query.</p><pre>RETURN RANGE(0, 4) AS res</pre><h4><strong>POWER</strong></h4><p>POWER performs exponent calculations. It extends the numeric expressions available for scoring, weighting, and mathematical transformations.</p><pre>RETURN POWER(-2, 3) AS res</pre><h4><strong>NORMALIZE and IS NORMALIZED</strong></h4><p>Unicode text can have visually identical but technically different encodings. NORMALIZE converts text to a normalization form, while IS NORMALIZED checks its current form. This supports more consistent matching and grouping across multilingual data.</p><pre>RETURN NORMALIZE(&#39;cafe\u0301&#39;) AS normalized_text<br>RETURN &#39;cafe\u0301&#39; IS NFKD NORMALIZED AS is_normalized</pre><h4><strong>Regular-expression functions</strong></h4><p>The MSFT.REGEXP functions match, count, locate, extract, and replace text patterns. They help prepare identifiers, names, codes, and descriptions before those values are compared or summarized.</p><pre>RETURN MSFT.REGEXP_LIKE(&#39;café&#39;, &#39;caf.&#39;) AS x<br>RETURN MSFT.REGEXP_COUNT(&#39;abcabcabc&#39;, &#39;abc&#39;) AS n<br>RETURN MSFT.REGEXP_INSTR(&#39;hello world&#39;, &#39;world&#39;) AS p<br>RETURN MSFT.REGEXP_REPLACE(&#39;a1b2c3&#39;, &#39;[0–9]&#39;, &#39;#&#39;) AS s<br>RETURN MSFT.REGEXP_SUBSTR(&#39;abc123def&#39;, &#39;[0–9]+&#39;) AS s</pre><h3><strong>Design guidance</strong></h3><p>Use the narrowest pattern that answers the question. Start from selective nodes, specify relationship and node labels, and apply filters early. Use bounded traversal when the business question has a natural maximum. When depth is unknown, combine an unbounded path with an appropriate path mode and test it against representative graph density. Return only the properties or path elements the application requires.</p><p>Feature availability can vary by environment and release stage. Confirm current support and syntax in the Microsoft Fabric Graph documentation before publishing a production query.</p><h3><strong>Next steps</strong></h3><p>Choose a connected-data scenario — such as lineage, dependency analysis, recommendations, investigations, or knowledge discovery — and identify which path, composition, and aggregation features make the question easier to express.</p><ul><li><a href="https://learn.microsoft.com/fabric/graph/overview">Graph in Microsoft Fabric overview</a></li><li><a href="https://learn.microsoft.com/fabric/graph/gql-language-guide">GQL language guide for graph in Microsoft Fabric</a></li><li><a href="https://learn.microsoft.com/fabric/graph/gql-graph-patterns">GQL graph patterns</a></li><li><a href="https://learn.microsoft.com/fabric/graph/gql-conformance">GQL standard conformance for graph in Microsoft Fabric</a></li><li><a href="https://learn.microsoft.com/fabric/graph/gql-query-performance">Optimize GQL query performance for graph in Microsoft Fabric</a></li></ul><p><strong>Tags: </strong>Graph, Graph Query Language (GQL), graph traversal, connected data, developers</p><p><a href="https://www.linkedin.com/in/muriloadriano?trk=article-ssr-frontend-pulse_little-mention">Murilo Vasconcelos, </a><a href="https://de.linkedin.com/in/stefan-plantikow-49896637/en?trk=article-ssr-frontend-pulse_little-mention">Stefan Plantikow, </a><a href="https://www.linkedin.com/in/idrismotiwala?trk=article-ssr-frontend-pulse_little-mention">Idris Motiwala, </a><a href="https://www.linkedin.com/in/eldad-hagashi?trk=article-ssr-frontend-pulse_little-mention">Eldad Hagashi, </a><a href="https://www.linkedin.com/in/qian-liang-67132311?trk=article-ssr-frontend-pulse_little-mention">Qian Liang, </a><a href="https://www.linkedin.com/in/navondanny?trk=article-ssr-frontend-pulse_little-mention">Danny Navon, </a><a href="https://uk.linkedin.com/in/mrobson1975?trk=article-ssr-frontend-pulse_little-mention">Michael Robson, </a><a href="https://es.linkedin.com/in/paubaiget?trk=article-ssr-frontend-pulse_little-mention">Pau Baiget, </a><a href="https://www.linkedin.com/in/rajagopal-ravipati-79020a4?trk=article-ssr-frontend-pulse_little-mention">Rajagopal Ravipati</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f461671fa4ce" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoft/more-expressive-graph-analysis-gql-improvements-in-microsoft-fabric-graph-f461671fa4ce">More expressive graph analysis: GQL improvements in Microsoft Fabric Graph</a> was originally published in <a href="https://medium.com/microsoft">Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a Governed Multi-Agent Content Factory on Azure]]></title>
            <link>https://medium.com/microsoft/building-a-governed-multi-agent-content-factory-on-azure-663a16dd2b7c?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/663a16dd2b7c</guid>
            <dc:creator><![CDATA[Lior Yantovski]]></dc:creator>
            <pubDate>Mon, 05 Oct 2026 23:42:16 GMT</pubDate>
            <atom:updated>2026-09-26T18:32:39.401Z</atom:updated>
            <content:encoded><![CDATA[<p><em>How three A2A agents, Azure Container Apps Sandboxes, and Microsoft Foundry come together to turn a topic into a research brief, a blog post, social content, and a podcast — with governed, private, default-deny networking end to end.</em></p><p>As soon as an agent needs to touch the open internet — search, scrape, retrieve — “secure by design” stops being a slide and starts being an actual network problem.</p><p>This lab (<strong>aca-sandbox-foundry</strong>, an evolution of <a href="https://github.com/jkalis-MS/azure-container-apps-multi-agent-workflow">jkalis-MS/azure-container-apps-multi-agent-workflow</a>) is a reference implementation for exactly that problem: an AKS-hosted, APIM-governed multi-agent system that isolates the one risky operation — web retrieval — inside disposable Azure Container Apps (ACA) Sandboxes, while everything around it stays authenticated, private, and observable.</p><p>Link to the repository and the full documentation journey at the bottom of this article.</p><h3>What It Actually Does</h3><p>The lab turns a single topic into a complete content package.</p><p>A <strong>Researcher</strong> agent gathers and synthesizes trusted sources into a research brief.</p><p>A <strong>Content Creator</strong> agent turns that brief into a long-form blog post and a social content package.</p><p>A <strong>Podcaster</strong> agent generates a multi-speaker script, synthesizes audio, and persists the result.</p><p>A browser-based <strong>DevUI</strong> shows the whole run: live agent health, sandbox lifecycle events, egress evidence, and the generated artifacts as they land.</p><h3>Solution at a Glance</h3><p><em>High-level architecture: the DevUI orchestrator, three framework-diverse agents, APIM, Foundry, Application Insights, and the ACA Sandbox retrieval path.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HtcNIY_vursHgmVzKDPXDg.png" /><figcaption><em>High-level architecture: the DevUI orchestrator, three framework-diverse agents, APIM, Foundry, Application Insights, and the ACA Sandbox retrieval path.</em></figcaption></figure><p>The user-facing orchestrator coordinates three framework-diverse agents on AKS. APIM governs both agent and model traffic, Microsoft Foundry supplies models and agent registration, Application Insights captures telemetry end to end, and ACA Sandboxes isolate only the research retrieval tool — the sandboxes never host the three long-running agents themselves.</p><h3>Three Agents, Three Frameworks, One Contract</h3><p>The lab intentionally refuses to treat every agent as “the same app in a different container.” Each one uses a distinct framework and runtime suited to its job, and <strong>A2A (Agent2Agent)</strong> is the common contract that lets them interoperate anyway — a real test of the protocol, not a convenience wrapper around one SDK.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/850/1*u4GM-aZS8HXzZG8sBUf7sQ.png" /><figcaption><em>Three-agent roles: Researcher, Content Creator, and Podcaster, each independently deployable and reachable only through APIM.</em></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PMrktAjndS80FvIgi0cz2Q.png" /></figure><p>DevUI is the user-facing orchestrator, but it is deliberately dumb about security: it runs the research step first, sends the resulting brief to the creator and podcaster in parallel, and never talks to an agent directly. Every call goes same-origin to the BFF, and every BFF call goes through APIM. No agent calls another agent — each remains an independently deployable service that happens to share an interoperability contract, not a tightly coupled pipeline.</p><h3>The Azure Stack, Component by Component</h3><p>This is where the lab earns its keep — not by picking exotic technology, but by wiring familiar Azure services together with a consistently paranoid network posture.</p><h3>Azure Kubernetes Service (AKS)</h3><p>AKS is the compute backbone for all three agents and the BFF. Each agent runs on a dedicated, tainted node pool, isolated from general workloads. No agent Pod is exposed publicly: every agent is fronted by an internal Kubernetes <em>LoadBalancer</em> Service bound to a private VNet address rather than a public IP. <em>loadBalancerSourceRanges</em> on each Service restricts inbound connections to APIM’s subnet alone, and Azure CNI powered by Cilium enforces the identical restriction a second time inside the cluster’s own dataplane. That redundancy is deliberate: even a bug in DevUI or the BFF that tried to call an agent directly, bypassing APIM, would find no route to take. AKS also hosts the Sandbox Broker, which is the only component permitted to request a sandbox on the Researcher’s behalf.</p><h3>Azure API Management (APIM)</h3><p>APIM is the single governed front door for two very different kinds of traffic, and that is the point: it is the only path in either direction. First, it fronts <strong>A2A traffic</strong> between the BFF and the three agents, so every inter-agent request is authenticated, rate-limited, and logged in one place rather than scattered across ad hoc service-to-service calls. Second, it exposes the <em>/openai</em> gateway that all three agents use for Microsoft Foundry model and text-to-speech access, so no agent holds a direct Foundry endpoint or API key of its own. Because APIM is also the only subnet allow-listed by every agent’s <em>loadBalancerSourceRanges</em>, it doubles as the network chokepoint the whole design is built around, not just an API facade.</p><h3>Microsoft Foundry</h3><p>Foundry is the model and agent-registration plane. It supplies the large language models the Researcher, Content Creator, and Podcaster call for synthesis, drafting, and script generation, along with the text-to-speech models behind the podcast audio. Foundry also handles custom-agent registration, giving each agent a governed identity in the platform rather than being an anonymous caller of a shared model endpoint. Every one of those calls is routed through the APIM <em>/openai</em> gateway — agents never dial Foundry directly, which keeps model access inside the same audit and policy boundary as every other governed call in the system.</p><h3>Azure Container Apps (ACA) Sandboxes</h3><p>Azure Container Apps Sandboxes reached <strong>general availability this week</strong> — and it is not a new isolation stack. It is Microsoft externalizing the same hardware-isolated microVM fabric that already runs Cloud Sandboxes in GitHub Copilot ,Foundry Hosted Agents, Azure ARE Agents and more. During public preview it was already creating over a million sandboxes a day. That maturity is exactly why it is the right foundation for the Researcher’s retrieval path in this lab, and for running private coding agents more broadly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kdIcCrzc22qqfqNVm-WTaw.png" /></figure><p><em>The GA announcement: sandboxes execute securely by default, resume instantly from a full memory-and-disk snapshot, and burst to hyperscale in sub-second time — with Azure Container Apps, Foundry, GitHub, and Container Apps Express all building on the same foundation layer.</em></p><p>The topology behind that announcement is straightforward once you see it laid out. A sandbox group is the unit of governance: everything inside it shares disk images, snapshots, data volumes, secrets, and identity, while every individual sandbox still gets its own CPU, memory, disk, and network boundary.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/932/1*zl2PauTF7F0tLYjKJNzMOw.jpeg" /></figure><p><em>Portal, CLI, and SDK access all converge on a sandbox group. Ingress is off by default and opt-in per sandbox and port, waking on request; egress runs through a per-sandbox proxy enforcing host allowlists and deny policies, with injected credentials that never enter the sandbox itself.</em></p><p>That last point is the one worth sitting with: credential injection happens at the egress proxy, <strong>outside</strong> the sandbox boundary. Code running inside — including AI-generated code — never sees the actual secret, only the effect of a request that was allowed to go through. It is the same shape as the Sandbox Broker pattern in this lab’s Researcher path, just implemented as a first-class platform primitive instead of something you wire up yourself.</p><h3>What This Looks Like Running</h3><p>A sandbox group in the Azure portal shows exactly what it costs to keep isolation this granular: total sandboxes, how many are actually running versus stopped, custom images, and snapshots, alongside live runtime metrics for running cores and memory.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gDjs7jvTi4TE-ogazEta6g.png" /></figure><p><em>A live sandbox group: 4 total sandboxes (one goes down), running-core and running-memory metrics over the last days, and recent sandboxes each stopped with their exact resource footprint (4 cores / 8 GiB / 80 GiB, down to 0.25 cores / 512 MiB / 5 GiB) preserved for the next resume.</em></p><p>Scoping sandboxes per task, rather than sharing one long-lived environment, is the pattern that keeps retrieval contained. Here five sandboxes are each labeled with the single host they were created to reach — one for azure.microsoft.com, one for learn.microsoft.com, one for github.com, and so on — all created within the same second and all running on identical 1 core / 2 GiB / 20 GiB footprints.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NlefV3b8J8QP2j0aconh7Q.png" /></figure><p><em>Five sandboxes, each scoped to a single allow-listed host and spun up simultaneously — the sub-second, burst-to-hyperscale behavior from the GA announcement, seen from the inside.</em></p><p>And this is the observability piece made concrete: a single running sandbox, its live terminal, and its egress network traffic panel — every outbound request logged with a timestamp, method, destination, and an explicit allowed or denied verdict, right next to real-time CPU, memory, storage, and network utilization and a live log stream.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gznGhwr6kVKkEk4NmsUTcw.png" /></figure><p><em>22 requests allowed, 0 denied — every GET call to azure.microsoft.com, learn.microsoft.com, files.pythonhosted.org, and pypi.org visible with its verdict, alongside live CPU, memory, storage, and network metrics for the sandbox.</em></p><p>This is what “governed, closed, and observable” means in practice: nothing leaves the sandbox that was not explicitly allow-listed, nothing that does leave is invisible, and none of it costs meaningful startup latency. For a Researcher agent fetching untrusted web content, or for a private Claude or GitHub Copilot coding agent running inside a customer’s tenant, that combination — hardware isolation, default-deny egress with full request-level audit, and sub-second start — is precisely the missing piece between “agents that browse the web” and “agents you can actually run in a governed enterprise environment.”</p><p>Now let’s return to our use case and see how ACA Sandboxes provides best solution for our needs.</p><p>ACA Sandboxes exist to solve one specific problem: the Researcher’s job requires fetching content whose provenance and payload it does not control, and that is the one operation in the whole system with real blast radius. The Researcher never performs that fetch itself — it hands the task to a <strong>Sandbox Broker</strong>, which spins up a short-lived, per-task ACA Sandbox with <strong>default-deny egress (</strong>in our example we blocked bing.com on purpose), scoped to exactly the destinations that single task requires. When the task completes, the sandbox is torn down with it. If a scraped page tried to phone home or pivot toward an internal service, there would be nothing left for it to reach by the time anyone noticed. Sandboxes are strictly a retrieval tool for the Researcher — they never host the long-running agents, the BFF, or DevUI.</p><h3>Identity, Storage, and Observability</h3><p>A user authenticates through Microsoft Entra ID, fronted by Application Gateway for Containers and an OAuth2 Proxy sidecar pattern, so no credential — reusable or otherwise — ever lives in the browser. The Podcaster writes generated audio to private Azure Blob Storage using Workload Identity instead of a connection string or access key in a config file. And OpenTelemetry instrumentation runs through every agent and the BFF, exporting to Application Insights and Log Analytics with APIM diagnostics stitched into the same correlation IDs, so a slow or failed run can be traced end to end — from the browser click down through the sandbox that did the retrieval.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kMmE9e0iTX4GeRcy6c7Yhg.png" /><figcaption>System Architecture</figcaption></figure><h3>Seeing It Run: User Experience</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P8oxcmPumh3BpSEft3f2nA.png" /><figcaption>DevUI is the user-facing orchestrator</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ldy8QeHxHYWFS6CSzGt91Q.png" /><figcaption><em>DevUI showing ACA Sandbox execution, egress evidence, the synthesized research brief, and generated blog content.</em></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nwT0DxIzhn8RL7iA1EYZcA.png" /><figcaption>Finally, we got full Media blog + Social Post + Reay Podcast with Audio + Transcript</figcaption></figure><h3>How a Request Actually Flows</h3><p>1. A user authenticates with Microsoft Entra ID through Application Gateway for Containers and OAuth2 Proxy.</p><p>2. DevUI JavaScript calls same-origin protected APIs through the BFF.</p><p>3. The BFF sends A2A requests to APIM rather than exposing reusable downstream credentials in the browser.</p><p>4. APIM reaches three source-restricted private AKS origins: research, creator, and podcaster.</p><p>5. The agents use the APIM <em>/openai</em> gateway for Foundry model and TTS access.</p><p>6. Research delegates isolated retrieval to the Sandbox Broker, which creates policy-controlled ACA Sandboxes.</p><p>7. Podcaster persists audio through a private Blob endpoint, while workloads and APIM export correlated telemetry to Application Insights.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jwZMuWpMWldrQNSQi8cNNA.png" /><figcaption>Network Design</figcaption></figure><h3>Project Status and Deployment Boundary</h3><p>This is a working baseline, not a proof of concept: AKS, APIM, Foundry, ACA Sandboxes, private storage, identity, ingress, and observability are all deployed and validated together as a conventional Kubernetes stack, stood up end to end with the Azure Developer CLI and Bicep.</p><p>One caveat worth flagging for anyone adapting this: the demonstration AKS API endpoint is left public for operator convenience, while the application workloads and agent origins themselves stay private. A production deployment needs a private AKS control plane, trusted TLS, production-grade identity governance, and organization-approved network controls layered on top of everything described above.</p><h3>Summary</h3><p>The interesting decision in this lab is not “agents can collaborate” — that part is easy to demo and easy to fake. It is that the one operation with real blast radius, unrestricted web retrieval by an LLM-driven agent, is fully contained behind default-deny, per-task sandboxes, enforced at two independent layers of the network, while the rest of the system stays governed by Entra ID, APIM, and Foundry end to end.</p><h3>Resources and documentation</h3><p>● Repository: <a href="https://github.com/lyantovski/aca-sandbox-foundry">lyantovski/aca-sandbox-foundry</a></p><p>● <a href="https://techcommunity.microsoft.com/blog/appsonazureblog/azure-container-apps-sandboxes-now-generally-available/4559125">Azure Container Apps Sandboxes, Now Generally Available | Microsoft Community Hub</a></p><p>● <a href="https://sandboxes.azure.com/docs/sandboxes/">ACA Sandboxes | ACA Sandboxes Portal Docs</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=663a16dd2b7c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoft/building-a-governed-multi-agent-content-factory-on-azure-663a16dd2b7c">Building a Governed Multi-Agent Content Factory on Azure</a> was originally published in <a href="https://medium.com/microsoft">Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Sharing a few tips and tricks about AI on Azure, that Claude itself isn’t always aware of!]]></title>
            <link>https://medium.com/microsoft/sharing-a-few-tips-and-tricks-about-ai-on-azure-that-claude-itself-isnt-always-aware-of-c44faeb6b7cd?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/c44faeb6b7cd</guid>
            <category><![CDATA[azure]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <dc:creator><![CDATA[Stephane Eyskens]]></dc:creator>
            <pubDate>Mon, 05 Oct 2026 23:42:11 GMT</pubDate>
            <atom:updated>2026-10-05T23:42:10.096Z</atom:updated>
            <content:encoded><![CDATA[<p>I was recently part of an AI project where I learnt a few things and realized that I was not the only one to learn, so I thought it might be a good idea to share the findings with a broader audience.</p><h4>Tip #1 — Foundry-hosted agents and outbound traffic</h4><p>When hosting your agents in Foundry, they are running into a container app environment managed by Microsoft behind the scenes. While Foundry supports the BYO subnet feature, you must make sure to:</p><ul><li>Use a standard setup (not basic)</li><li>Bring not only your own subnet but also your own resources, meaning Cosmos DB, AI Search, Storage, etc.</li></ul><p>Only bringing your own subnet will not throw any error but the agents will still fail to resolve private link resources and go to the public endpoints of any resource they try to reach.</p><p>Here is a useful repo to get started <a href="https://github.com/microsoft-foundry/foundry-samples/">https://github.com/microsoft-foundry/foundry-samples/</a></p><h4>Tip #2 — Using private link with Sandbox Groups</h4><p>Azure Sandbox Groups are a great way to execute LLM-generated code safely. They are backed by MicroVMs, ensuring strict isolation as well as lightning speed. However, in the enterprise environment, we tend to isolate things from internet as much as possible, and here comes the tip! Sandbox Groups themselves have no private endpoints. The best you can achieve is to add network ACLs on their public endpoints. However, you can attach them to Container Apps Environments of type ‘Express’. Once attached, the Sandbox Groups can be connected using private endpoints. You can read more about this here <a href="https://sandboxes.azure.com/docs/sandboxes/private-endpoints">https://sandboxes.azure.com/docs/sandboxes/private-endpoints</a></p><h4>Tip #3 — Dealing with MCP authentication (DCR and/or CIMD)</h4><p>I shared a few options to deal with MCP within the Azure and Microsoft ecosystem. You can read this here to get all the details <a href="https://medium.com/@stephaneeyskens/i-built-my-own-wine-companion-mcp-server-on-azure-and-net-it-wasnt-that-straightforward-f8e74fab8722">https://medium.com/@stephaneeyskens/i-built-my-own-wine-companion-mcp-server-on-azure-and-net-it-wasnt-that-straightforward-f8e74fab8722</a> .</p><p>However, I recently discovered an option I wasn’t aware of, consisting of using FastMCP, a Python library. In a nutshell, FastMCP is a library that is part of your MCP server and acts as a proxy between the MCP client and your MCP server.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/862/1*_2LXsudQGBvDpsx5BIOvLQ.png" /><figcaption>FastMCP library</figcaption></figure><p>It supports both Dynamic Client Registration (DCR) and Client ID Metadata Documents (CIMD). During the handshake, the client communicates with FastMCP rather than directly with the identity provider for registration and token acquisition. The client interacts with Entra ID only to authenticate the user.</p><p>FastMCP acquires tokens transparently and passes them to the MCP server, which can then use an on-behalf-of (OBO) flow to obtain tokens for downstream APIs. FastMCP also provides a state API that makes it easier to persist state in Redis, using a computed JTI key to link that state to upstream tokens.</p><p>Below is the sequence diagram showing the flow.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cADAMov0Nb5Sntu1eKFbUg.png" /><figcaption>MCP Client-Server interaction with Entra ID as the IDP</figcaption></figure><p>Here is a pointer to the official FastMCP web site <a href="https://gofastmcp.com/v2/servers/auth/oauth-proxy">https://gofastmcp.com/v2/servers/auth/oauth-proxy</a></p><h4>Tip #4 — Dealing with MCP integration with SaaS platforms</h4><p>Although Satya Nadella suggested that SaaS platforms would die with the rise of AI, we still see many SaaS platforms whose the core business <strong>is</strong> AI. Platforms such as Perplexity and Claude code are just examples of these. I see two ways to expose your enterprise MCP servers to the outside world:</p><ul><li>Use Private Link Service (PLS) whenever possible if the SaaS provider supports it.</li><li>Expose your MCP server to Internet. In this case, you’d go for Front Door/Application Gateway ==&gt; API Management ==&gt; MCP server with or without FastMCP.</li></ul><p>However, at this stage, using PLS remains not that easy because:</p><ul><li>As of 09/2026, PLS Direct Connect is still in preview and only available in a few regions (e.g. only Spain Central for Europe).</li><li>The destination of a PLS cannot be a private endpoint, although it technically works (I tested it).</li></ul><p>The Citadel approach consists in using an AI gateway (API Management) as a central policy enforcement point. However, as of 09/2026, we cannot use Private Link Service (PLS) with API Management’s load balancer because PLS does not recognize it as an Azure Load Balancer. A private endpoint for APIM might seem like an alternative, but that scenario is not supported either. PLS requires a standard Azure Load Balancer, such as the one used by AKS.</p><p>For now, the only supported approach appears to be proxying the AI gateway through a gateway API hosted on AKS, although that feels like a dirty workaround. Hopefully, Microsoft will make PLS Direct Connect generally available across all regions soon and support private endpoints as destinations, enabling a wider range of integration scenarios.</p><h4>Tip #5 — Writing stateful agents</h4><p>There are many ways to orchestrate agents, but fewer options for running stateful orchestrations. As of 09/2026, I consider Dapr workflows to be one of the best options. Additionally, Dapr makes it easy to run ambient agents, which are nothing else but agents responding to events/commands, and Dapr particularly excels in building distributed systems.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c44faeb6b7cd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoft/sharing-a-few-tips-and-tricks-about-ai-on-azure-that-claude-itself-isnt-always-aware-of-c44faeb6b7cd">Sharing a few tips and tricks about AI on Azure, that Claude itself isn’t always aware of!</a> was originally published in <a href="https://medium.com/microsoft">Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deploy and use the Foundry Model Router using Azure Bicep]]></title>
            <link>https://medium.com/microsoft/deploy-and-use-the-foundry-model-router-using-azure-bicep-0339eddaaffa?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/0339eddaaffa</guid>
            <category><![CDATA[microsoft]]></category>
            <category><![CDATA[azure]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <dc:creator><![CDATA[Brian Veldman]]></dc:creator>
            <pubDate>Mon, 31 Aug 2026 14:49:53 GMT</pubDate>
            <atom:updated>2026-08-31T14:49:51.865Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZCVhvncuNr-DQrlhnqv63w.png" /></figure><p>As organizations build more AI powered applications, choosing the right model for every request becomes increasingly important. Not every prompt requires a large and expensive reasoning model, while more complex workloads often benefit from advanced models with higher capabilities. Microsoft Foundry Model Router addresses this challenge by automatically selecting the most appropriate model for each request based on factors such as complexity, quality requirements, latency, and cost. Instead of maintaining custom routing logic, developers can interact with a single endpoint while the routing decisions happen behind the scenes..</p><p>In this article, we will deploy Microsoft Foundry Model Router using Bicep and explore how Infrastructure as Code can simplify the deployment and management of intelligent AI routing workloads on Azure.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CiUX1IASkakKJWvzC-12Yw.gif" /><figcaption>This diagram costed me $3 dollars on AI credits…</figcaption></figure><p>The main.bicepparam template defines our input parameters, such as the Landing Zone, Environment, Location.</p><pre>using &#39;main.bicep&#39;<br><br>//////////////////////////////////<br>param parAlzName = &#39;sln&#39;<br>param parEnvironment = &#39;prod&#39;<br>param parLocation = &#39;swedencentral&#39;<br>/////////////////////////////////</pre><p>The main.bicep template serves as the entry point for our Bicep configuration and defines the parameters and variables used across the Azure AI Foundry module.</p><pre>metadata name = &#39;Cognitive Services Account with Model Router&#39;<br>metadata description = &#39;This is a Bicep template to deploy a Cognitive Services Account with the Model Router deployment.&#39;<br>metadata owner = &#39;Brian Veldman&#39;<br>metadata version = &#39;1.0.0&#39;<br><br>/* TARGET SCOPE */<br>targetScope = &#39;subscription&#39;<br><br>@description(&#39;Defining our input parameters&#39;)<br>param parEnvironment string<br>@allowed([<br>  &#39;swedencentral&#39;<br>])<br><br>param parLocation string <br>param parAlzName string<br><br>@description(&#39;Defining our variables&#39;)<br>var shortEnvironmentMapping = {<br>  swedencentral: &#39;sdc&#39; // Supported for Model Router in Foundry<br>}<br><br>var shortEnvironment = shortEnvironmentMapping[parLocation] ?? parLocation<br>var resourceGroupName = &#39;rg-${parAlzName}-${parEnvironment}-${shortEnvironment}-001&#39;<br><br>@description(&#39;Deploying our resourcegroup&#39;)<br>resource rg &#39;Microsoft.Resources/resourceGroups@2025-04-01&#39; = {<br>  name: resourceGroupName<br>  location: parLocation<br>}<br><br>@description(&#39;Deploying our AI module&#39;)<br>module ai &#39;modules/ai.bicep&#39; = {<br>  params: {<br>    parAlzName: parAlzName<br>    parEnvironment: parEnvironment<br>    parLocation: parLocation<br>    shortEnvironment: shortEnvironment<br>  }<br>  scope: rg<br>}</pre><p>The ai.bicep module automates the deployment of an Azure AI Foundry environment by provisioning an Azure AI Services account, an AI Foundry project, and a Model Router deployment. It creates a centrally managed AI platform with project management capabilities enabled, configures a dedicated AI Foundry project with a system assigned managed identity for secure resource access, and deploys a Model Router endpoint using the Global Standard SKU. The module also applies a consistent naming convention based on the landing zone, environment, and location parameters, enabling standardized and scalable AI service deployments across Azure environments. ❤️</p><pre>param parEnvironment string<br>param parLocation string <br>param parAlzName string<br>param shortEnvironment string<br><br>@description(&#39;Deployment of Foundry&#39;)<br>resource aif &#39;Microsoft.CognitiveServices/accounts@2025-12-01&#39; = {<br>  name: &#39;aif-${parAlzName}-${parEnvironment}-${shortEnvironment}-001&#39;<br>  location: parLocation<br>  kind: &#39;AIServices&#39;<br>  sku: {<br>    name: &#39;S0&#39;<br>  }<br>  properties: {<br>    allowProjectManagement: true<br>    customSubDomainName: &#39;sub-aif-${parAlzName}-${parEnvironment}-${shortEnvironment}-001&#39;<br>  }<br>}<br><br>@description(&#39;Deployment of Foundry Project&#39;)<br>resource aip &#39;Microsoft.CognitiveServices/accounts/projects@2025-12-01&#39; = {<br>  name: &#39;proj-aif-${parAlzName}-${parEnvironment}-${shortEnvironment}-001&#39;<br>  parent: aif<br>  location: parLocation<br>  identity: {<br>    type: &#39;SystemAssigned&#39;<br>  }<br>}<br><br>@description(&#39;Deployment of Foundry Model Router&#39;)<br>resource router &#39;Microsoft.CognitiveServices/accounts/deployments@2025-12-01&#39; = {<br>  name: &#39;model-router&#39;<br>  parent: aif<br>  sku: {<br>    name:  &#39;GlobalStandard&#39;<br>    capacity: 499 //1 capacity unit = 1000 tokens per minute, took the standard capacity<br>  }<br>  properties: {<br>    model: {<br>      name: &#39;model-router&#39;<br>      format: &#39;OpenAI&#39;<br>      version: &#39;2025-11-18&#39; // Last supported version<br>      <br>    }<br>    routing: {<br>      mode: &#39;balanced&#39;<br>    }<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-AzSubscriptionDeployment -Name deploymentName -TemplateFile .\main.bicep -TemplateParameterFile .\main.bicepparam -Location swedencentral.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d0r7Q-wDm6h1nDA4-LRm4Q@2x.png" /></figure><p>After deployment, you can use the standard Chat Completions API against the Model Router endpoint. Simple prompts are typically routed to smaller and cheaper models, while more complex reasoning tasks are automatically directed to larger models. This allows organizations to optimize both cost and performance without modifying application logic.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9ThjMg7T75dl09fybFOEhQ@2x.png" /></figure><p>Within the Microsoft Foundry portal, navigate to Deployments and verify that the Model Router deployment is present and successfully provisioned.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*88I5xycDtnQsN0Y_8y3iFw@2x.png" /></figure><p>We can see the model-router deployment. For this demo, I will use the Open in Playground option, which allows us to test the Model Router directly from within the browser.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZzoRjh-TTTOxTCcv8J4nUQ@2x.png" /></figure><p>When I ask <em>“What is Azure?”</em>, the request is routed to the GPT-5 Mini model by the Model Router, which selects the most appropriate model based on the prompt and routing configuration. For this query, the GPT-5 Mini model is chosen to generate the response.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Z_BQiddxoEBRZGIPhubZ-Q@2x.png" /></figure><p>However, when I ask, <em>“Can you write an Azure Bicep template based on Azure Verified Modules to deploy an Azure Virtual Machine?”</em>, the Model Router selects the GPT-5.3 Chat model. This is because the request involves more advanced reasoning, code generation, and knowledge of Azure infrastructure patterns, making GPT-5.3 Chat the more suitable model for generating an accurate and comprehensive response.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eYDI5YCQLWT_YjanMmSOfw@2x.png" /></figure><p>We can also use the Completions API to call the Model Router endpoint directly. With this approach, every request is automatically routed to the most suitable model based on the complexity and requirements of the prompt. This allows applications to benefit from optimized model selection without having to manually choose between different models, helping to balance performance, capability, and cost.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ytZTFZngycyZjqvAPhrV1g@2x.png" /></figure><p>That’s all for today. As you could see, Azure AI Foundry Model Router simplifies the way applications interact with AI models by automatically selecting the most suitable model for each request. Whether you are handling simple questions, complex reasoning tasks, or code generation scenarios, Model Router helps optimize performance, capability, and cost without requiring manual model selection. This makes it easier to build intelligent applications that can adapt to a wide range of user requests while taking full advantage of the latest AI models available in Azure AI Foundry. 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=0339eddaaffa" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoft/deploy-and-use-the-foundry-model-router-using-azure-bicep-0339eddaaffa">Deploy and use the Foundry Model Router using Azure Bicep</a> was originally published in <a href="https://medium.com/microsoft">Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Configuring Microsoft Entra ID Authentication for Azure SQL Database using Azure Bicep]]></title>
            <link>https://medium.com/microsoft/configuring-microsoft-entra-id-authentication-for-azure-sql-database-using-azure-bicep-d0bc5d01875d?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/d0bc5d01875d</guid>
            <category><![CDATA[infrastructure-as-code]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[sql-server]]></category>
            <category><![CDATA[microsoft]]></category>
            <category><![CDATA[azure]]></category>
            <dc:creator><![CDATA[Brian Veldman]]></dc:creator>
            <pubDate>Mon, 17 Aug 2026 17:44:18 GMT</pubDate>
            <atom:updated>2026-08-17T17:44:17.697Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*s3NUB9uegxX0HJbX0Mmqxg.png" /></figure><p>When I started blogging, one of my first articles was about configuring Microsoft Entra ID authentication for Azure SQL Database. At that time, everything was done manually through the Azure portal using ClickOps. While that worked perfectly fine, it wasn’t exactly the Infrastructure as Code approach that I prefer. Recently, I was asked how to deploy Azure SQL with Microsoft Entra ID authentication entirely using Azure Bicep. That question inspired me to revisit the topic and build a fully automated solution that not only deploys the Azure SQL Server and database, but also creates the required Microsoft Entra groups and configures the Entra administrator. In this blog, I’ll walk you through building a complete end to end Azure Bicep solution, allowing you to provision Azure SQL with Microsoft Entra ID authentication from scratch without relying on manual configuration in the Azure portal.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aEbobZJZzc89VxDBmeh8jA.gif" /><figcaption>Diagram of the solution that we are going to deploy ❤</figcaption></figure><p>The main.biceptemplate serves as the entry point for our Infrastructure as Code solution. It defines the parameters, variables, and module orchestration required to deploy the complete Azure SQL environment.</p><pre>metadata name = &#39;Deploy Azure SQL Server with Entra ID Authentication&#39;<br>metadata description = &#39;Deploys an Azure SQL Server with Entra ID authentication enabled for administrators.&#39;<br>metadata owner = &#39;Brian Veldman&#39;<br>metadata version = &#39;1.0.0&#39;<br><br>/* TARGET SCOPE */<br>targetScope = &#39;subscription&#39;<br>/* EXTENSIONS */<br>extension &#39;br:mcr.microsoft.com/bicep/extensions/microsoftgraph/v1.0:0.1.8-preview&#39;<br><br>@description(&#39;Defining our input parameters&#39;)<br>@allowed([<br>  &#39;canadacentral&#39;<br>  &#39;westus&#39;<br>  &#39;westus2&#39;<br>  &#39;eastus&#39;<br>  &#39;eastus2&#39;<br>  &#39;westeurope&#39;<br>])<br>param parLocation string = &#39;canadacentral&#39;<br>param parEnvironment string<br>param parAlzName string<br><br>@description(&#39;Defining our variables&#39;)<br>var varShortEnvironmentMapping = {<br>  canadacentral: &#39;cnc&#39;<br>  westus: &#39;wus&#39;<br>  westus2: &#39;wus2&#39;<br>  eastus: &#39;eus&#39;<br>  eastus2: &#39;eus2&#39;<br>  westeurope: &#39;weu&#39;<br>}<br><br>var shortEnvironment = varShortEnvironmentMapping[parLocation] ?? parLocation<br>var resourceGroupName = &#39;rg-sql-${parAlzName}-${parEnvironment}-${shortEnvironment}-001&#39;<br>var sqlServerName = &#39;sql-entra-${parAlzName}-${parEnvironment}-${shortEnvironment}-001&#39;<br>var sqlDatabaseName = &#39;sqldb-test-${parAlzName}-${parEnvironment}-${shortEnvironment}-001&#39;<br><br>@description(&#39;Resource Group Deployment&#39;)<br>resource sqlResourceGroup &#39;Microsoft.Resources/resourceGroups@2023-07-01&#39; = {<br>  name: resourceGroupName<br>  location: parLocation<br>}<br><br>@description(&#39;Creating Entra ID Group for SQL Administrators&#39;)<br>resource groupAdministrators &#39;Microsoft.Graph/groups@v1.0&#39; = {<br>  displayName: &#39;SQL Administrators&#39;<br>  mailEnabled: false<br>  mailNickname: &#39;sqladministrators&#39;<br>  securityEnabled: true<br>  uniqueName: &#39;sqladministrators&#39;<br>  members: [<br>    deployer().objectId<br>  ]<br>}<br><br>@description(&#39;Creating Entra ID Group for SQL Readers&#39;)<br>resource groupReaders &#39;Microsoft.Graph/groups@v1.0&#39; = {<br>  displayName: &#39;SQL Readers&#39;<br>  mailEnabled: false<br>  mailNickname: &#39;sqlreaders&#39;<br>  securityEnabled: true<br>  uniqueName: &#39;sqlreaders&#39;<br>}<br><br>@description(&#39;Deploying Azure SQL Server with Entra ID Authentication&#39;)<br>module server &#39;br/public:avm/res/sql/server:0.21.3&#39; = {<br>  params: {<br>    name: sqlServerName<br>    administrators: {<br>      azureADOnlyAuthentication: true<br>      login: groupAdministrators.displayName<br>      principalType: &#39;Group&#39;<br>      sid: groupAdministrators.id<br>    }<br>    location: parLocation<br>    databases: [<br>      {<br>        name: sqlDatabaseName<br>        availabilityZone: -1<br>        collation: &#39;SQL_Latin1_General_CP1_CI_AS&#39;<br>        maxSizeBytes: 53687091200<br>        zoneRedundant: false<br>        sku: {<br>          name: &#39;S1&#39;<br>          tier: &#39;Standard&#39;<br>        }<br>      }<br>    ]<br>  }<br>  scope: resourceGroup(resourceGroupName)<br>  dependsOn: [<br>    sqlResourceGroup<br>  ]<br>}<br><br></pre><p>Customize the code to align with your specific requirements, then execute it. You can do this by using: New-AzSubscriptionDeployment -Name deploymentName -Location canadacentral -TemplateFile .\main.bicep. After a few minutes, all the necessary resources will be deployed. 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*YlpT1f_5fBc5HsmeFHgR0A.png" /></figure><p>When checking Microsoft Entra ID, we can see that the SQL Administrators group has been created successfully, with me added as a member through the deployer().objectId function, which is exactly the expected behavior.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LxJ-jjEb75aqGbAy1Z1cnw.png" /></figure><p>We can also see that the SQL Administrators Microsoft Entra ID group has been configured as the Microsoft Entra administrator for the Azure SQL Server. 😍</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TImu1I6alhaL6DGY8COVqQ.png" /></figure><p>Now using the Query Editor we can access the Azure SQL Database since we have succesfully access to it using the Microsoft Entra Authentication.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W9_esc1TvlHpKCQ1ATjZIg.png" /></figure><p>What about the SQL Readers group? For this group, I chose to create the Microsoft Entra ID group as part of the Bicep deployment. However, I grant it access manually by using the following T-SQL statement to create the contained database user: CREATE USER [SQL Readers] FROM EXTERNAL PROVIDER;</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_HdE4TQatjAkRJhH5pl_oQ.png" /></figure><p>We can also grant the SQL Readers group the db_datareader database role by using the following T-SQL statement: ALTER ROLE db_datareader ADD MEMBER [SQL READERS];. From now on, any user who is added to the Microsoft Entra ID group SQL Readers can connect to the Azure SQL Database using SQL Server Management Studio, provided they have network access to the database. Because the group is a member of the db_datareader role, its members can read data from all user tables and views in the database.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*h0LewX4JRwD1ACrB15Bx1Q.png" /></figure><p>From this point, you know how to deploy an Azure SQL environment by using Azure Bicep and securely grant users access to Azure SQL databases through Microsoft Entra ID authentication. By adopting Infrastructure as Code, you can build repeatable, scalable, and consistent Azure SQL environments while minimizing manual configuration, reducing deployment time, and improving security. The Azure Bicep code is available in my GitHub repository: <a href="https://github.com/brianveldman/azure-bicep/tree/main/04-Compute-Containers/Azure%20Virtual%20Desktop/Session%20Host%20Config">GitHub — brianveldman/azure-bicep</a>. Feel free to star the repository and clap for this story. That’s all for today. I’d love to hear your feedback, and I look forward to our next session. Until then, take care. ⭐️</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d0bc5d01875d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoft/configuring-microsoft-entra-id-authentication-for-azure-sql-database-using-azure-bicep-d0bc5d01875d">Configuring Microsoft Entra ID Authentication for Azure SQL Database using Azure Bicep</a> was originally published in <a href="https://medium.com/microsoft">Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From Live Signals to Smarter Risk: Building a Company Brain on Microsoft Fabric]]></title>
            <link>https://medium.com/microsoft/from-live-signals-to-smarter-risk-building-a-company-brain-on-microsoft-fabric-c5eb14548790?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/c5eb14548790</guid>
            <category><![CDATA[data-engineering]]></category>
            <category><![CDATA[microsoft-fabric]]></category>
            <category><![CDATA[realtime-analytics]]></category>
            <category><![CDATA[ontology]]></category>
            <category><![CDATA[ai-agent]]></category>
            <dc:creator><![CDATA[Dori Rabin]]></dc:creator>
            <pubDate>Thu, 16 Jul 2026 15:18:31 GMT</pubDate>
            <atom:updated>2026-07-16T15:18:30.589Z</atom:updated>
            <content:encoded><![CDATA[<h4>How Microsoft Fabric turns live maritime signals into agentic risk intelligence for real-time decisions.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W0HcU1YoB5LCGSgMIt4Itw.png" /></figure><p>A vessel is crossing the Strait of Hormuz. Its AIS signal updates in real time. A few minutes later, the vessel enters a high-risk zone.</p><p>For a maritime insurer, that single movement can trigger a chain of business questions:</p><p>Is the vessel still covered?<br>Does the policy include a war-risk exclusion?<br>Is there a warranty breach?<br>Which company operates the vessel?<br>What cargo is onboard?<br>What is the financial exposure right now?</p><p>Traditionally, answering those questions requires people to stitch together multiple systems: live vessel telemetry, geospatial boundaries, policy contracts, customer and cargo data, dashboards, and operational alerts.</p><p>This is exactly the kind of problem where enterprise AI needs more than retrieval. It needs business context.</p><p>In this post, I’ll show how I built a maritime risk “Company Brain” on Microsoft Fabric: an ontology-driven AI experience that connects live operational signals, semantic business relationships, and trusted policy documents so a <a href="https://learn.microsoft.com/en-us/fabric/data-science/concept-data-agent">Fabric Data Agent</a> can answer risk questions in real time.</p><h3>The disconnect between dynamic risk and static rules</h3><p>Maritime insurance risk is constantly changing. A vessel’s location, speed, route, AIS status, nearby weather, cargo, and geopolitical exposure can all shift while the policy language governing that risk remains locked inside static PDF or Word documents.</p><p>That creates a practical gap for underwriters and risk analysts.</p><p>They may have the data, but the meaning is scattered across different systems:</p><p>- live AIS telemetry<br>- geospatial risk boundaries<br>- policy contracts and warranty clauses<br>- vessel, company, cargo, and policy master data<br>- analytical dashboards and operational alerts</p><p>Each system can answer part of the question. None of them, on its own, can answer the business question that matters:</p><p>Is this vessel exposed right now, what does the policy say, and what should we do about it?</p><p>That is the gap this demo is designed to close.</p><h3>The solution: a geospatial Company Brain</h3><p>The core idea behind the demo is simple: the AI agent should not guess, and it should not treat every question as a document search problem.</p><p>Instead, it should understand which source of knowledge is responsible for each part of the answer.</p><p>In this solution, Microsoft Fabric becomes the foundation for a maritime risk Company Brain: a connected intelligence layer that combines live vessel state, geospatial risk context, business relationships, and trusted policy language.</p><p>The result is an AI experience that can answer business questions such as:</p><p>- Where is this vessel right now?<br>- Is it inside a high-risk zone?<br>- Which company operates it?<br>- What cargo is it carrying?<br>- Which policy applies?<br>- What does the policy say about this situation?<br>- Is there a coverage issue or warranty breach?<br>- What action should the risk team take?</p><p>That is the shift: from a dashboard that shows live data to an agent that explains what live data means for the business.</p><h3>High-level architecture</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zognBoiycm5jAGZrwWgUDw.jpeg" /><figcaption>End-to-end architecture for the maritime risk Company Brain, built with Microsoft Fabric and Azure AI Search.</figcaption></figure><p>End-to-end architecture for the maritime risk Company Brain, built with Microsoft Fabric and Azure AI Search.</p><p>The architecture is centered on Microsoft Fabric, with Azure AI Search connected as the external knowledge retrieval layer for policy documents.</p><p>At a high level, the flow works like this:</p><p>1. Live AIS telemetry is received from <a href="https://aisstream.io/">AisStream.io</a> and published into <a href="https://learn.microsoft.com/en-us/fabric/real-time-intelligence/event-streams/overview">Fabric Eventstream</a>.<br>2. <a href="https://learn.microsoft.com/en-us/fabric/real-time-intelligence/eventhouse">Eventhouse</a> stores the real-time vessel stream and uses KQL functions, <a href="https://learn.microsoft.com/en-us/kusto/management/update-policy?view=microsoft-fabric">update policies</a>, and <a href="https://learn.microsoft.com/en-us/kusto/management/materialized-views/materialized-view-overview?view=microsoft-fabric">materialized views</a> to enrich each position with geospatial risk context.<br>3. <a href="https://learn.microsoft.com/en-us/fabric/data-engineering/lakehouse-overview">Lakehouse</a> stores the business master data: vessels, companies, cargo, policies, and maritime risk zones.<br>4. GeoJSON risk-zone files define polygons such as Red Zone and Yellow Zone boundaries. These are transformed into structured tables that Eventhouse can use for geospatial enrichment.<br>5. Power BI semantic model and <a href="https://learn.microsoft.com/en-us/fabric/iq/ontology/overview">Fabric ontology</a> describe the business relationships between vessels, operators, cargo, policies, and live vessel position.<br>6. Azure AI Search indexes policy documents so the agent can retrieve coverage, exclusion, warranty, deductible, and war-risk language.<br>7. <a href="https://learn.microsoft.com/en-us/fabric/data-science/concept-data-agent">Fabric Data Agent</a> orchestrates the answer by routing each part of the question to the right source.<br>8. <a href="https://learn.microsoft.com/en-us/fabric/real-time-intelligence/map/create-map">Fabric Map</a> and Activator provide the visual and operational layers: live geospatial monitoring and alerting when a vessel enters a critical zone.</p><p>The key design choice is the vessel entity. The vessel, identified by MMSI, becomes the bridge between the operational world and the business world. Its latest position comes from Eventhouse, while its operator, cargo, policy, and coverage context come from the semantic model and ontology.</p><p>That lets the Data Agent answer questions that require both real-time state and business meaning.</p><h3>How the solution works</h3><p>After the architecture is in place, the implementation follows a simple flow: ingest live vessel telemetry, enrich it with geospatial risk context, connect it to business entities, and ground policy answers in indexed documents.</p><p>The live vessel data comes from AisStream.io, which provides a high-frequency feed of real-world AIS telemetry broadcast by ships across the world’s oceans. Each vessel is identified by an MMSI, or Maritime Mobile Service Identity: a unique 9-digit identifier that works like a digital license plate for a ship. In this solution, MMSI is the key that connects live telemetry in Eventhouse to the vessel entity in the ontology.</p><p>A Fabric notebook connects via WebSocket to AisStream.io and publishes live AIS events into Fabric Eventstream. Eventstream lands the telemetry in Eventhouse, where the raw maritimeAIS table stores vessel position, speed, heading, MMSI, ship name, and ingestion time.</p><p>Inside Eventhouse, KQL functions enrich each incoming position with geospatial risk context. The solution evaluates whether a vessel is inside a defined polygon using geo_point_in_polygon, then adds fields such as IsInZone, ZoneName, RiskLevel, and PremiumMultiplier. The enriched stream is stored in maritimeAIS_Enriched.</p><p>To make current-state questions fast and reliable, the solution creates the LatestShipPositionsEnriched materialized view. This view keeps only the most recent enriched position for each vessel, keyed by MMSI.</p><p>In parallel, the Lakehouse stores the business master data: vessels, companies, cargo, policies, and maritime risk zones. The risk zones are defined as GeoJSON files, transformed into a structured maritimezones table, and used by Eventhouse for geospatial enrichment.</p><p>The semantic model and Fabric ontology then connect the vessel to the business context around it: operator, cargo, policy, and latest live position.</p><p>Finally, policy documents are indexed in Azure AI Search so the Data Agent can retrieve relevant language about coverage, exclusions, warranties, deductibles, and war-risk conditions.</p><p>Together, these components allow the agent to move from a live vessel position to a business-level risk answer: where the vessel is, whether it is inside a risk zone, who operates it, what cargo it carries, which policy applies, and what the policy says about the current situation.</p><h3>Why Ontology matters</h3><p>One of the most important lessons from this demo is that enterprise AI needs more than retrieval.</p><p>RAG is powerful, but document search alone does not know which document matters. A policy clause may look relevant, but the agent still needs to know which policy belongs to which vessel, who operates that vessel, what cargo it carries, and whether the vessel is currently inside a risk zone.</p><p>That is where the ontology becomes critical.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yZPglL2kq6UbagD7Bs_DHw.png" /><figcaption>Fabric ontology overview, with the vessel as the central entity connecting companies, cargo, policies, and live operational context.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BTNnrgo3mGWTYH3acCkqHg.png" /><figcaption>A focused ontology graph showing how simulated vessels are linked to their operator, cargo, and insurance policy.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MhmUSq-NabtePY-iVZyTwQ.png" /><figcaption>Expanded ontology graph across the fleet, making entity relationships visible and queryable through the Fabric ontology experience.</figcaption></figure><p>In this architecture, the vessel is the central business entity. It connects the real-time operational world to the business and contractual world:</p><p>- latest vessel position from Eventhouse<br>- operator from the company master data<br>- cargo from the cargo master data<br>- policy from the insurance master data<br>- risk-zone status from geospatial enrichment</p><p>For example, if a user asks:</p><p>Is EAST_SIMULATED_TANKER_02 covered while crossing the Red Zone?</p><p>The agent should not start by searching all documents. It should reason through the business graph:</p><p>1. Find the vessel’s latest location in Eventhouse.<br>2. Check whether IsInZone is true and identify the RiskLevel.<br>3. Resolve the vessel to its company, cargo, and policy through the ontology.<br>4. Retrieve the relevant policy clauses from Azure AI Search.<br>5. Synthesize a grounded answer.</p><p>This is the difference between an AI assistant that can search and an AI agent that can understand context.</p><h3>Building the Data Agent</h3><p>The Fabric Data Agent is the orchestration layer for the experience.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BtnDA7O8IKdEfz92sc1gSg.png" /><figcaption>Fabric Data Agent answering a coverage question by combining Eventhouse telemetry, ontology context, and policy clauses from Azure AI Search.</figcaption></figure><p>In this demo, the agent is grounded in three complementary sources of knowledge:<br>- Eventhouse answers live operational questions: where the vessel is, whether it is inside a risk zone, and what the current risk state is.<br>- Fabric ontology and semantic model answer business-context questions: who operates the vessel, what cargo it carries, and which policy applies.<br>- Azure AI Search answers policy-evidence questions: what the insurance documents say about coverage, exclusions, warranties, deductibles, and war-risk conditions.</p><p>If the user asks where a vessel is, the agent should use Eventhouse.<br>If the user asks who owns a vessel or which policy applies, it should use the ontology.<br>If the user asks whether something is covered, excluded, or subject to a deductible, it should use Azure AI Search.<br>For complex questions, it should chain all three.</p><p>For example:</p><p>Is MV Ocean Voyager covered for a drone strike right now?</p><p>The expected reasoning path is:</p><p>1. Query LatestShipPositionsEnriched to find the vessel’s current location and zone status.<br>2. Use the ontology to find the policy linked to that vessel.<br>3. Search the policy index for drone strike, war exclusion, and high-risk zone language.<br>4. Return a grounded answer that cites both the live zone and the relevant contract clause.</p><p>The important point is that the agent is not inventing geospatial boundaries or legal interpretations. It is grounded in the live KQL materialized view, the ontology, and the indexed policy documents.</p><h3>Real-time risk in action</h3><p>For the demo, I used both real AIS data and simulated vessels.</p><p>The real AIS stream demonstrates live ingestion into Eventhouse. The simulation notebooks create controlled vessel itineraries that intentionally cross defined risk zones, which makes it easier to demonstrate how the risk state changes over time.</p><p>Two simulated vessels are included:</p><p>- SIMULATED_TANKER_01<br>- EAST_SIMULATED_TANKER_02</p><p>Each simulated vessel is enriched with demo insurance context such as company, cargo, hull value, and policy ID. One vessel is associated with a Hull &amp; Machinery policy, while another is associated with a War Risk policy.</p><p>As the simulated vessels move through the Strait of Hormuz scenario, the Data Agent’s answers change.</p><p>When a vessel is outside a risk zone, the agent can report standard coverage and no active breach. When the same vessel enters the Red Zone, the agent can flag elevated exposure, identify the critical zone, apply the premium multiplier, retrieve the relevant policy language, and explain the potential warranty or coverage impact.</p><p>This is the key experience: the same business question receives a different grounded answer because the operational reality changed in real time.</p><p>That is what makes the pattern powerful. The agent is not just answering from static knowledge; it is reasoning over the current state of the business.</p><h3>Visualizing live maritime risk with the Fabric Map item</h3><p>The Fabric Map item provides the spatial operating picture for the demo.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K_1Wh78kARgsN7_zc9HYQA.png" /><figcaption>Fabric Map visualizing vessel positions and maritime risk-zone polygons over a satellite-style map of the Strait of Hormuz.</figcaption></figure><p>While the Data Agent answers natural-language business questions, the map lets users see the same risk scenario visually: live vessels moving across geographic boundaries, risk-zone polygons, and changing exposure over time.</p><p>In this solution, the map brings together three layers:</p><p>- live vessel positions from Eventhouse<br>- maritime risk-zone polygons from Lakehouse GeoJSON data<br>- business context from the ontology, where each vessel connects to operator, cargo, policy, and current location</p><p>This is especially useful for real-time risk monitoring. An underwriter can inspect vessels approaching a high-risk polygon, filter by operator or cargo type, zoom into a corridor such as the Strait of Hormuz, and then ask the Data Agent a grounded follow-up question about coverage, warranties, or financial exposure.</p><p>In other words, Fabric Map provides the spatial view, while the ontology and Data Agent provide the business meaning behind what the user sees.</p><h3>From dashboard to decision</h3><p>Dashboards are still valuable. They show what is happening.</p><p>But the Data Agent adds a different interaction model. It helps users ask what the situation means.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sbHOpJ37MwunafcTi06CBA.png" /><figcaption>Natural-language risk analysis and geospatial exploration side by side: the Data Agent explains the risk while the Map shows where it happens.</figcaption></figure><p>A dashboard can show that a vessel is in a particular location. An ontology-driven agent can connect that location to the vessel’s operator, cargo, policy, current risk zone, and relevant contractual language.</p><p>That distinction matters for underwriters and risk teams. They do not only need to see that something happened; they need to understand whether it creates a coverage issue, whether the cargo changes the severity, whether the operator has a high-risk profile, and whether the policy includes a relevant exclusion or warranty condition.</p><p>With the ontology-driven approach, the agent can connect those dots and turn live telemetry into a business-level risk explanation.</p><h3>Adding operational alerts with Activator</h3><p>The solution also includes an Activator scenario, represented in the repository as a Reflex item called RedAlertActivator.</p><p>This adds an operational layer to the pattern. Once live data is enriched with geospatial and business meaning, it can trigger action rather than only support analysis.</p><p>For example, when a vessel enters a critical zone, the system can move beyond passive monitoring and activate an alerting flow.</p><p>That creates a practical enterprise pattern:</p><p>1. Eventstream ingests live data.<br>2. Eventhouse enriches the data in real time.<br>3. Materialized views expose the latest risk state.<br>4. Power BI and Fabric Map visualize the fleet.<br>5. Data Agent explains the business meaning.<br>6. Activator triggers operational action.</p><p>This is where the Company Brain becomes more than a question-answering interface. It becomes part of the operating model.</p><h3>Example questions for the Data Agent</h3><p>Here are some of the prompts I used to demonstrate the solution:</p><blockquote>Where is SIMULATED_TANKER_01 right now, and is it in a risk zone?</blockquote><blockquote>What is the total risk assessment for EAST_SIMULATED_TANKER_02?</blockquote><blockquote>Is this vessel in breach of any policy warranty?</blockquote><blockquote>Which of my ships are currently inside a high-risk zone?</blockquote><blockquote>What does the policy say about war-risk zones for this vessel?</blockquote><blockquote>Who operates this vessel, what cargo is it carrying, and which policy applies?</blockquote><p>These prompts demonstrate different agent behaviors.</p><p>Some are pure live telemetry questions. Some are ontology traversal questions. Some are policy retrieval questions. The most interesting ones require the agent to orchestrate all three.</p><h3>What I learned building it</h3><p>The biggest learning from this demo is that the value of enterprise AI does not come only from the model.</p><p>It comes from grounding the model in the right architecture.</p><p>A strong enterprise AI architecture needs:</p><h3>Live operational context</h3><p>For this demo, that context came from AIS telemetry streaming through Eventstream into Eventhouse.</p><h3>Semantic business context</h3><p>The ontology gave the AI a way to understand relationships between vessels, companies, cargo, policies, and zones.</p><h3>Trusted knowledge</h3><p>Azure AI Search gave the agent access to policy documents and legal clauses without forcing the user to manually read through dense contracts.</p><h3>Clear routing and orchestration</h3><p>The Data Agent needed explicit instructions about when to use Eventhouse, when to use the ontology, and when to use AI Search.</p><h3>Real-time state</h3><p>The LatestShipPositionsEnriched materialized view was essential because risk assessment depends on the latest vessel position, not historical telemetry.</p><p>Together, these pieces create something much more useful than a generic chatbot.</p><p>They create an AI agent that can reason over the business.</p><h3>Why this pattern matters</h3><p>Although this demo focuses on maritime insurance, the pattern applies to many industries.</p><p>In manufacturing, the central entity might be a machine or production line.</p><p>In healthcare, it might be a patient journey.</p><p>In retail, it might be a product, supplier, or store.</p><p>In energy, it might be an asset, grid node, or maintenance event.</p><p>The common pattern is the same:</p><ol><li>Capture live operational signals.</li><li>Enrich them with domain-specific logic.</li><li>Model business entities and relationships.</li><li>Ground the AI in trusted documents.</li><li>Expose the experience through a natural-language agent.</li><li>Trigger alerts or actions when business conditions change.</li></ol><p>That is the essence of the Company Brain.</p><p>It is not just an AI assistant connected to data. It is an AI layer that understands how the business is connected.</p><h3>Final thoughts</h3><p>The Fabric IQ demo at the Microsoft AI Tour was a great opportunity for me to show how Microsoft Fabric can bring together real-time analytics, semantic modeling, ontology, document intelligence, and AI agents into a single architecture.</p><p>The most exciting part is the shift in user experience.</p><p>Instead of asking analysts to manually inspect telemetry, dashboards, policies, and risk rules, we can let them ask business questions directly:</p><blockquote>“Which vessels are exposed right now, why, and what does the policy say?”</blockquote><p>That is the promise of ontology-driven AI.</p><p>When your data platform understands your business entities, your AI agent can do more than retrieve information. It can reason across live events, business relationships, and trusted knowledge.</p><p>That is how we start building the Company Brain.</p><h3>Resources</h3><p>The full demo repository is available here:</p><p><a href="https://github.com/dorirabin/fabricdemo/tree/fabriciq-maritimedemo">https://github.com/dorirabin/fabricdemo/tree/fabriciq-maritimedemo</a></p><p>The repo can be automatically deployed in your Fabric Workspace using the <a href="https://microsoft.github.io/fabric-cicd/latest/">fabric cicd </a>python library <br>The full demo repository includes the Fabric assets, notebooks, ontology, Data Agent configuration, sample policy documents, reports, maps, and Activator scenario used to build the solution.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c5eb14548790" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoft/from-live-signals-to-smarter-risk-building-a-company-brain-on-microsoft-fabric-c5eb14548790">From Live Signals to Smarter Risk: Building a Company Brain on Microsoft Fabric</a> was originally published in <a href="https://medium.com/microsoft">Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Monitoring GitHub Copilot at Scale with OpenTelemetry (OTLP) and Grafana]]></title>
            <link>https://medium.com/microsoft/monitoring-github-copilot-at-scale-with-opentelemetry-otlp-and-grafana-6d011279e766?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/6d011279e766</guid>
            <dc:creator><![CDATA[Lior Yantovski]]></dc:creator>
            <pubDate>Thu, 16 Jul 2026 15:18:14 GMT</pubDate>
            <atom:updated>2026-07-16T15:18:13.184Z</atom:updated>
            <content:encoded><![CDATA[<p><em>How to track AI adoption, LLM latency, token usage, and costs across your organization using native OTel instrumentation and Grafana dashboards.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wo1smT6f2ZYZ5SOKk2cXsA.png" /></figure><p>As organizations roll out AI coding assistants like GitHub Copilot, engineering leaders quickly run into a blind spot:</p><p><strong>How do we actually measure adoption, performance, and cost efficiency?</strong></p><p>Thanks to recent enterprise capabilities, GitHub Copilot natively supports OpenTelemetry (OTLP) export for client apps (like VS Code and the Copilot CLI). This means you can funnel telemetry directly to an OpenTelemetry Collector and visualize everything from token consumption to response latency.</p><p>Depending on your organization’s compliance, scale, and infrastructure goals, there are three primary paths to route this data. This guide provides clean, production-ready configurations for each approach.</p><p>Link to repository and official documentation on the bottom of this article.</p><h3>The Architecture at a Glance</h3><p>The setup relies on a standard push observability pattern:</p><pre>[ Developer Machines ] ──(OTLP/HTTP)──&gt; [ OTel Collector ] ──&gt; [ Observability Backend ] ──&gt; [ Grafana ]<br>  - VS Code Extension                                            - Local: Prometheus / Tempo<br>  - Copilot CLI                                                  - Azure: Azure Monitor / App Insights + OTLP support</pre><ul><li><strong>The Clients:</strong> VS Code and CLI capture runtime metrics (input/output tokens, time-to-first-token, exceptions).</li><li><strong>The Bridge:</strong> An OpenTelemetry Collector-Contrib deployment acts as the central router, parsing metrics, handling authentication, and injecting user metadata.</li></ul><h3>Step 1: Enable OTel on the Client</h3><p>To force the GitHub Copilot extension to emit telemetry, developers (or platform teams using enterprise-managed settings) need to configure their client settings.</p><p>Add the following to your VS Code settings.json:</p><pre>{<br>  &quot;github.copilot.chat.otel.enabled&quot;: true,<br>  &quot;github.copilot.chat.otel.otlpEndpoint&quot;: &quot;http://localhost:4318&quot;,<br>  &quot;github.copilot.chat.otel.exporterType&quot;: &quot;otlp-http&quot;,<br>  &quot;github.copilot.chat.otel.captureContent&quot;: false<br>}</pre><p><strong>Security Note:</strong> Keep captureContent set to false in production to ensure actual prompt/response code snippets are not bundled into the telemetry attributes.</p><h3>Step 2: Choose Your Collector Pipeline</h3><p>Here are the three distinct configuration options depending on your hosting environment.</p><h3>Option A: The Local Validation Stack</h3><p>For quick, self-contained local testing and evaluation, route your telemetry straight into local Prometheus and Tempo instances.</p><p>Otel Collector configuration YAML with local Tempo instance:</p><pre>receivers:<br>  otlp:<br>    protocols:<br>      http:<br>        endpoint: 0.0.0.0:4318<br>      grpc:<br>        endpoint: 0.0.0.0:4317<br><br>processors:<br>  batch:<br>    timeout: 5s<br>    send_batch_size: 1024<br><br>exporters:<br>  prometheus:<br>    endpoint: &quot;0.0.0.0:8889&quot;<br>  otlp/tempo:<br>    endpoint: &quot;tempo:4317&quot;<br>    tls:<br>      insecure: true<br><br>service:<br>  pipelines:<br>    metrics:<br>      receivers: [otlp]<br>      processors: [batch]<br>      exporters: [prometheus]<br>    traces:<br>      receivers: [otlp]<br>      processors: [batch]<br>      exporters: [otlp/tempo]</pre><h3>Option B: Route to Application Insights via Connection String</h3><p>This is the standard, generally available configuration. The Collector leverages the official azuremonitor exporter to ship telemetry directly to your Application Insights workspace using its unique connection string.</p><p>Otel Collector configuration YAML with azuremonitorexporter connected to Application Insights instance:</p><pre>receivers:<br>  otlp:<br>    protocols:<br>      http:<br>        endpoint: 0.0.0.0:4318<br>      grpc:<br>        endpoint: 0.0.0.0:4317<br><br>processors:<br>  batch:<br>    timeout: 5s<br>    send_batch_size: 1024<br><br>exporters:<br>  azuremonitor:<br>    connection_string: &quot;InstrumentationKey=&lt;YOUR-KEY&gt;;IngestionEndpoint=https://&lt;region&gt;.in.applicationinsights.azure.com/;LiveEndpoint=https://&lt;region&gt;.livediagnostics.monitor.azure.com/&quot;<br><br>service:<br>  pipelines:<br>    metrics:<br>      receivers: [otlp]<br>      processors: [batch]<br>      exporters: [azuremonitor]<br>    traces:<br>      receivers: [otlp]<br>      processors: [batch]<br>      exporters: [azuremonitor]</pre><h3>Option C: Ingest OTLP Data into Azure Monitor with Entra ID Authentication</h3><p>This enterprise-grade setup targets Azure Monitor’s cloud native OTLP ingestion pipeline. By utilizing Microsoft Entra ID (azure_auth) to secure transport and custom processors to stamp individual developer identities onto each metric, you can route your logs, traces, and converted delta metrics securely over direct Azure endpoints.</p><p>Otel Collector configuration YAML with otlphttp/azuremonitor exporter connected to Application Insights instance and leveraging azure_auth extension:</p><pre>receivers:<br>  otlp:<br>    protocols:<br>      http:<br>        endpoint: 0.0.0.0:4318<br>      grpc:<br>        endpoint: 0.0.0.0:4317<br><br>processors:<br>  # Stamping specific user identifiers onto telemetry fields<br>  resource/user_identity:<br>    attributes:<br>      - key: enduser.id<br>        value: ${COPILOT_USER_EMAIL}<br>        action: upsert<br>      - key: github.copilot.user.email<br>        value: ${COPILOT_USER_EMAIL}<br>        action: upsert<br>        <br>  attributes/user_identity:<br>    actions:<br>      - key: enduser.id<br>        value: ${COPILOT_USER_EMAIL}<br>        action: upsert<br>      - key: github.copilot.user.email<br>        value: ${COPILOT_USER_EMAIL}<br>        action: upsert<br><br>  memory_limiter:<br>    check_interval: 1s<br>    limit_mib: 512<br>    spike_limit_mib: 128<br><br>  # Converts cumulative metrics to delta formats required by Azure Monitor<br>  cumulativetodelta:<br><br>  batch:<br>    timeout: 5s<br>    send_batch_size: 1024<br><br>extensions:<br>  health_check:<br>  azure_auth:<br>    use_default: true<br>    scopes:<br>      - https://monitor.azure.com/.default<br><br>exporters:<br>  otlphttp/azuremonitor:<br>    traces_endpoint: ${AZURE_MONITOR_TRACES_ENDPOINT}<br>    logs_endpoint: ${AZURE_MONITOR_LOGS_ENDPOINT}<br>    metrics_endpoint: ${AZURE_MONITOR_METRICS_ENDPOINT}<br>    auth:<br>      authenticator: azure_auth<br><br>service:<br>  extensions: [health_check, azure_auth]<br>  pipelines:<br>    traces:<br>      receivers: [otlp]<br>      processors: [resource/user_identity, attributes/user_identity, memory_limiter, batch]<br>      exporters: [otlphttp/azuremonitor]<br>    logs:<br>      receivers: [otlp]<br>      processors: [resource/user_identity, attributes/user_identity, memory_limiter, batch]<br>      exporters: [otlphttp/azuremonitor]<br>    metrics:<br>      receivers: [otlp]<br>      processors: [resource/user_identity, memory_limiter, cumulativetodelta, batch]<br>      exporters: [otlphttp/azuremonitor]</pre><p>Note: on Option B and C we enriched metadata with user info, and it will propagate to span attributes of our traces (as enduser.id).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*c_AO4x9tPLVwuCNffpDsKw.png" /></figure><h3>Step 3: Visualize with Grafana</h3><p>Once the telemetry starts landing in your designated backend, you can visualize the data in Grafana. If you run your stack on Azure (either via <strong>Option B</strong> or <strong>Option C</strong>), you can leverage <strong>Azure Managed Grafana</strong> to directly query Log Analytics workspaces or Application Insights endpoints.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*IT2NfUXLK74nAxdr" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Rm-D6A9Kgb7u3Fc2F5zEfw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dtEtcA1W4B28fDbLMDrE3g.png" /></figure><h3>Key Dashboards to Build:</h3><ol><li><strong>Token Efficiency:</strong> Track input vs. output tokens over time, broken down by model (e.g., GPT-4o vs. Claude 3.5 Sonnet).</li><li><strong>Model Latency:</strong> Analyze <strong>Time to First Token (TTFT)</strong> alongside overall response durations.</li><li><strong>Developer Engagement:</strong> Group active calls by the injected enduser.id or github.copilot.user.email attributes to map organizational usage.</li><li><strong>Reliability:</strong> Keep an eye on API throttling, rate limits, timeouts, or extension exceptions.</li></ol><h3>Summary &amp; Next Steps</h3><p>Setting this up ensures that your organization’s AI investment isn’t a black box. You gain immediate visibility into performance bottlenecking, developer adoption, and detailed LLM metrics.</p><p>For a complete working setup — including pre-packaged Docker Compose environments, ready-to-import Grafana dashboards, and deployment scripts — head over to the companion repository:</p><p>👉 <strong>GitHub Repository:</strong> <a href="https://www.google.com/search?q=https://github.com/lyantovski/github-copilot-otlp-grafana">lyantovski/github-copilot-otlp-grafana</a></p><p><strong>Important:</strong> While this guide provides the foundational blueprints for local and Azure-native pipelines, API endpoints, schema mappings, and authentication scopes (especially regarding Azure’s OTLP preview endpoints) are subject to change.</p><p>For advanced configurations, network hardening, or troubleshooting edge cases, always cross-reference your implementation with the <strong>official documentation.</strong></p><p>Microsoft and Github official docs reference:</p><p><a href="https://learn.microsoft.com/en-us/azure/managed-grafana/grafana-opentelemetry-app-insights">Monitor AI coding agents with Grafana | Microsoft Learn</a></p><p><a href="https://learn.microsoft.com/en-us/azure/azure-monitor/containers/opentelemetry-protocol-ingestion">Ingest OTLP Data into Azure Monitor with OTel Collector — Azure Monitor | Microsoft Learn</a></p><p><a href="https://learn.microsoft.com/en-us/azure/azure-monitor/containers/collect-use-observability-data">Collect and analyze OpenTelemetry data with Azure Monitor (Preview) — Azure Monitor | Microsoft Learn</a></p><p><a href="https://github.blog/changelog/2026-07-08-enterprise-managed-opentelemetry-export-for-vs-code-and-cli/">Enterprise-managed OpenTelemetry export for VS Code and CLI — GitHub Changelog</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6d011279e766" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoft/monitoring-github-copilot-at-scale-with-opentelemetry-otlp-and-grafana-6d011279e766">Monitoring GitHub Copilot at Scale with OpenTelemetry (OTLP) and Grafana</a> was originally published in <a href="https://medium.com/microsoft">Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using Azure API Management to obtain Anthropic Messages APIs logs]]></title>
            <link>https://medium.com/microsoft/using-azure-api-management-to-obtain-anthropic-messages-apis-logs-16ab6ad289b8?source=rss----8bec1183ada9---4</link>
            <guid isPermaLink="false">https://medium.com/p/16ab6ad289b8</guid>
            <category><![CDATA[ai-gateway]]></category>
            <category><![CDATA[azure]]></category>
            <category><![CDATA[api-management]]></category>
            <category><![CDATA[anthropic-claude]]></category>
            <dc:creator><![CDATA[Akihiro Nishikawa]]></dc:creator>
            <pubDate>Wed, 15 Jul 2026 18:56:21 GMT</pubDate>
            <atom:updated>2026-06-22T04:19:19.325Z</atom:updated>
            <content:encoded><![CDATA[<p>This entry is based on information current as at 16 June 2026. The details provided may differ from the actual situation due to future additions or changes to the functionality. And the original (in Japanese) is accessible via the following URL.</p><p><a href="https://logico-jp.dev/2026/06/16/retrieve-logs-and-token-usages-when-using-anthropic-messages-api-through-azure-api-management/">Azure API ManagementでAnthropic Messages APIのプロンプトログを取得する</a></p><h3>Query from a customer</h3><p>The client, who had enquired in the past, asked me about the following topic.</p><blockquote>I understand that Anthropic models are now available via Microsoft Foundry. If we were to deploy an Anthropic model as a backend service for API Management, would it be possible to collect logs and track token consumption? I understand that this is possible with OpenAI-compatible APIs, but I’d like to know the current status of support for the Native API.</blockquote><p><a href="https://medium.com/microsoftazure/fail-to-capture-prompt-logs-for-llm-apis-deployed-behind-azure-api-management-a607d6df44e5">Fail to capture prompt logs for LLM APIs deployed behind Azure API Management</a></p><p>It appears that the prevailing opinion is that, given the extended period since the models’ initial release, and their subsequent availability via Foundry, the necessary adjustments must have been made. It is true that the situation has changed, so it would be advisable to check.</p><h3>Supportability</h3><p>It is explicitly stated in the documentation that the Messages API of the Anthropic model is supported in API Management v2 as part of the AI Gateway feature of the same system.</p><blockquote><em>Use the AI gateway to manage a wide range of AI endpoints, including:<br></em><strong><em>Language model APIs</em></strong><em> that conform to one of the following API schemas:<br>- </em>OpenAI Chat Completions or Responses API<br>- Anthropic Messages API (currently supported in API Management v2 tiers)<br>- Google Vertex AI API (rebranded into Gemini Enterprise Agent Platform)</blockquote><p><a href="https://learn.microsoft.com/azure/api-management/genai-gateway-capabilities">AI gateway capabilities in Azure API Management</a></p><p>The term ‘Vertex AI API’ refers to the native Gemini inference API format that has been migrated to the Gemini Enterprise Agent Platform, rather than the full suite of models currently available on the Gemini Enterprise AI Platform.</p><p>While the feature appears to be operational from this document, this investigation aims to verify its functionality.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1023/1*LI9pZc2OSm5TEZdV1HYXgg.png" /></figure><h3>Environment</h3><p>I would like to confirm that the environment remains unchanged since the previous occasion. On this occasion, however, I opted for Haiku instead of Opus. All other conditions remain unchanged.</p><p><strong>APIM: Standard V2<br></strong>- This can also be achieved with other V2 SKUs<br>- Diagnostic settings are already configured</p><p><strong>LLM: Claude Haiku 4.5 (20251001)<br></strong>- Messages APIs are used.</p><p><a href="https://platform.claude.com/docs/en/api/messages">Messages - Claude API Reference</a></p><p>As before, since Anthropic has not published the OpenAPI Spec, I have manually registered the Messages APIs with APIM. The API key can be configured in either the ‘Backends’ or the ‘Policies’ section. Please be advised that the ‘Header key’ differs when configuring the API key.</p><p>This concludes the environmental setup.</p><h3>Let’s try it!</h3><p>For this project, I chose to utilise the following requests. Please note that I have sent one request with streaming enabled and another with streaming disabled (by changing &quot;stream&quot;: false in the request below, or by removing stream). As the primary objective is to verify the collection of logs, I did not conduct an evaluation of the output results.</p><pre><br>{<br>  &quot;model&quot;: &quot;claude-haiku-4-5-20251001&quot;,<br>  &quot;max_tokens&quot;: 64000,<br>  &quot;stream&quot;: true,<br>  &quot;system&quot;: &quot;You have an expertise in Azure architecture. Your responsibility is to articulate and elaborate queries and provide the best architecture following Azure Well-architected Framework.&quot;,<br>  &quot;messages&quot;: [<br>    {<br>      &quot;role&quot;: &quot;user&quot;,<br>      &quot;content&quot;: [<br>        {<br>          &quot;type&quot;: &quot;text&quot;,<br>          &quot;text&quot;: &quot;SharePoint OnlineからファイルをBoxに移送する手段として、一番コストが安い方法を提示して。&quot;<br>        }<br>      ]<br>    }<br>  ],<br>  &quot;thinking&quot;: {<br>    &quot;type&quot;: &quot;enabled&quot;,<br>    &quot;budget_tokens&quot;: 63999<br>  }<br>}</pre><h3>Verification</h3><p>In Log Analytics Workspace, I checked whether any logs had been recorded in ApiManagementGatewayLlmLog.</p><h4>When streaming is enabled</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1021/0*ncFfrZS-E5L21jxH" /></figure><h4>When streaming is disabled</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1022/0*ONuGgIrcA26JNEo4" /></figure><p>It is evident that in both cases, the logs and token consumption are being written to the log without any issues. When streaming is enabled, it is also evident that IsStreamCompletion is set to true.</p><h3>The follow-up enquiry arrives</h3><p>As always, the follow-up enquiry was received. I can understand why they would like to know.</p><blockquote>Could you kindly confirm whether token usage is logged in relation to Prompt Cache? It would be appreciated if the item could be included in the logs. However, should this not be possible, it would be satisfactory to retrieve it via custom metrics.</blockquote><p>The log snippet below, which is from approximately the third to the seventh line, shows cache-related token usage. If streaming is enabled, a message similar to the one below should be sent in the final delta. Their primary concern is whether this information can be verified in any way.</p><pre>&quot;usage&quot;: {<br>    &quot;input_tokens&quot;: 3,<br>    &quot;cache_creation_input_tokens&quot;: 184,<br>    &quot;cache_read_input_tokens&quot;: 10564,<br>    &quot;cache_creation&quot;: {<br>        &quot;ephemeral_5m_input_tokens&quot;: 184,<br>        &quot;ephemeral_1h_input_tokens&quot;: 0<br>    },<br>    &quot;output_tokens&quot;: 160,<br>    &quot;service_tier&quot;: &quot;standard&quot;,<br>    &quot;inference_geo&quot;: &quot;not_available&quot;<br>}</pre><h3>Verification</h3><h4>1. Does it appear in the logs?</h4><p>Unfortunately, the answer is no. As previously stated, ApiManagementGatewayLlmLog does not contain this field, therefore it is not stored in the log table (we hope this will be addressed in future updates).</p><h4>2. Can it be captured via custom metrics?</h4><p>The llm-emit-token-metric policy permits the transmission of custom metrics to Application Insights. However, the question remains as to whether token usage can be verified via the customMetrics table in Application Insights. The answer to this is ‘<em>some information is available</em>’. However, please note that certain details are missing, specifically cache_creation_input_tokens and related information.</p><h4>When streaming is enabled</h4><p>Please find below a summary of the contents of the table customMetrics. The data contained within the red rectangle illustrates the delta values as at 09:54:01 (UTC) on 17 June 2026.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1021/0*Gpm06TAoM-l-Eaap" /></figure><p>The following comparison reveals that cache_creation_input_tokens has not been retrieved, but cache_read_input_tokens has.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*f9XVzfeWetex76ClSK7gnA.png" /></figure><h4>When streaming is disabled</h4><p>Similarly, I checked this when streaming was disabled. Please find below a summary of the contents of the table customMetrics.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1022/0*EQ9ZQCXlaJeBGJo-" /></figure><p>The following details are provided in relation to token usage at 10:26:01 (UTC) on 17 June 2026.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*c3C2-diOW4XuwJnKXxjeiA.png" /></figure><p>Although the values for ephemeral_5m_input_tokens and ephemeral_1h_input_tokenswhich cache_creation_input_tokens consists of have not been captured, the rest remain unchanged and captured even when streaming was enabled.</p><h3>Please note that ...</h3><p>The llm-emit-token-metric policy is designed to send metrics each time an event occurs. However, it should be noted that the resolution of Application Insights is 60 seconds. Therefore, please be aware that Application Insights are only able to output data at intervals of at least 60 seconds, i.e. every minute. Consequently, if the same dimension is used, all metrics received within that 60-second period will be aggregated. To keep things simple, I have created a test application that cycles through each turn every 60 seconds to verify the behaviour.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=16ab6ad289b8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/microsoft/using-azure-api-management-to-obtain-anthropic-messages-apis-logs-16ab6ad289b8">Using Azure API Management to obtain Anthropic Messages APIs logs</a> was originally published in <a href="https://medium.com/microsoft">Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The NEW Bicep Like and Distinct Functions ✨]]></title>
            <link>https://medium.com/microsoft/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/microsoft/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/microsoft">Microsoft</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>