<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jino R Krishnan</title>
    <description>The latest articles on DEV Community by Jino R Krishnan (@jinkrish).</description>
    <link>https://dev.to/jinkrish</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1067699%2F0d8b84f1-fbeb-4973-a062-fa3efbf712ab.jpeg</url>
      <title>DEV Community: Jino R Krishnan</title>
      <link>https://dev.to/jinkrish</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jinkrish"/>
    <language>en</language>
    <item>
      <title>DNS Explained: How Your Browser Decodes Website Addresses</title>
      <dc:creator>Jino R Krishnan</dc:creator>
      <pubDate>Fri, 26 Jun 2026 12:25:46 +0000</pubDate>
      <link>https://dev.to/jinkrish/dns-explained-how-your-browser-decodes-website-addresses-2bcm</link>
      <guid>https://dev.to/jinkrish/dns-explained-how-your-browser-decodes-website-addresses-2bcm</guid>
      <description>&lt;p&gt;You type &lt;code&gt;www.google.com&lt;/code&gt; into your browser and hit Enter. The page loads in under a second.&lt;/p&gt;

&lt;p&gt;But stop and think about what just happened. Your browser didn't &lt;em&gt;know&lt;/em&gt; where Google lives on the internet. It had to ask. And in that fraction of a second, a surprisingly elegant chain of lookups took place behind the scenes.&lt;/p&gt;

&lt;p&gt;That system is called &lt;strong&gt;DNS&lt;/strong&gt; — the Domain Name System. Think of it as the internet's phonebook: it translates human-friendly names like &lt;code&gt;www.google.com&lt;/code&gt; into machine-friendly IP addresses like &lt;code&gt;142.250.80.46&lt;/code&gt;. Without it, you'd have to memorise numbers to visit any website.&lt;/p&gt;

&lt;p&gt;Let's walk through exactly what happens, step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: You Type a URL — But What Does It Mean?
&lt;/h2&gt;

&lt;p&gt;When you type &lt;code&gt;www.bing.com&lt;/code&gt;, you're entering a &lt;strong&gt;domain name&lt;/strong&gt;. Domain names have a structure — and reading them right-to-left tells you a lot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;www . bing . com
 │      │     │
 │      │     └── Top-Level Domain (TLD): category or country
 │      └──────── Second-Level Domain (SLD): the brand/org name
 └─────────────── Subdomain: a section of the site (optional)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some real examples:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;TLD&lt;/th&gt;
&lt;th&gt;SLD&lt;/th&gt;
&lt;th&gt;Subdomain&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;www.bing.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bing&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;www&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;news.bbc.co.uk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.uk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bbc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;news&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs.github.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;github&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docs&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;TLDs indicate the type or origin of a site — &lt;code&gt;.com&lt;/code&gt; for commercial, &lt;code&gt;.edu&lt;/code&gt; for education, &lt;code&gt;.in&lt;/code&gt; for India, and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Your Browser Checks Locally First
&lt;/h2&gt;

&lt;p&gt;Before going anywhere on the internet, your browser does a quick local check — two of them, actually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Browser cache&lt;/strong&gt;&lt;br&gt;
Modern browsers cache DNS results from previous lookups. If you visited &lt;code&gt;bing.com&lt;/code&gt; five minutes ago, the browser already knows its IP and skips the entire lookup process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The &lt;code&gt;hosts&lt;/code&gt; file&lt;/strong&gt;&lt;br&gt;
Your operating system has a plain text file that maps domain names to IPs manually. On most systems it lives at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows:&lt;/strong&gt; &lt;code&gt;C:\Windows\System32\drivers\etc\hosts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mac/Linux:&lt;/strong&gt; &lt;code&gt;/etc/hosts&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="m"&gt;127&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;    &lt;span class="n"&gt;localhost&lt;/span&gt;
&lt;span class="m"&gt;192&lt;/span&gt;.&lt;span class="m"&gt;168&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="n"&gt;mydevserver&lt;/span&gt;.&lt;span class="n"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Developers use this all the time for local testing — mapping a production domain name to a local IP to test before going live.&lt;/p&gt;

&lt;p&gt;If neither cache nor hosts has an answer, the real DNS lookup begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Your OS Asks a Recursive Resolver
&lt;/h2&gt;

&lt;p&gt;Your OS passes the query to a &lt;strong&gt;Recursive Resolver&lt;/strong&gt; (sometimes called a Recursive DNS server). This is typically provided by your ISP, but you can override it with public ones:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;DNS Address&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8.8.8.8&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1.1.1.1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenDNS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;208.67.222.222&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Switching to &lt;code&gt;1.1.1.1&lt;/code&gt; (Cloudflare) or &lt;code&gt;8.8.8.8&lt;/code&gt; (Google) can noticeably speed up DNS resolution and improve privacy over your ISP's default resolver.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Recursive Resolver is the workhorse. It does all the legwork of finding the answer so your device doesn't have to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: The Resolver Walks the DNS Hierarchy
&lt;/h2&gt;

&lt;p&gt;If the Recursive Resolver doesn't have the answer cached, it begins a top-down walk through the DNS hierarchy. There are three layers:&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1 — Root Servers
&lt;/h3&gt;

&lt;p&gt;The resolver first contacts one of the &lt;strong&gt;13 root server clusters&lt;/strong&gt; distributed worldwide (operated by IANA, Verisign, NASA, and others). These servers don't know the final answer — they just know &lt;em&gt;who to ask next&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.iana.org/domains/root/servers" rel="noopener noreferrer"&gt;Full list of root servers → iana.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The root server responds: &lt;em&gt;"For &lt;code&gt;.com&lt;/code&gt; domains, go talk to this TLD server."&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2 — TLD Servers
&lt;/h3&gt;

&lt;p&gt;The resolver contacts the &lt;strong&gt;TLD server&lt;/strong&gt; for &lt;code&gt;.com&lt;/code&gt;. Again, it doesn't have the final IP — but it knows which &lt;strong&gt;authoritative name server&lt;/strong&gt; is responsible for &lt;code&gt;bing.com&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.iana.org/domains/root/db/com.html" rel="noopener noreferrer"&gt;.com delegation data → iana.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Layer 3 — Authoritative Name Server
&lt;/h3&gt;

&lt;p&gt;Finally, the resolver reaches the &lt;strong&gt;Authoritative Name Server&lt;/strong&gt; for &lt;code&gt;bing.com&lt;/code&gt;. This server holds the actual DNS records for the domain — and it returns the IP address.&lt;/p&gt;

&lt;p&gt;The full journey looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Browser
    │
    ▼
Recursive Resolver  ──── checks cache ──► found? return it
    │ (cache miss)
    ▼
Root Server  ──────────────────────────► "ask the .com TLD server"
    │
    ▼
TLD Server (.com)  ────────────────────► "ask bing.com's name server"
    │
    ▼
Authoritative Name Server (bing.com)  ─► "the IP is 204.79.197.200"
    │
    ▼
Recursive Resolver caches the result
    │
    ▼
Your Browser connects to 204.79.197.200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Caching Saves Everyone Time
&lt;/h2&gt;

&lt;p&gt;Every response in that chain comes with a &lt;strong&gt;TTL (Time To Live)&lt;/strong&gt; — a number in seconds that tells resolvers how long to cache the answer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bing.com.   300   IN   A   204.79.197.200
               │
               └── TTL: cache this for 300 seconds (5 minutes)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the answer is cached at the Recursive Resolver level, subsequent queries from &lt;em&gt;anyone&lt;/em&gt; using that resolver skip the entire walk. This is why DNS is fast at scale even though the hierarchy seems deep.&lt;/p&gt;

&lt;p&gt;When a site's IP changes (e.g. migrating servers), admins lower the TTL beforehand so the old IP expires quickly everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Common DNS Record Types
&lt;/h2&gt;

&lt;p&gt;DNS isn't just about IP addresses. A domain can have multiple record types:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Record&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Domain → IPv4 address&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bing.com → 204.79.197.200&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AAAA&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Domain → IPv6 address&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bing.com → 2620:1ec:c11::200&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CNAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Alias to another domain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;www.bing.com → bing.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MX&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mail server for a domain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bing.com → mail.bing.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TXT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Arbitrary text (SPF, DMARC, verification)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"v=spf1 include:..."&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Name servers for the domain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bing.com → ns1.msft.net&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As a developer, you'll interact with all of these — especially &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;CNAME&lt;/code&gt;, &lt;code&gt;MX&lt;/code&gt;, and &lt;code&gt;TXT&lt;/code&gt; — whenever you deploy an app, configure email, or verify domain ownership.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Word on Modern DNS: DoH and DoT
&lt;/h2&gt;

&lt;p&gt;Traditional DNS queries travel in &lt;strong&gt;plain text&lt;/strong&gt; — anyone on the network (your ISP, a coffee shop router) can see every domain you resolve. Two modern protocols address this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DNS over HTTPS (DoH):&lt;/strong&gt; Wraps DNS queries in HTTPS, making them indistinguishable from regular web traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS over TLS (DoT):&lt;/strong&gt; Encrypts DNS on port 853&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both Chrome and Firefox support DoH natively. Cloudflare's &lt;code&gt;1.1.1.1&lt;/code&gt; and Google's &lt;code&gt;8.8.8.8&lt;/code&gt; support both. Worth enabling if privacy matters to your users or your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Full Picture
&lt;/h2&gt;

&lt;p&gt;Here's the complete DNS resolution flow in one view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. User types www.bing.com
2. Browser cache? → Hit: done. Miss: continue.
3. OS hosts file? → Hit: done. Miss: continue.
4. Recursive Resolver cache? → Hit: done. Miss: continue.
5. Root Server → points to .com TLD Server
6. TLD Server → points to bing.com Authoritative Server
7. Authoritative Server → returns 204.79.197.200
8. Resolver caches result (TTL)
9. Browser connects to 204.79.197.200
10. Page loads 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of this typically completes in &lt;strong&gt;20–120 milliseconds&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;DNS is one of those invisible foundations that the entire web sits on. As a developer you'll hit it constantly — debugging propagation delays after a deploy, setting up custom domains, configuring email records, or hardening your app's privacy with DoH.&lt;/p&gt;

&lt;p&gt;Understanding the hierarchy (Root → TLD → Authoritative) and the role of caching and TTLs takes a lot of the mystery out of those moments when "the DNS hasn't propagated yet."&lt;/p&gt;

&lt;p&gt;Next time you type a URL, you'll know exactly what's happening in those milliseconds. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;By Jino R Krishnan — Full Stack Developer&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>dns</category>
      <category>networking</category>
      <category>beginners</category>
    </item>
    <item>
      <title>From API to AI: Transform Your .NET + SQL App into a Conversational Web App Using NLWeb, GPT-4o, and the Microsoft Agent Framework</title>
      <dc:creator>Jino R Krishnan</dc:creator>
      <pubDate>Fri, 26 Jun 2026 12:04:58 +0000</pubDate>
      <link>https://dev.to/jinkrish/from-api-to-ai-transform-your-net-sql-app-into-a-conversational-web-app-using-nlweb-gpt-4o-4cnl</link>
      <guid>https://dev.to/jinkrish/from-api-to-ai-transform-your-net-sql-app-into-a-conversational-web-app-using-nlweb-gpt-4o-4cnl</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Updated for 2026&lt;/strong&gt; — covering NLWeb's evolution since Build 2025, the shift from Semantic Kernel to Microsoft Agent Framework, GPT-4o, and Cloudflare's managed NLWeb deployment path.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Natural language interfaces are no longer a novelty — they're the new baseline expectation. Users increasingly expect to &lt;em&gt;ask&lt;/em&gt; your app questions the same way they'd talk to a colleague. With Microsoft's &lt;strong&gt;NLWeb&lt;/strong&gt;, you can retrofit your existing .NET + SQL application with a conversational layer without rebuilding it from scratch. In this updated guide, we'll walk through the full process using the latest tooling available in mid-2026.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is NLWeb? (2026 Update)
&lt;/h2&gt;

&lt;p&gt;NLWeb is an open-source protocol from Microsoft, conceived by R.V. Guha (the creator of RSS, RDF, and Schema.org), that lets any web property respond to natural language queries directly — without a search engine acting as intermediary. Think of it as what HTML did for publishing: a universal, open standard that makes your site a first-class citizen of the emerging &lt;strong&gt;agentic web&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every NLWeb instance is also a &lt;strong&gt;Model Context Protocol (MCP) server&lt;/strong&gt;, exposing your content to AI agents via two key endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/ask&lt;/code&gt; — for human-facing conversational queries&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/mcp&lt;/code&gt; — for agent-to-agent discovery and tool calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since its announcement at Build 2025, the ecosystem has matured significantly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare&lt;/strong&gt; added native NLWeb support via its &lt;strong&gt;AutoRAG&lt;/strong&gt; infrastructure in early 2026, offering a fully managed deployment path&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microsoft&lt;/strong&gt; joined the MCP Steering Committee and contributed an updated authorization spec and MCP server registry design&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build 2026&lt;/strong&gt; featured NLWeb prominently in the Agents and Apps track, alongside .NET 11's new agentic web building blocks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NLWeb is technology-agnostic — it supports all major LLMs, vector databases, and operating systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Changed Since the Original Guide
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Original (May 2025)&lt;/th&gt;
&lt;th&gt;Updated (June 2026)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Model&lt;/td&gt;
&lt;td&gt;GPT-4&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;GPT-4o&lt;/strong&gt; (default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orchestration&lt;/td&gt;
&lt;td&gt;Semantic Kernel (experimental agents)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Microsoft Agent Framework (MAF)&lt;/strong&gt; — GA in Q2 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET Version&lt;/td&gt;
&lt;td&gt;ASP.NET Core (unspecified)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;.NET 11&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NLWeb Deployment&lt;/td&gt;
&lt;td&gt;Manual self-hosted only&lt;/td&gt;
&lt;td&gt;Manual &lt;strong&gt;or&lt;/strong&gt; Cloudflare AutoRAG (managed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embeddings&lt;/td&gt;
&lt;td&gt;&lt;code&gt;text-embedding-3-small&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;text-embedding-3-small&lt;/code&gt; / &lt;code&gt;text-embedding-3-large&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 └─► NLWeb UI (/ask endpoint)
      └─► ASP.NET Core (.NET 11) Controller
           └─► Microsoft Agent Framework
                ├─► GPT-4o (Azure OpenAI)
                ├─► Embedding + Vector DB (Azure AI Search / Qdrant)
                └─► SQL Server
                     └─► Schema.org JSON response back to NLWeb UI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;.NET 11 Web API project (ASP.NET Core)&lt;/li&gt;
&lt;li&gt;Microsoft SQL Server&lt;/li&gt;
&lt;li&gt;Node.js (for the NLWeb UI demo)&lt;/li&gt;
&lt;li&gt;Azure OpenAI access (GPT-4o + text-embedding-3-small)&lt;/li&gt;
&lt;li&gt;A vector database: &lt;strong&gt;Azure AI Search&lt;/strong&gt; (recommended), Qdrant, Pinecone, or Weaviate&lt;/li&gt;
&lt;li&gt;Docker (optional, for deployment)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step-by-Step Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Clone NLWeb
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/microsoft/NLWeb.git
&lt;span class="nb"&gt;cd &lt;/span&gt;NLWeb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key folders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;code/&lt;/code&gt; — Python reference implementation and &lt;code&gt;/ask&lt;/code&gt; endpoint logic&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;demo/&lt;/code&gt; — Embeddable frontend UI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docs/&lt;/code&gt; — MCP protocol and Schema.org response specs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Run the NLWeb UI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;demo
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This launches a local chat interface. Queries are POSTed to your backend's &lt;code&gt;/ask&lt;/code&gt; endpoint. You can also embed the UI snippet directly into any webpage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Understand the NLWeb Request/Response Contract
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Incoming request to your API:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What are the top-selling products this month?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected response (Schema.org JSON-LD):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ItemList"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"itemListElement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wireless Mouse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ergonomic wireless mouse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"offers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"29.99"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"priceCurrency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NLWeb renders this structured response as a conversational answer in the UI.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4: Install the Microsoft Agent Framework (MAF)
&lt;/h3&gt;

&lt;p&gt;MAF is the production-ready successor to Semantic Kernel's agent layer, reaching GA in Q2 2026. It merges the best of AutoGen and Semantic Kernel into a single, cleaner SDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package Microsoft.Extensions.AI
dotnet add package Microsoft.SemanticKernel
dotnet add package Microsoft.Agents.AI.OpenAI
dotnet add package Azure.AI.OpenAI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note for existing SK users:&lt;/strong&gt; Semantic Kernel v1.x is supported until at least one year after MAF GA. Your plugins and vector store integrations migrate cleanly — the mental model is identical, just with a cleaner API surface.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Step 5: Update Your .NET 11 API
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Define the Query Model
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NLWebQuery&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Query&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Create the Controller
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NLWebController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;INLWebAgentService&lt;/span&gt; &lt;span class="n"&gt;_agentService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;NLWebController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INLWebAgentService&lt;/span&gt; &lt;span class="n"&gt;agentService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_agentService&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agentService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ask"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ask&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;FromBody&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;NLWebQuery&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;schemaOrgResponse&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_agentService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProcessAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schemaOrgResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 6: Build the Agent Service with MAF
&lt;/h3&gt;

&lt;p&gt;This is where the 2026 approach differs significantly. Instead of manually chaining prompt → vector search → SQL, the Microsoft Agent Framework handles orchestration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.AI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Agents.AI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Azure.AI.OpenAI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Azure.Identity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NLWebAgentService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;INLWebAgentService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IChatClient&lt;/span&gt; &lt;span class="n"&gt;_chatClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IVectorSearchService&lt;/span&gt; &lt;span class="n"&gt;_vectorSearch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IProductRepository&lt;/span&gt; &lt;span class="n"&gt;_productRepo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;NLWebAgentService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;IChatClient&lt;/span&gt; &lt;span class="n"&gt;chatClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IVectorSearchService&lt;/span&gt; &lt;span class="n"&gt;vectorSearch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IProductRepository&lt;/span&gt; &lt;span class="n"&gt;productRepo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_chatClient&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chatClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_vectorSearch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vectorSearch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_productRepo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;productRepo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ProcessAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. Embed the query&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;relevantContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_vectorSearch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SearchAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 2. Build prompt with retrieved context&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;systemPrompt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"""
&lt;/span&gt;            &lt;span class="n"&gt;You&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;analyst&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;commerce&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
            &lt;span class="n"&gt;Based&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="n"&gt;below&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generate&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;SQL&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
            &lt;span class="n"&gt;Return&lt;/span&gt; &lt;span class="n"&gt;ONLY&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;SQL&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;explanation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

            &lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;relevantContext&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
            &lt;span class="s"&gt;""";
&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ChatMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ChatRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ChatRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="c1"&gt;// Add conversation history for contextual follow-up&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;prior&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ChatRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Assistant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prior&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="c1"&gt;// 3. Call GPT-4o via MAF&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_chatClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CompleteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// 4. Execute SQL&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_productRepo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecuteQueryAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 5. Return Schema.org JSON&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;FormatAsSchemaOrg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Register Services in Program.cs (.NET 11)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// MAF: Layer 1 - IChatClient (provider-agnostic)&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IChatClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AzureOpenAIClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"AzureOpenAI:Endpoint"&lt;/span&gt;&lt;span class="p"&gt;]!),&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DefaultAzureCredential&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetChatClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gpt-4o"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsIChatClient&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// Vector search (Azure AI Search recommended for .NET + enterprise)&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IVectorSearchService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AzureAISearchService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IProductRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SqlProductRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;INLWebAgentService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NLWebAgentService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 7: Prepare SQL Data for Vector Search
&lt;/h3&gt;

&lt;p&gt;Before your app can do semantic retrieval, you need to embed your SQL data and store it in your vector database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// One-time ingestion pipeline&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;IngestProductsAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Products&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Category&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (Category: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_embeddingClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetEmbeddingAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_vectorDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UpsertAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;VectorRecord&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;Vector&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SourceTable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Products"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Best practices for 2026:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;hybrid search&lt;/strong&gt; (keyword + semantic) in Azure AI Search for best recall&lt;/li&gt;
&lt;li&gt;Embed at the right granularity — row-level for products, paragraph-level for FAQs&lt;/li&gt;
&lt;li&gt;Store &lt;code&gt;SourceTable&lt;/code&gt; and &lt;code&gt;RowId&lt;/code&gt; in metadata for traceability and debugging&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 8: Format the Response as Schema.org
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="nf"&gt;FormatAsSchemaOrg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DataTable&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;@context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;@type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ItemList"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;itemListElement&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DataRow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;@type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Product"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;offers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;@type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Price"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;priceCurrency&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"USD"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 9: Test the Full Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Start your .NET API: &lt;code&gt;dotnet run&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Start the NLWeb UI: &lt;code&gt;npm start&lt;/code&gt; in the &lt;code&gt;demo/&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;Type: &lt;em&gt;"What are the top-selling products this month?"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Observe the full pipeline: query → embed → vector search → GPT-4o → SQL → Schema.org JSON → conversational answer in UI&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Bonus: Add Memory and Context Persistence
&lt;/h2&gt;

&lt;p&gt;For multi-turn conversations, persist chat history using Redis or SQL and pass it back with each request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Store turn history in Redis&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetStringAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"chat:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MAF handles the concept of a &lt;strong&gt;session/conversation thread&lt;/strong&gt; natively — no manual history wiring needed if you use its agent abstraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Alternative: Managed Deployment with Cloudflare AutoRAG
&lt;/h2&gt;

&lt;p&gt;If you don't want to manage the NLWeb infrastructure yourself, Cloudflare now offers a one-click managed path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Cloudflare Dashboard → AI → AI Search&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Create AI Search → Website&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;NLWeb Worker&lt;/strong&gt; — Cloudflare automatically deploys the &lt;code&gt;/ask&lt;/code&gt; and &lt;code&gt;/mcp&lt;/code&gt; endpoints&lt;/li&gt;
&lt;li&gt;Point the NLWeb UI to your Cloudflare Worker URL&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is ideal for teams that want NLWeb running in production without managing vector DB infrastructure or NLWeb server updates manually.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/nlweb" rel="noopener noreferrer"&gt;NLWeb GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/agent-framework/" rel="noopener noreferrer"&gt;Microsoft Agent Framework Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-semantic-kernel/" rel="noopener noreferrer"&gt;Semantic Kernel → MAF Migration Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.cloudflare.com/ai-search/how-to/nlweb/" rel="noopener noreferrer"&gt;Cloudflare NLWeb Integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/search/" rel="noopener noreferrer"&gt;Azure AI Search (Vector + Hybrid)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://schema.org" rel="noopener noreferrer"&gt;Schema.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-at-microsoft-build-2026/" rel="noopener noreferrer"&gt;.NET 11 at Build 2026&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;A year on from NLWeb's announcement, the ecosystem has grown from a promising experiment into a solidifying standard. With &lt;strong&gt;Cloudflare's managed path&lt;/strong&gt;, &lt;strong&gt;.NET 11's native agentic web support&lt;/strong&gt;, and the &lt;strong&gt;Microsoft Agent Framework&lt;/strong&gt; replacing the more fragmented Semantic Kernel agent APIs, the integration story is significantly cleaner in 2026.&lt;/p&gt;

&lt;p&gt;The core idea remains the same: your existing .NET + SQL data is more valuable than you're exposing through a traditional REST interface. NLWeb, GPT-4o, and vector search give your users a natural language front door to that data — whether they're humans typing questions or AI agents making autonomous requests.&lt;/p&gt;

&lt;p&gt;The agentic web is here. Your app should be part of it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;By Jino R Krishnan | Updated June 2026&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>dotnet</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How the Web Stays Connected</title>
      <dc:creator>Jino R Krishnan</dc:creator>
      <pubDate>Fri, 26 Jun 2026 11:42:47 +0000</pubDate>
      <link>https://dev.to/jinkrish/how-the-web-stays-connected-3200</link>
      <guid>https://dev.to/jinkrish/how-the-web-stays-connected-3200</guid>
      <description>&lt;p&gt;When you type a website address into your browser, you probably don’t think about the intricate global infrastructure that makes it all work. Behind the scenes, a handful of organizations ensure that the internet remains stable, secure, and universally accessible. Two of the most critical players in this ecosystem are ICANN and IANA.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll dive deep into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What ICANN and IANA are&lt;/li&gt;
&lt;li&gt;Their roles in the global internet infrastructure&lt;/li&gt;
&lt;li&gt;The technical systems they manage&lt;/li&gt;
&lt;li&gt;Why they are essential to the functioning of the internet&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What is ICANN?
&lt;/h2&gt;

&lt;p&gt;ICANN stands for the &lt;strong&gt;Internet Corporation for Assigned Names and Numbers&lt;/strong&gt;. It is a non-profit organization founded in 1998 and headquartered in Los Angeles, California.&lt;/p&gt;

&lt;h3&gt;
  
  
  ICANN’s Core Responsibilities:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain Name System (DNS) Management:&lt;/strong&gt; ICANN oversees the global DNS, which translates human-readable domain names (like &lt;code&gt;example.com&lt;/code&gt;) into IP addresses (like &lt;code&gt;93.184.216.34&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IP Address Allocation:&lt;/strong&gt; ICANN allocates blocks of IP addresses to Regional Internet Registries (RIRs), which then distribute them to ISPs and organizations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol Parameter Assignment:&lt;/strong&gt; ICANN, through IANA, manages protocol identifiers used in internet protocols (like port numbers and MIME types).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Root Zone Management:&lt;/strong&gt; ICANN coordinates changes to the DNS root zone, the top-level of the DNS hierarchy.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What is IANA?
&lt;/h2&gt;

&lt;p&gt;IANA stands for the &lt;strong&gt;Internet Assigned Numbers Authority&lt;/strong&gt;. It is a department within ICANN that performs the actual technical coordination of key internet resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  IANA’s Three Main Functions:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. IP Address Management
&lt;/h4&gt;

&lt;p&gt;IANA allocates large blocks of IP addresses to the five RIRs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ARIN&lt;/strong&gt; (North America)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RIPE NCC&lt;/strong&gt; (Europe, Middle East)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APNIC&lt;/strong&gt; (Asia Pacific)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LACNIC&lt;/strong&gt; (Latin America)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AFRINIC&lt;/strong&gt; (Africa)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. DNS Root Zone Management
&lt;/h4&gt;

&lt;p&gt;IANA maintains the root zone database, which includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Top-Level Domains (TLDs) like &lt;code&gt;.com&lt;/code&gt;, &lt;code&gt;.org&lt;/code&gt;, &lt;code&gt;.net&lt;/code&gt;, and country codes like &lt;code&gt;.uk&lt;/code&gt;, &lt;code&gt;.jp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Name servers for each TLD&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Protocol Assignments
&lt;/h4&gt;

&lt;p&gt;IANA manages registries for protocol numbers, port numbers, and other parameters used in internet protocols, in coordination with the Internet Engineering Task Force (IETF).&lt;/p&gt;




&lt;h2&gt;
  
  
  The Technical Backbone: How It All Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The DNS Hierarchy
&lt;/h3&gt;

&lt;p&gt;The Domain Name System is structured like a tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;. (root)
├── com
│   └── example.com
├── org
│   └── wikipedia.org
└── net
    └── speedtest.net

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the top is the root zone, managed by IANA. Below that are Top-Level Domains (TLDs), and beneath them are second-level domains (like &lt;em&gt;example&lt;/em&gt; in &lt;code&gt;example.com&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Servers
&lt;/h3&gt;

&lt;p&gt;There are 13 root server letters (A to M), operated by different organizations around the world. These are not single machines but clusters of servers using anycast routing to provide resilience and speed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A Root:&lt;/strong&gt; Operated by Verisign&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;B Root:&lt;/strong&gt; Operated by USC-ISI&lt;/li&gt;
&lt;li&gt;&lt;em&gt;...&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;M Root:&lt;/strong&gt; Operated by WIDE Project (Japan)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These servers respond to DNS queries for the root zone and direct them to the appropriate TLD name servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  How a DNS Query Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;You type &lt;code&gt;www.example.com&lt;/code&gt; into your browser.&lt;/li&gt;
&lt;li&gt;Your computer asks a recursive resolver (usually your ISP).&lt;/li&gt;
&lt;li&gt;If the resolver doesn’t know the answer, it asks a root server.&lt;/li&gt;
&lt;li&gt;The root server replies with the address of the &lt;code&gt;.com&lt;/code&gt; TLD server.&lt;/li&gt;
&lt;li&gt;The resolver asks the &lt;code&gt;.com&lt;/code&gt; server for &lt;code&gt;example.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;.com&lt;/code&gt; server replies with the address of the authoritative server for &lt;code&gt;example.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The resolver asks that server for &lt;code&gt;www.example.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The IP address is returned, and your browser connects to the website.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Why ICANN and IANA Matter
&lt;/h2&gt;

&lt;p&gt;Without ICANN and IANA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There would be no global coordination of domain names or IP addresses.&lt;/li&gt;
&lt;li&gt;The internet could fragment, with different regions using conflicting systems.&lt;/li&gt;
&lt;li&gt;Security and trust in the internet would erode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These organizations ensure that the internet remains a single, interoperable network for everyone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Other Key Organizations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IETF (Internet Engineering Task Force):&lt;/strong&gt; Develops and maintains internet protocols.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;W3C (World Wide Web Consortium):&lt;/strong&gt; Develops web standards like HTML and CSS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ISOC (Internet Society):&lt;/strong&gt; Advocates for open internet development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RIRs (Regional Internet Registries):&lt;/strong&gt; Distribute IP addresses regionally.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Governance and Controversies
&lt;/h2&gt;

&lt;p&gt;ICANN operates under a multi-stakeholder model, involving:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Governments&lt;/li&gt;
&lt;li&gt;Private sector&lt;/li&gt;
&lt;li&gt;Civil society&lt;/li&gt;
&lt;li&gt;Technical community&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This model has faced criticism and praise. Some argue for more governmental control, while others defend the decentralized, community-driven approach.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;ICANN and IANA are the unsung heroes of the internet. Their work is invisible to most users but absolutely essential. They ensure that when you type a URL, send an email, or stream a video, everything just works.&lt;/p&gt;

&lt;p&gt;Understanding these organizations helps us appreciate the complexity and beauty of the internet’s design — and the importance of keeping it open, secure, and well-governed.&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>infrastructure</category>
      <category>networking</category>
      <category>web</category>
    </item>
  </channel>
</rss>
