ai
1406 TopicsBuilding HIPAA-Compliant Medical Transcription with Local AI
Building HIPAA-Compliant Medical Transcription with Local AI Introduction Healthcare organizations generate vast amounts of spoken content, patient consultations, research interviews, clinical notes, medical conferences. Transcribing these recordings traditionally requires either manual typing (time-consuming and expensive) or cloud transcription services (creating immediate HIPAA compliance concerns). Every audio file sent to external APIs exposes Protected Health Information (PHI), requires Business Associate Agreements, creates audit trails on third-party servers, and introduces potential breach vectors. This sample solution lies in on-premises voice-to-text systems that process audio entirely locally, never sending PHI beyond organizational boundaries. This article demonstrates building a sample medical transcription application using FLWhisper, ASP.NET Core, C#, and Microsoft Foundry Local with OpenAI Whisper models. You'll learn how to build sample HIPAA-compliant audio processing, integrate Whisper models for medical terminology accuracy, design privacy-first API patterns, and build responsive web UIs for healthcare workflows. Whether you're developing electronic health record (EHR) integrations, building clinical research platforms, or implementing dictation systems for medical practices, this sample could be a great starting point for privacy-first speech recognition. Why Local Transcription Is Critical for Healthcare Healthcare data handling is fundamentally different from general business data due to HIPAA regulations, state privacy laws, and professional ethics obligations. Understanding these requirements explains why cloud transcription services, despite their convenience, create unacceptable risks for medical applications. HIPAA compliance mandates strict controls over PHI. Every system that touches patient data must implement administrative, physical, and technical safeguards. Cloud transcription APIs require Business Associate Agreements (BAAs), but even with paperwork, you're entrusting PHI to external systems. Every API call creates logs on vendor servers, potentially in multiple jurisdictions. Data breaches at transcription vendors expose patient information, creating liability for healthcare organizations. On-premises processing eliminates these third-party risks entirely, PHI never leaves your controlled environment. US State laws increasingly add requirements beyond HIPAA. California's CCPA, New York's SHIELD Act, and similar legislation create additional compliance obligations. International regulations like GDPR prohibit transferring health data outside approved jurisdictions. Local processing simplifies compliance by keeping data within organizational boundaries. Research applications face even stricter requirements. Institutional Review Boards (IRBs) often require explicit consent for data sharing with external parties. Cloud transcription may violate study protocols that promise "no third-party data sharing." Clinical trials in pharmaceutical development handle proprietary information alongside PHI, double jeopardy for data exposure. Local transcription maintains research integrity while enabling audio analysis. Cost considerations favor local deployment at scale. Medical organizations generate substantial audio, thousands of patient encounters monthly. Cloud APIs charge per minute of audio, creating significant recurring costs. Local models have fixed infrastructure costs that scale economically. A modest GPU server can process hundreds of hours monthly at predictable expense. Latency matters for clinical workflows. Doctors and nurses need transcriptions available immediately after patient encounters to review and edit while details are fresh. Cloud APIs introduce network delays, especially problematic in rural health facilities with limited connectivity. Local inference provides <1 second turnaround for typical consultation lengths. Application Architecture: ASP.NET Core with Foundry Local The sample FLWhisper application implements clean separation between audio handling, AI inference, and state management using modern .NET patterns: The ASP.NET Core 10 minimal API provides HTTP endpoints for health checks, audio transcription, and sample file streaming. Minimal APIs reduce boilerplate while maintaining full middleware support for error handling, authentication, and CORS. The API design follows OpenAI's transcription endpoint specification, enabling drop-in replacement for existing integrations. The service layer encapsulates business logic: FoundryModelService manages model loading and lifetime, TranscriptionService handles audio processing and AI inference, and SampleAudioService provides demonstration files for testing. This separation enables easy testing, dependency injection, and service swapping. Foundry Local integration uses the Microsoft.AI.Foundry.Local.WinML SDK. Unlike cloud APIs requiring authentication and network calls, this SDK communicates directly with the local Foundry service via in-process calls. Models load once at startup, remaining resident in memory for sub-second inference on subsequent requests. The static file frontend delivers vanilla HTML/CSS/JavaScript, no framework overhead. This simplicity aids healthcare IT security audits and enables deployment on locked-down hospital networks. The UI provides file upload, sample selection, audio preview, transcription requests, and result display with copy-to-clipboard functionality. Here's the architectural flow for transcription requests: Web UI (Upload Audio File) ↓ POST /v1/audio/transcriptions (Multipart Form Data) ↓ ASP.NET Core API Route ↓ TranscriptionService.TranscribeAudio(audioStream) ↓ Foundry Local Model (Whisper Medium locally) ↓ Text Result + Metadata (language, duration) ↓ Return JSON/Text Response ↓ Display in UI This architecture embodies several healthcare system design principles: Data never leaves the device: All processing occurs on-premises, no external API calls No data persistence by default: Audio and transcripts are session-only, never saved unless explicitly configured Comprehensive health checks: System readiness verification before accepting PHI Audit logging support: Structured logging for compliance documentation Graceful degradation: Clear error messages when models unavailable rather than silent failures Setting Up Foundry Local with Whisper Models Foundry Local supports multiple Whisper model sizes, each with different accuracy/speed tradeoffs. For medical transcription, accuracy is paramount—misheard drug names or dosages create patient safety risks: # Install Foundry Local (Windows) winget install Microsoft.FoundryLocal # Verify installation foundry --version # Download Whisper Medium model (optimal for medical accuracy) foundry model add openai-whisper-medium-generic-cpu:1 # Check model availability foundry model list Whisper Medium (769M parameters) provides the best balance for medical use. Smaller models (Tiny, Base) miss medical terminology frequently. Larger models (Large) offer marginal accuracy gains at 3x inference time. Medium handles medical vocabulary well, drug names, anatomical terms, procedure names, while processing typical consultation audio (5-10 minutes) in under 30 seconds. The application detects and loads the model automatically: // Services/FoundryModelService.cs using Microsoft.AI.Foundry.Local.WinML; public class FoundryModelService { private readonly ILogger _logger; private readonly FoundryOptions _options; private ILocalAIModel? _loadedModel; public FoundryModelService( ILogger logger, IOptions options) { _logger = logger; _options = options.Value; } public async Task InitializeModelAsync() { try { _logger.LogInformation( "Loading Foundry model: {ModelAlias}", _options.ModelAlias ); // Load model from Foundry Local _loadedModel = await FoundryClient.LoadModelAsync( modelAlias: _options.ModelAlias, cancellationToken: CancellationToken.None ); if (_loadedModel == null) { _logger.LogWarning("Model loaded but returned null instance"); return false; } _logger.LogInformation( "Successfully loaded model: {ModelAlias}", _options.ModelAlias ); return true; } catch (Exception ex) { _logger.LogError( ex, "Failed to load Foundry model: {ModelAlias}", _options.ModelAlias ); return false; } } public ILocalAIModel? GetLoadedModel() => _loadedModel; public async Task UnloadModelAsync() { if (_loadedModel != null) { await FoundryClient.UnloadModelAsync(_loadedModel); _loadedModel = null; _logger.LogInformation("Model unloaded"); } } } Configuration lives in appsettings.json , enabling easy customization without code changes: { "Foundry": { "ModelAlias": "whisper-medium", "LogLevel": "Information" }, "Transcription": { "MaxAudioDurationSeconds": 300, "SupportedFormats": ["wav", "mp3", "m4a", "flac"], "DefaultLanguage": "en" } } Implementing Privacy-First Transcription Service The transcription service handles audio processing while maintaining strict privacy controls. No audio or transcript persists beyond the HTTP request lifecycle unless explicitly configured: // Services/TranscriptionService.cs public class TranscriptionService { private readonly FoundryModelService _modelService; private readonly ILogger _logger; public async Task TranscribeAudioAsync( Stream audioStream, string originalFileName, TranscriptionOptions? options = null) { options ??= new TranscriptionOptions(); var startTime = DateTime.UtcNow; try { // Validate audio format ValidateAudioFormat(originalFileName); // Get loaded model var model = _modelService.GetLoadedModel(); if (model == null) { throw new InvalidOperationException("Whisper model not loaded"); } // Create temporary file (automatically deleted after transcription) using var tempFile = new TempAudioFile(audioStream); // Execute transcription _logger.LogInformation( "Starting transcription for file: {FileName}", originalFileName ); var transcription = await model.TranscribeAsync( audioFilePath: tempFile.Path, language: options.Language, cancellationToken: CancellationToken.None ); var duration = (DateTime.UtcNow - startTime).TotalSeconds; _logger.LogInformation( "Transcription completed in {Duration:F2}s", duration ); return new TranscriptionResult { Text = transcription.Text, Language = transcription.Language ?? options.Language, Duration = transcription.AudioDuration, ProcessingTimeSeconds = duration, FileName = originalFileName, Timestamp = DateTime.UtcNow }; } catch (Exception ex) { _logger.LogError( ex, "Transcription failed for file: {FileName}", originalFileName ); throw; } } private void ValidateAudioFormat(string fileName) { var extension = Path.GetExtension(fileName).TrimStart('.'); var supportedFormats = new[] { "wav", "mp3", "m4a", "flac", "ogg" }; if (!supportedFormats.Contains(extension.ToLowerInvariant())) { throw new ArgumentException( $"Unsupported audio format: {extension}. " + $"Supported: {string.Join(", ", supportedFormats)}" ); } } } // Temporary file wrapper that auto-deletes internal class TempAudioFile : IDisposable { public string Path { get; } public TempAudioFile(Stream sourceStream) { Path = System.IO.Path.GetTempFileName(); using var fileStream = File.OpenWrite(Path); sourceStream.CopyTo(fileStream); } public void Dispose() { try { if (File.Exists(Path)) { File.Delete(Path); } } catch { // Ignore deletion errors in temp folder } } } This service demonstrates several privacy-first patterns: Temporary file lifecycle management: Audio written to temp storage, automatically deleted after transcription No implicit persistence: Results returned to caller, not saved by service Format validation: Accept only supported audio formats to prevent processing errors Comprehensive logging: Audit trail for compliance without logging PHI content Error isolation: Exceptions contain diagnostic info but no patient data Building the OpenAI-Compatible REST API The API endpoint mirrors OpenAI's transcription API specification, enabling existing integrations to work without modifications: // Program.cs var builder = WebApplication.CreateBuilder(args); // Configure services builder.Services.Configure( builder.Configuration.GetSection("Foundry") ); builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddHealthChecks() .AddCheck("foundry-health"); var app = builder.Build(); // Load model at startup var modelService = app.Services.GetRequiredService(); await modelService.InitializeModelAsync(); app.UseHealthChecks("/health"); app.MapHealthChecks("/api/health/status"); // OpenAI-compatible transcription endpoint app.MapPost("/v1/audio/transcriptions", async ( HttpRequest request, TranscriptionService transcriptionService, ILogger logger) => { if (!request.HasFormContentType) { return Results.BadRequest(new { error = "Content-Type must be multipart/form-data" }); } var form = await request.ReadFormAsync(); // Extract audio file var audioFile = form.Files.GetFile("file"); if (audioFile == null || audioFile.Length == 0) { return Results.BadRequest(new { error = "Audio file required in 'file' field" }); } // Parse options var format = form["format"].ToString() ?? "text"; var language = form["language"].ToString() ?? "en"; try { // Process transcription using var stream = audioFile.OpenReadStream(); var result = await transcriptionService.TranscribeAudioAsync( audioStream: stream, originalFileName: audioFile.FileName, options: new TranscriptionOptions { Language = language } ); // Return in requested format if (format == "json") { return Results.Json(new { text = result.Text, language = result.Language, duration = result.Duration }); } else { // Default: plain text return Results.Text(result.Text); } } catch (Exception ex) { logger.LogError(ex, "Transcription request failed"); return Results.StatusCode(500); } }) .DisableAntiforgery() // File uploads need CSRF exemption .WithName("TranscribeAudio") .WithOpenApi(); app.Run(); Example API usage: # PowerShell $audioFile = Get-Item "consultation-recording.wav" $response = Invoke-RestMethod ` -Uri "http://localhost:5192/v1/audio/transcriptions" ` -Method Post ` -Form @{ file = $audioFile; format = "json" } Write-Output $response.text # cURL curl -X POST http://localhost:5192/v1/audio/transcriptions \ -F "file=@consultation-recording.wav" \ -F "format=json" Building the Interactive Web Frontend The web UI provides a user-friendly interface for non-technical medical staff to transcribe recordings: SarahCare Medical Transcription The JavaScript handles file uploads and API interactions: // wwwroot/app.js let selectedFile = null; async function checkHealth() { try { const response = await fetch('/health'); const statusEl = document.getElementById('status'); if (response.ok) { statusEl.className = 'status-badge online'; statusEl.textContent = '✓ System Ready'; } else { statusEl.className = 'status-badge offline'; statusEl.textContent = '✗ System Unavailable'; } } catch (error) { console.error('Health check failed:', error); } } function handleFileSelect(event) { const file = event.target.files[0]; if (!file) return; selectedFile = file; // Show file info const fileInfo = document.getElementById('fileInfo'); fileInfo.textContent = `Selected: ${file.name} (${formatFileSize(file.size)})`; fileInfo.classList.remove('hidden'); // Enable audio preview const preview = document.getElementById('audioPreview'); preview.src = URL.createObjectURL(file); preview.classList.remove('hidden'); // Enable transcribe button document.getElementById('transcribeBtn').disabled = false; } async function transcribeAudio() { if (!selectedFile) return; const loadingEl = document.getElementById('loadingIndicator'); const resultEl = document.getElementById('resultSection'); const transcribeBtn = document.getElementById('transcribeBtn'); // Show loading state loadingEl.classList.remove('hidden'); resultEl.classList.add('hidden'); transcribeBtn.disabled = true; try { const formData = new FormData(); formData.append('file', selectedFile); formData.append('format', 'json'); const startTime = Date.now(); const response = await fetch('/v1/audio/transcriptions', { method: 'POST', body: formData }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const result = await response.json(); const processingTime = ((Date.now() - startTime) / 1000).toFixed(1); // Display results document.getElementById('transcriptionText').value = result.text; document.getElementById('resultDuration').textContent = `Duration: ${result.duration.toFixed(1)}s`; document.getElementById('resultLanguage').textContent = `Language: ${result.language}`; resultEl.classList.remove('hidden'); console.log(`Transcription completed in ${processingTime}s`); } catch (error) { console.error('Transcription failed:', error); alert(`Transcription failed: ${error.message}`); } finally { loadingEl.classList.add('hidden'); transcribeBtn.disabled = false; } } function copyToClipboard() { const text = document.getElementById('transcriptionText').value; navigator.clipboard.writeText(text) .then(() => alert('Copied to clipboard')) .catch(err => console.error('Copy failed:', err)); } // Initialize window.addEventListener('load', () => { checkHealth(); loadSamplesList(); }); Key Takeaways and Production Considerations Building HIPAA-compliant voice-to-text systems requires architectural decisions that prioritize data privacy over convenience. The FLWhisper application demonstrates that you can achieve accurate medical transcription, fast processing times, and intuitive user experiences entirely on-premises. Critical lessons for healthcare AI: Privacy by architecture: Design systems where PHI never exists outside controlled environments, not as a configuration option No persistence by default: Audio and transcripts should be ephemeral unless explicitly saved with proper access controls Model selection matters: Whisper Medium provides medical terminology accuracy that smaller models miss Health checks enable reliability: Systems should verify model availability before accepting PHI Audit logging without content logging: Track operations for compliance without storing sensitive data in logs For production deployment in clinical settings, integrate with EHR systems via HL7/FHIR interfaces. Implement role-based access control with Active Directory integration. Add digital signatures for transcript authentication. Configure automatic PHI redaction using clinical NLP models. Deploy on HIPAA-compliant infrastructure with proper physical security. Implement comprehensive audit logging meeting compliance requirements. The complete implementation with ASP.NET Core API, Foundry Local integration, sample audio files, and comprehensive tests is available at github.com/leestott/FLWhisper. Clone the repository and follow the setup guide to experience privacy-first medical transcription. Resources and Further Reading FLWhisper Repository - Complete C# implementation with .NET 10 Quick Start Guide - Installation and usage instructions Microsoft Foundry Local Documentation - SDK reference and model catalog OpenAI Whisper Documentation - Model architecture and capabilities HIPAA Compliance Guidelines - HHS official guidance Testing Guide - Comprehensive test suite documentationCopilot, Microsoft 365 & Power Platform Community call
💡 Copilot, Microsoft 365 & Power Platform weekly community call focuses on different use cases and features within the Microsoft 365 and Power Platform - across Microsoft 365 Copilot, Copilot Studio, SharePoint, Power Apps and more. Demos in this call are presented by the community members. 👏 Looking to catch up on the latest news and updates, including cool community demos, this call is for you! 📅 On 20th of August we'll have following agenda: Latest on SharePoint Framework (SPFx) Latest on Copilot prompt of the week PnPjs CLI for Microsoft 365 Dev Proxy Reusable Controls for SPFx SPFx Toolkit VS Code extension PnP Search Solution Demos this time OluwaMayowa Ogbeide – Building a Domain-Specific AI Advisor with Power Automate + SharePoint + External LLM APIs Simon Doy – Cowork Plugins and Timesheets - Almost Never have to fill out a timesheet again 📅 Download recurrent invite from https://aka.ms/community/m365-powerplat-dev-call-invite 📞 & 📺 Join the Microsoft Teams meeting live at https://aka.ms/community/m365-powerplat-dev-call-join 💡 Building something cool for Microsoft 365 or Power Platform (Copilot, SharePoint, Power Apps, etc)? We are always looking for presenters - Volunteer for a community call demo at https://aka.ms/community/request/demo 👋 See you in the call! 📖 Resources: Previous community call recordings and demos from the Microsoft Community Learning YouTube channel at https://aka.ms/community/youtube Microsoft 365 & Power Platform samples from Microsoft and community - https://aka.ms/community/samples Microsoft 365 & Power Platform community details - https://aka.ms/community/home 🧡 Sharing is caring!12Views0likes0CommentsFrom AI PoC to Production: 7 Architecture Decisions Every Enterprise Must Get Right
Architecture Deep Dive Moving from an AI Proof of Concept to an enterprise-ready production workload requires much more than selecting the right model. AI is no longer just an experimentation topic. Across enterprises, teams are building copilots, RAG applications, AI agents, intelligent automation and domain-specific AI solutions. But there is a significant difference between making an AI Proof of Concept work and making an AI solution production-ready. A PoC asks: “Can we make AI do this?” Production asks much harder questions: “Can we make it secure, reliable, scalable, observable, governed and financially sustainable?” That is where architecture becomes critical. Microsoft’s Azure Well-Architected guidance for AI workloads highlights that AI systems introduce architectural considerations beyond traditional applications, including nondeterministic behavior, grounding data, model operations, testing, responsible AI and continuous evaluation. Here are seven architecture decisions I believe every enterprise should consider before moving an AI workload from PoC to production. 1. Start With the Business Outcome — Not the Model One of the most common mistakes is starting with: “Which AI model should we use?” The better question is: “What business problem are we solving?” Before selecting a model or Azure service, define: • The business outcome • The users • The expected experience • The measurable success criteria • Regulatory and compliance requirements • Data sensitivity • Expected scale For example: Instead of saying: “We want to build an enterprise chatbot.” Define the outcome: “We want employees to find accurate information from 500,000 internal documents in less than 5 seconds while respecting existing access permissions.” That single statement changes the architecture conversation completely. 2. Design the Data and Grounding Architecture First Enterprise AI is only as useful as the information it can access and trust. For many enterprise scenarios, the challenge isn't simply selecting a powerful model. The challenge is providing the model with the right context. This is where grounding and RAG architectures become important. A typical flow looks like: User → Application → Orchestration → Knowledge/Retrieval → Model → Response But an enterprise implementation also needs to consider: • Data ingestion • Chunking and enrichment • Metadata • Indexing • Access control • Data freshness • Source attribution • Retrieval quality • Auditability Microsoft's current AI architecture guidance explicitly treats the knowledge layer as a core architectural component and emphasizes enforcing data access policies and authorization within that layer. The key architectural question is therefore not: “Can the model answer the question?” It is: “Can the model answer the question using authorized, relevant and trustworthy enterprise data?” 3. Separate Intelligence, Inference, Knowledge and Tools AI applications are becoming more sophisticated. Modern architectures may involve models, agents, orchestration, enterprise data and external tools. Putting everything into one application layer quickly becomes difficult to secure, scale and operate. A better approach is to establish clear architectural boundaries. A useful conceptual model is: Client Layer ↓ Intelligence / Orchestration Layer ↓ Inference Layer ↓ Knowledge Layer ↓ Tools / Business APIs Each layer can have its own: • Identity • Security policies • Scaling strategy • Monitoring • Caching • Failure handling This separation becomes particularly important when moving from a simple chatbot to agentic AI applications. Microsoft's AI application design guidance recommends distinct client, intelligence, inference, knowledge and tools layers for intelligent applications. 4. Treat Security as an Architecture Principle — Not a Checklist AI introduces new security considerations. You need to think beyond traditional application security. Ask: • Who can access the AI application? • What data can the user retrieve? • Can the model access information the user cannot? • How are identities propagated across components? • How are prompts and responses protected? • How are AI tools authorized? • How are sensitive outputs detected? • How are activities audited? One particularly important principle is: The AI system should not become an alternative path around existing enterprise authorization. If an employee cannot access a document directly, the AI assistant should not expose that document through a generated response. Security therefore needs to exist across the entire AI architecture: Identity → Data → Retrieval → Model → Tools → Output 5. Design for Scale and Reliability Before You Need It A PoC might have: 10 users 100 documents 1 model 1 environment Production might have: 100,000 users Millions of documents Multiple models Multiple business applications Continuous availability requirements The architecture must therefore consider: • Horizontal scaling • Availability Zones • Regional resiliency • Load balancing • Model availability • Rate limiting • Failover • Caching • Capacity planning AI workloads also have unique infrastructure considerations. Inference capacity can become a bottleneck, and GPU-based workloads can introduce significant infrastructure costs. Microsoft's current Azure AI architecture guidance recommends designing for scalability and availability across the intelligence, orchestration, inference and knowledge layers. 6. Cost Must Be Designed Into the Architecture AI can create unexpected cost growth. A solution may work perfectly from a technical perspective and still fail the business case because of: • Token consumption • Model selection • GPU utilization • Storage • Data processing • Retrieval infrastructure • Logging • Network traffic • High-frequency inference Therefore, ask: “What is the expected cost per transaction?” Then model: Users × Requests × Tokens × Model Cost But don't stop there. Also evaluate: • Caching opportunities • Model routing • Smaller models for simpler tasks • Batch processing • GPU utilization • Resource scaling • Storage optimization Microsoft's Well-Architected guidance specifically highlights monitoring utilization and avoiding unnecessary AI infrastructure costs. The cheapest architecture isn't necessarily the best architecture. The goal is: Maximum business value per unit of AI spend. 7. Production Requires Continuous Evaluation and Observability Traditional applications usually monitor: CPU Memory Latency Errors Availability AI applications need more. You also need to understand: • Response quality • Grounding accuracy • Retrieval relevance • Hallucination rate • Model performance • Prompt effectiveness • Safety violations • User feedback • Token consumption • Cost per interaction AI is nondeterministic. The same input may not always produce exactly the same output. That means testing cannot simply end when the application goes live. Production evaluation becomes part of the architecture. Microsoft's guidance recommends extending observability to AI-specific quality metrics and supporting testing and evaluation with real production inputs. The Architecture Mindset Shift The biggest transition from PoC to production is not necessarily choosing a better model. It is changing the questions we ask. PoC thinking: “Can AI do it?” Production thinking: “Can the enterprise operate it safely and economically at scale?” That leads to a different architecture conversation: Business Outcome ↓ Data & Grounding ↓ Security & Identity ↓ AI Application Architecture ↓ Infrastructure & Scalability ↓ Observability & Governance ↓ Cost Optimization ↓ Continuous Evaluation My 7-Question Production Readiness Test Before approving an enterprise AI workload for production, I would ask: 1. What measurable business outcome are we delivering? 2. Can we trust and govern the data being used? 3. Can the AI respect existing identity and authorization boundaries? 4. Can every major component scale and recover from failure? 5. Can we measure AI quality—not just infrastructure health? 6. Do we understand the cost at production scale? 7. Can we continuously evaluate, improve and govern the solution? If the answer to several of these is “not yet”, the solution may still be a PoC. And that's perfectly fine. The objective isn't to rush an AI PoC into production. The objective is to build the architecture that makes production possible. Final Thought AI architecture is becoming less about: “Which model should we use?” And increasingly about: “How do we build an AI system that the enterprise can trust?” That is the real journey: PoC → Architecture → Production → Scale → Business Value The organizations that get this architecture right will be in a much stronger position to move from AI experimentation to sustainable enterprise AI adoption. What do you think is the biggest challenge when moving an enterprise AI solution from PoC to production — security, data, scalability, cost, or something else?7Views0likes0CommentsFree course: Unlocking AI for Nonprofits
With support from Microsoft, NetHope has launched a new free, CPD-certified course series - Unlocking AI for Nonprofits - designed specifically for nonprofit professionals. The series will help nonprofit teams build practical and responsible AI skills, no technical background required. The four learning pathways include: AI Basics – Learn what AI is and why it matters for nonprofits Applications of Generative AI – Explore time-saving tools for content, reporting, and data Advanced Applications: Microsoft Copilot and Beyond – Help your team adopt AI with clarity and confidence Responsible Use of AI – Understand ethics, inclusion, and organizational safeguards We’ve had more than 1,000 enrollments across the series to date – don't miss out! Courses are free and available through August 31, 2025. https://nethope.org/programs/unlocking-ai-for-nonprofits-enroll-in-our-new-ai-skills-course-for-nonprofits/?utm_medium=forum&utm_source=microsoftnonprofit&utm_campaign=msaiskillsjul&utm_content=unlockingai506Views3likes3CommentsBuilding Autonomous Agents with Microsoft Agent Framework and GitHub Copilot SDK Part 2/5
This is the second post in our series on the Microsoft agent platform. Here we dive deep into building autonomous agents, the development experience, the Microsoft Agent Framework, tool design patterns, and how the GitHub Copilot SDK brings conversational AI to your agent system. All examples reference the FibreOps repository, an autonomous fibre outage response system demonstrated at Microsoft Build BRK241. The Microsoft Agent Framework The Microsoft Agent Framework (now GA) provides a unified programming model for building agents. It supports multiple backends through a single .run() contract: Hosted — FoundryAgent connected to a Prompt Agent published to Microsoft Foundry Agent Service. Foundry — Agent + FoundryChatClient with the definition resolved locally (ideal for prompt iteration). Local — Deterministic LocalAgent for offline development and testing. This design means your orchestration code never changes regardless of where the agent runs. The factory pattern in FibreOps selects the backend at startup: # src/fibreops/agents/factory.py — simplified from agent_framework_foundry import FoundryAgent from agent_framework import Agent, FoundryChatClient def build_agent(role: str, backend: str, config: Config): if backend == "hosted": return FoundryAgent(agent_id=config.foundry_agents[role]) elif backend == "foundry": return Agent( instructions=get_instructions(role), chat_client=FoundryChatClient(endpoint=config.endpoint), tools=get_tools(role), ) else: return LocalAgent(role=role) Set FIBREOPS_AGENT_BACKEND to override the backend, or leave it as auto for intelligent detection. Designing Role-Specialised Agents FibreOps demonstrates a key pattern: role specialisation. Rather than one monolithic agent, the system uses three focused agents, each with a clear responsibility boundary: Agent Role Tools Available IncidentAnalysisAgent Classify severity, find root cause, retrieve SOP Knowledge (SOPs + topology), Web IQ, Work IQ NetOpsCoordinatorAgent File D365 incident, post Teams notice Ticketing, Teams, Memory FieldDispatchAgent Select engineer, book resource, update team Dispatch, Teams, Voice Why Role Specialisation? Focused system prompts — Each agent has a tightly scoped instruction set, reducing hallucination and improving reliability. Independent evaluation — You can score each agent separately against role-specific criteria. Parallel development — Teams can iterate on agents independently. Selective upgrade — Swap one agent's model or implementation without touching others. Tool Design: Typed Python Functions Tools in the Microsoft Agent Framework are typed Python functions that the runtime supplies to the hosted agent definition. FibreOps demonstrates several tool categories: Knowledge Tools # src/fibreops/tools/knowledge.py — simplified def sop_lookup(node_id: str, signal_type: str) -> dict: """Retrieve the Standard Operating Procedure for a given signal type. Args: node_id: The fibre node identifier (e.g., FN-LDN-001) signal_type: The type of signal (loss_of_light, high_ber, signal_degradation) Returns: SOP with steps, escalation path, and estimated resolution time. """ # Load from local markdown SOPs or Foundry IQ ... def web_iq_search(query: str, *, limit: int = 5) -> list[dict]: """Search public web for context relevant to the incident. Grounding against roadworks, weather, power outages, splice guidance. Falls back to deterministic fixtures when endpoint is unset. """ ... def work_iq_search(query: str, *, limit: int = 5) -> list[dict]: """Search enterprise knowledge for context relevant to the incident. Site surveys, SLA tiers, competency matrix, MTTR trends. """ ... Integration Tools # src/fibreops/tools/teams.py — simplified def post_outage_notice( incident_id: str, node_id: str, severity: str, summary: str, engineer: str | None = None, ) -> dict: """Post an Adaptive Card outage notice to the configured Teams channel. If TEAMS_WEBHOOK_URL is not set, appends to state/teams_outbox.jsonl for offline review. """ card = build_adaptive_card(incident_id, node_id, severity, summary, engineer) if config.teams_webhook_url: requests.post(config.teams_webhook_url, json=card) else: append_to_outbox(card) return {"status": "posted", "incident_id": incident_id} Design Principles for Agent Tools Typed parameters with docstrings — The runtime uses type hints and docstrings to generate the tool schema for the LLM. Graceful degradation — Every tool works offline by falling back to local fixtures or file-based state. Idempotent where possible — Tools that create resources return existing records if called with the same parameters. Observable — Every tool invocation emits an OpenTelemetry span for tracing and debugging. The Orchestrator Pattern The orchestrator drives signals through the agent pipeline. It is deliberately simple — a linear flow with error handling: # src/fibreops/orchestrator.py — simplified async def handle_signal(signal: TelemetrySignal) -> RunResult: """Process a telemetry signal through the agent pipeline.""" # Stage 1: Incident Analysis analysis = await incident_agent.run( f"Analyse this signal: {signal.model_dump_json()}" ) # Stage 2: NetOps Coordination coordination = await netops_agent.run( f"Coordinate response for: {analysis.summary}" ) # Stage 3: Field Dispatch dispatch = await dispatch_agent.run( f"Dispatch engineer for incident: {coordination.incident_id}" ) return RunResult( signal=signal, analysis=analysis, coordination=coordination, dispatch=dispatch, ) The orchestrator honours the same contract regardless of backend — hosted , foundry , or local — because all backends implement await agent.run(prompt) . GitHub Copilot SDK Integration (GA) The GitHub Copilot SDK enables conversational interaction with your agent system. FibreOps implements FibreOpsCopilotClient with the same interface as github/copilot-sdk : # src/fibreops/sdk/__init__.py — simplified from fibreops.sdk.client import FibreOpsCopilotClient client = FibreOpsCopilotClient() session = client.create_session() # Query agent status response = session.send_and_wait("status") print(response.text) # Human-readable summary print(response.data) # Structured JSON # Inject a telemetry signal via conversation response = session.send_and_wait(json.dumps({ "signal_id": "sig-demo", "node_id": "FN-LDN-001", "signal_type": "loss_of_light", "severity": "critical" })) The adapter routes prompts by shape: JSON signal-shaped dicts — Forwarded to the orchestrator for processing. Free-form text — Answered by a deterministic responder ( help , status , nodes , engineers , optimiser , dispatch ). Drive it from the terminal: python -m fibreops.demo chat "help" python -m fibreops.demo chat "status" python -m fibreops.demo chat '{"signal_id":"sig-demo","node_id":"FN-LDN-001","signal_type":"loss_of_light","severity":"critical"}' Or hit the embedded HTTP endpoint when the NOC console is running: Invoke-RestMethod -Method Post http://127.0.0.1:8800/sdk/chat -Body '{"prompt":"status"}' -ContentType application/json Development Workflow with Foundry Toolkit for VS Code The Foundry Toolkit for VS Code provides an integrated development experience: Author prompts — Edit system instructions with live preview and token counting. Test locally — Run against the foundry backend with FoundryChatClient pointing at your development model. Iterate fast — The foundry backend resolves definitions locally, so prompt changes take effect immediately without republishing. Publish when ready — python -m fibreops.demo publish creates hosted Prompt Agents in Foundry. Multi-Model Support The Microsoft Agent Framework supports multiple models. FibreOps defaults to gpt-4.1-mini (the model available in most demo Foundry accounts), but any chat-completions deployment works: # .env AZURE_AI_MODEL_DEPLOYMENT=gpt-4.1-mini # or gpt-4o-mini, gpt-4o, gpt-4.1 The framework also supports Claude Code connectors and Magentic-One for multi-agent collaboration scenarios. Testing Strategy FibreOps demonstrates a layered testing approach: Unit tests — Test tools in isolation with mocked dependencies. Local backend tests — Run the full pipeline with LocalAgent for deterministic assertions. Integration tests — Run against real Foundry agents with pytest -q . Rubric evaluation — The optimizer scores every run against defined criteria. # Run the test suite .\.venv\Scripts\python.exe -m pytest -q Key Takeaways The Microsoft Agent Framework provides a unified .run() contract across hosted, foundry, and local backends. Role specialisation keeps agents focused, testable, and independently evolvable. Tools are typed Python functions with docstrings — the runtime generates schemas automatically. The GitHub Copilot SDK (GA) enables conversational interaction with any agent system. Graceful degradation means the entire system works offline for development. The factory pattern lets you switch backends without changing orchestration code. Next Steps Clone the FibreOps repository and run python -m fibreops.demo --signals 3 Microsoft Agent Framework documentation Next in this series: Running Hosted Agents in Microsoft Foundry Agent ServiceContainer Network Insights Agent (CNIA): Your AI Teammate for AKS Networking Incidents
Hello Folks! If you run AKS in production, you already know the script. A pod cannot reach an external service, every dashboard says the cluster is healthy, and somebody is SSHing into a node with five browser tabs open trying to piece the story together. This session from the Microsoft Azure Infra Summit 2026 tackles that exact pain. Shaifali Garg (PM for Azure Container Networking on AKS) sits down with Jonathan Wang, an AKS operator running 30 clusters across two regions on Cilium, and they walk through what a real networking incident feels like, then introduce the Container Network Insights Agent (CNIA) live in the cluster. Why IT Pros Should Care In Jonathan’s environment, about 40% of incidents end up being networking problems. The tools all exist (kubectl, dashboards, detectors, Hubble), but the time sink is figuring out which layer the problem lives in and what to check next. CNIA goes after that gap. Here is what you actually get back: A symptom-to-classification jump in seconds, so you skip the first 30 minutes of “is this DNS, policy, node, or app?” One chat window with one evidence table, one root cause, and one copy-paste fix command, instead of jumping across five tabs Senior SRE tribal knowledge baked into the workflow, so anyone on the team can run the same investigation a principal engineer would Read-only by design, so the agent never changes anything on your cluster. You stay the human in the loop Installs as an AKS extension (no Helm chart, no YAML to babysit), and Azure handles the lifecycle In short, CNIA is not trying to replace your SRE team. It hands them back 20 or 30 minutes on every networking ticket, which adds up fast across a fleet. What CNIA Is, A Technical Overview Think of CNIA as an AI teammate that lives inside your AKS cluster as a pod. You describe what is broken in plain English, the way you would ping a senior engineer on Slack, and behind the scenes the agent does four things in order. It classifies the kind of problem (DNS, egress, policy, node, app), it pulls live evidence from your cluster, it analyzes that evidence, and it hands you back a clean report with evidence, root cause, and a copy-paste exec command. Two architectural choices stand out. First, the agent uses your own Azure OpenAI resource (bring your own), so prompts and diagnostic content stay in your tenant and your region. Microsoft does not see your diagnostic data, and nothing gets persisted externally. Second, the answer is grounded in evidence pulled from your cluster, not from the internet. Your pods, your policies, your CoreDNS, your host-level NIC and kernel counters. If the evidence is inconclusive, CNIA says so rather than fabricating a root cause. That last bit is what earns trust with senior SREs. CNIA fits inside the broader Advanced Container Networking Services (ACNS) story on AKS. ACNS gives you metrics in Azure Managed Prometheus and Grafana, stored and on-demand network logs with Hubble, and FQDN-based filtering with Cilium. CNIA sits on top, automating the triage loop across those signals so you do not have to walk through the playbook by hand every time. How It Works, Under the Hood The install is an AKS extension. Roughly 5 to 7 minutes from “az aks extension” to “you have an SRE buddy in your cluster.” One small pod runs continuously. A second helper only spins up on the node during a deep packet-drop investigation, reads host-level network counters, and is cleaned up right after. Nothing left behind. Permissions are deliberately narrow: Read-only RBAC on the cluster. The agent looks, it never changes anything A workload identity tied to your Azure OpenAI resource. No shared credentials Outbound traffic is HTTPS to your OpenAI endpoint on port 443, and nothing else. If you want to log that further through an NSG or firewall, that is supported On the safety side, CNIA layers two protections against prompt injection. The agent is scope-restricted by design, so off-topic requests get rejected straight away. In one of Jonathan’s demos, Shefali asks the agent to “delete core-dns” and to “write a script to scrape LinkedIn profiles.” Both are refused on the spot. The second layer is the read-only RBAC at the cluster level. Even if someone tricked the prompt into emitting a destructive command, the cluster itself would refuse. The pod’s execution is scoped to specific diagnostic commands. It is not an open shell. Honest tradeoffs, because you will ask: It is one cluster at a time. Multi-cluster correlation is not in scope yet It does not auto-remediate. It tells you the fix, you verify and run it It is AKS only. EKS and GKE are not supported today Session state lives in the pod in memory. If the pod restarts, you start a fresh chat (past sessions are still available in history) Heavy packet-drop investigations have been validated up to around 7 concurrent users on smaller clusters. The team is actively scaling that up Real-World Value The session includes two demos that map directly to incidents you have probably lived through. Demo 1, egress that silently dies. Pods cannot reach google.com. CoreDNS resolves it fine, example.com works from the same pod, every dashboard says healthy. CNIA classifies it as an egress connectivity problem (not DNS) and surfaces the actual culprit: a Cilium network policy named “restrict external FQDN” with a toFQDN rule that only allows example.com. Everything else gets silently dropped at the egress gate. DNS was allowed, the TCP connection was not. The fix command (a kubectl patch to add google.com to the allow list) is right there in the report. End-to-end fix in under a minute. Demo 2, the target port typo. A service is down with connection refused. Pods running, service exists, endpoints populated, no network policies. The agent goes inside the pod, looks at the actual listening sockets, and proves the mismatch: target port 8080, but nginx listens on port 80. One-digit typo in YAML that no kubectl get would surface on its own. The ROI math is straightforward. If your team handles networking incidents weekly and each one costs 20 to 30 minutes of “where do I even start,” that capacity adds up across the org. And critically, the win is not just speed. When the one engineer who knows where to look goes on leave, the rest of the team is no longer stuck calling them at home. Getting Started Three steps. That is it. Read the public docs, get an overview, scan the use cases, and understand what CNIA does and does not cover Pick a cluster (dev or staging is a great place to start) and install the AKS extension. Give it 5 to 7 minutes Run a few real network tickets through it. Compare your time-to-answer before and after. Hit thumbs-up or thumbs-down in the chat so the product team sees real signal Pricing in preview: no license fee. You pay for the Azure OpenAI tokens it uses (your tenant, your resource), plus the tiny bit of cluster compute for the pod. If you already have Azure OpenAI in your tenant, just point CNIA at it. Resources Diagnose and resolve AKS network issues with Advanced Container Networking Services Advanced Container Networking Services overview Configure Azure CNI Powered by Cilium in AKS AKS cluster extensions Deploy and configure Microsoft Entra Workload ID on an AKS cluster What is Azure OpenAI Service? Keep Learning at the Summit Catch the full Microsoft Azure Infra Summit 2026 session playlist here: https://www.youtube.com/playlist?list=PLjt5SKzX1iI8con7FJDB56G6hHqxGm7ki Cheers! Pierre Roman53Views0likes0CommentsAccelerate your AI go-to-market strategy with Microsoft Marketplace
AI innovation is moving faster than ever but building a successful AI solution requires more than choosing the right model. From development and deployment to discovery, customer adoption, and monetization, every decision plays a role in bringing AI-powered solutions to market. In this insightful article, Microsoft Marketplace experts explore how software companies can accelerate AI development by leveraging the Microsoft ecosystem, including Azure AI Foundry, Microsoft Copilot, and Microsoft Marketplace. Learn how to evaluate models, choose the right Marketplace offer type, improve solution discoverability through Intelligent Discovery, and build customer trust through secure-by-design practices. Whether you're enhancing an existing application with AI or developing a new AI-native solution, this article provides practical guidance for connecting innovation with commercial success helping you learn how Microsoft Marketplace can help transform your AI innovation into scalable business growth. Read the full article An overview of accelerating AI development with Microsoft Marketplace20Views0likes0CommentsAn overview of accelerating AI development with Microsoft Marketplace
“The best Marketplace listings explain what the solution does, who it serves, and the outcomes it helps customers achieve.” - Felipe Ospina The new reality of AI development The pace of AI innovation continues to accelerate. New models, frameworks, and development tools are arriving at an extraordinary rate, creating new opportunities for software companies to bring intelligent products to market. But delivering an AI-powered solution requires more than selecting a model and writing code. Developers must decide how to package their solution, how customers will consume it, how it will be discovered, and how to create a path from innovation to revenue. Microsoft Marketplace is increasingly becoming part of that journey. By bringing together cloud and AI solutions, developer tools, distribution channels, and commercialization capabilities, Marketplace helps software companies move from experimentation to customer adoption through a connected Microsoft Cloud experience. Building an AI solution starts with the right foundation Many development teams work across multiple services and providers as they create AI apps and agents. Models may come from one vendor, observability tools from another, databases from a third, and cloud infrastructure from yet another source. As AI projects grow, teams often spend as much time managing supporting services as they do building differentiated customer experiences. Microsoft Marketplace offers an alternative approach by helping developers source cloud and AI solutions directly within the Microsoft ecosystem. Models, developer tools, databases, analytics platforms, and observability solutions can be provisioned into Azure environments while remaining connected to existing development workflows. This creates an experience where developers can focus more of their energy on creating value for customers and less on stitching together disconnected processes. The importance of model selection One of the most important choices in any AI project is model selection. The model that delivers the best outcome is not always the largest model or the most recognizable name. Performance, cost, specialization, and intended use case all play a role in determining whether a model supports long-term product success. Through Azure AI Foundry, developers can compare models against specific scenarios and evaluate performance characteristics alongside cost considerations. This provides a data-driven approach to selecting the right model rather than relying on assumptions alone. The ability to evaluate, provision, and iterate on models creates flexibility for software companies. A solution can begin with one model, evolve toward a different provider, or expand into industry-specific variants while maintaining a consistent development experience. For teams building products in healthcare, financial services, legal services, and other specialized domains, that flexibility can play an important role in creating differentiated solutions. Not every AI journey starts from scratch There is a common assumption that success in AI requires building an entirely new product. In reality, many software companies already have established applications, existing customer relationships, proven workflows, and trusted user experiences. For these organizations, adding AI capabilities to an existing product may create a faster path to growth. Others may choose to build entirely new AI-native agents and applications designed around emerging user experiences. Both approaches can be successful. The key is aligning the strategy to business goals, product differentiation, and desired time to market. What matters most is making intentional architectural and commercialization decisions early in the process. Choosing the right Marketplace offer type One of the most practical lessons for developers is that commercialization planning should begin while the product is being designed, not after development is complete. Microsoft Marketplace provides multiple offer types; each designed for different deployment and customer scenarios: SaaS offers are often a strong fit for applications hosted and operated by the software company. Container offers can support customers that require solutions to run within their own environments. Managed applications provide a model where customers control their Azure environment while the publisher operates the solution. Apps, agents, and connectors for Microsoft Copilot help publishers bring experiences directly into Microsoft 365 and Copilot workflows. These decisions influence architecture, deployment patterns, customer onboarding, billing approaches, support models, and go-to-market strategies. Determining the right path early helps create alignment across the entire product lifecycle. Publishing is about more than listing a product A successful AI solution needs visibility. Publishing through Marketplace is not simply about adding a product to a catalog. It is about connecting a solution to customers already working across Azure, Microsoft 365, Microsoft Copilot, Azure AI Foundry, and Microsoft partner channels. This approach allows software companies to publish once while creating opportunities for discovery across multiple Microsoft experiences. For developers and technical founders, this changes how go-to-market planning can be approached. Instead of building entirely separate distribution channels, organizations can focus on strengthening the product while benefiting from distribution pathways already connected to Microsoft Marketplace. The opportunity is not just Marketplace itself. The opportunity is reaching more customers, scaling product-led growth, and extending innovation through Microsoft's commercial ecosystem. Why intelligent discovery matters As the number of cloud and AI solutions continues to grow, discoverability becomes increasingly important. Intelligent Discovery, currently in preview, is designed to help customers describe business needs using natural language and receive relevant solution recommendations. Instead of relying only on traditional keyword searches, customers can search based on intent. For publishers, this creates an important responsibility. Product descriptions, use cases, categories, industries, and solution details become critical signals that help customers find the right offering. Clear, accurate descriptions are no longer just product marketing assets. They are part of the discovery experience itself. The more clearly a solution explains the problem it solves, the audience it serves, and the outcomes it supports, the better positioned it is to surface in relevant customer searches. Trust is built into the product AI adoption depends on trust. Customers are evaluating more than model quality. They are also evaluating security, privacy, governance, documentation, support readiness, and operational maturity. That is why secure-by-design principles should be considered from the beginning. Identity management, tenant isolation, least-privilege access controls, encryption, secure integrations, secrets management, and responsible AI practices all contribute to building customer confidence. The same principle applies to Marketplace readiness. Complete solution information, accurate support resources, strong documentation, and thoughtful onboarding experiences help customers evaluate and adopt solutions more effectively. Final thoughts AI development is no longer just about choosing a model or deploying infrastructure. Success increasingly depends on how effectively software companies connect development, publishing, discovery, customer adoption, and monetization. Microsoft Marketplace brings those elements together through a platform that helps software companies source cloud and AI solutions, publish offers, reach customers across Microsoft experiences, and grow through Microsoft's commercial ecosystem. We recently hosted a Marketplace community event that dove deeper into accelerating AI development and how Marketplace can support your next stage of AI development, publishing and growth. The complete office hour session offers additional guidance, examples, and recommendations for turning innovative ideas into scalable business opportunities. Watch and learn From AI evaluation to deployment with Microsoft Marketplace89Views0likes0CommentsVector search finds candidates. Reranking decides what your RAG app reads
You ask a retrieval-augmented generation (RAG) application a question. Vector search returns ten passages that are clearly related to the topic. The passage that actually contains the answer, however, is ranked seventh, while the language model receives only the first five. Retrieval did not completely fail. It found the evidence, but ordered it below less useful context. Reranking addresses that gap between a passage that is semantically similar and a passage that is relevant to the user's specific question. This article demonstrates that pattern in four Azure services using the Stanford Question Answering Dataset (SQuAD). The goal is not to declare a winning service or publish a quality benchmark. It is to show where retrieval, rank fusion, and model-based reranking run in each architecture, and to illustrate how the position of a known source passage can change. What this demonstration establishes The examples show rank movement for three selected questions. They do not establish that one reranker or service is universally more accurate. A production decision requires a larger, representative query set and aggregate relevance, latency, and cost measurements. Get the full Python implementation: pauldj54/azure-vector-reranking-squad Retrieval and reranking are different stages A production search pipeline commonly uses two stages: Retrieve for recall. Fast retrieval narrows a large corpus to a bounded candidate set. It can use vector search, keyword search, or both. Rerank for precision. A more expensive model evaluates only those candidates against the original query and produces the final order. Reciprocal Rank Fusion (RRF) belongs between those two ideas. RRF is a model-free rank aggregation method that merges independent result lists, usually vector and keyword results. For a document d, a typical score is: RRF(d) = ∑ r ∈ R 1 k + rank r (d) Here, R is the set of ranked lists and k is commonly 60. RRF works with positions rather than raw scores, so it can combine signals such as cosine distance and BM25 without pretending their score scales are comparable. This gives a clearer three-part vocabulary: Stage Purpose Typical mechanism Retrieve Find broad candidate set Vector search, BM25, filters Fuse Combine independent rankings RRF Rerank Reassess query-document relevance Semantic ranker or cross-encoder RRF often improves hybrid retrieval when exact names, dates, identifiers, or terms matter. A learned reranker can then read the query and each candidate together, capturing interactions that separately generated embeddings can miss. The learned stage costs more, so it should operate on tens of candidates rather than the whole corpus. The following image describes the general process: Why use SQuAD for this demonstration? SQuAD 1.1 contains crowd-written questions over more than 500 Wikipedia articles. Its packaged splits contain 87,599 training rows and 10,570 validation rows. Each row includes a question, a context passage, and one or more answer spans inside that passage. That source-context mapping gives this demonstration a useful label: the context associated with a question is treated as its gold passage. We can then inspect whether each search stage moves that passage up or down. This is convenient, but it is not a perfect passage-ranking benchmark. SQuAD was designed for extractive question answering, and another passage in the corpus might also answer a question. The gold context is therefore a reproducible reference, not proof that every other passage is irrelevant. The results shown here use the 2,067 unique contexts in the SQuAD validation split and 1,536-dimensional embeddings. The repository default should be set to the same corpus size before treating the screenshots or rank transitions as directly reproducible. Three illustrative questions Question Expected answer Gold context According to game stats, which Super Bowl 50 quarterback had his worst year since his first NFL season? Peyton Manning 12, Super Bowl 50 What else did Tesla do for work at this time? Various electrical repair jobs 165, Nikola Tesla Who acts as laborer, paymaster, and design team for a renovation project? The property owner 1306, Construction Each notebook selects a seeded demonstration question when it runs. The three saved examples were collected across separate runs; the current notebooks do not execute all three questions in one pass. A benchmark harness should iterate over a fixed question list and save all stage results in one structured output. Capability boundaries at a glance Service Retrieval and Fusion Learned Reranking Boundary to Keep in Mind Azure AI Search Native keyword and vector retrieval with native RRF Built-in semantic ranker Semantic ranking only reorders the retrieved top 50 Azure SQL Database Exact vector retrieval in the current notebook External Cohere model invoked through native REST procedure SQL issues the HTTPS request; Foundry performs inference PostgreSQL Flexible Server pgvector plus hand-written SQL RRF over full-text search Optional external Cohere call from Python Retrieval primitives are native; this RRF query and Cohere path are application code Azure Cosmos DB for NoSQL Native vector search and native hybrid RRF SDK-integrated Semantic Reranker, currently preview Reranking is a separate inference call over at most 50 supplied documents Azure AI Search: native hybrid retrieval and semantic ranking How it works: Azure AI Search provides the most integrated pipeline in this demonstration. A hybrid query runs keyword and vector retrieval, combines the lists with RRF, and passes up to the top 50 results to the built-in semantic ranker. The semantic ranker assigns @search.rerankerScore values from 0 to 4 and can return extractive captions and answers. The semantic configuration identifies the fields that carry the meaning of each document: semantic_search = SemanticSearch( configurations=[ SemanticConfiguration( name=SEMANTIC_CONFIG, prioritized_fields=SemanticPrioritizedFields( title_field=SemanticField(field_name="title"), content_fields=[SemanticField(field_name="content")], ), ) ] ) This tells the semantic ranker which text fields to evaluate. The query then enables semantic ranking after hybrid retrieval: results = search_client.search( search_text=question, vector_queries=[vector_query], query_type="semantic", semantic_configuration_name=SEMANTIC_CONFIG, top=10, ) The important constraint is candidate recall. Semantic ranking does not search the corpus again. If the correct passage is absent from the hybrid top 50, the semantic stage cannot recover it. See 01_azure_ai_search_reranking.ipynb for the complete setup and query path. Test results for Azure AI Search These examples show that semantic reranking improves relevance selectively, not universally. It strongly helps the construction query, moving the correct passage from rank 4 to rank 1, but slightly degrades the Super Bowl and Tesla queries by one position. This reinforces that semantic ranking should be evaluated across a representative query set using aggregate metrics such as MRR or NDCG, rather than judged from a single result. Azure SQL Database: vector retrieval plus external Cohere reranking How it works. The Azure SQL notebook retrieves 20 candidates with exact cosine distance and sends their text to Cohere Rerank v4.0 Fast through sys.sp_invoke_external_rest_endpoint. The vector column and query vector must have the same dimensions. This repository uses 1,536-dimensional embeddings: SELECT TOP (@ candidate_count) context_id, title, content, 1 - VECTOR_DISTANCE( 'cosine', CAST(@ query_vector AS VECTOR(1536)), embedding ) AS similarity FROM dbo.documents ORDER BY similarity DESC; For reranking, we selected Cohere Rerank v4.0 Fast (Cohere-rerank-v4.0-fast), a fast version of Cohere’s fourth-generation relevance-ranking model. The model is deployed in Microsoft Foundry, where its Azure Direct inference endpoint is available in the deployment details within the Foundry portal. Azure SQL can call REST APIs directly using sp_invoke_external_rest_endpoint. Because Azure SQL allowlists Azure AI’s *.cognitiveservices.azure.com domain, we translate the equivalent Foundry endpoint from *.services.ai.azure.com while preserving the Cohere reranking route. from urllib.parse import urlsplit, urlunsplit def sql_compatible_endpoint(endpoint: str) -> str: """Convert an Azure Direct endpoint to Azure SQL's allowed hostname.""" parts = urlsplit(endpoint) if parts.hostname.endswith(".services.ai.azure.com"): resource = parts.hostname.removesuffix(".services.ai.azure.com") hostname = f"{resource}.cognitiveservices.azure.com" elif parts.hostname.endswith(".cognitiveservices.azure.com"): hostname = parts.hostname else: raise ValueError("Expected an Azure AI Services endpoint.") return urlunsplit( (parts.scheme, hostname, parts.path, parts.query, "") ) Then I defined a re-rank with cohere function, starting by loading the endpoint and setting the authentication: def rerank_with_cohere( cursor, question: str, candidates: list[dict], top_n: int = 10, ) -> list[dict]: """ Rerank candidate documents by calling Cohere through Azure SQL. Each candidate must contain a 'content' field. """ if not candidates: return [] sql_endpoint = sql_compatible_endpoint( os.environ["COHERE_RERANK_ENDPOINT"] ) model = os.environ["COHERE_RERANK_MODEL"] access_token = credential.get_token( "https://cognitiveservices.azure.com/.default" ).token headers = json.dumps({"Authorization": f"Bearer {access_token}"}) payload = json.dumps( { "model": model, "query": question, "documents": [row["content"] for row in candidates], "top_n": min(k, len(candidates)), }, ensure_ascii=False, ) cursor.execute( """ DECLARE @url NVARCHAR(4000) = CAST(? AS NVARCHAR(4000)); DECLARE @headers NVARCHAR(4000) = CAST(? AS NVARCHAR(4000)); DECLARE Payload NVARCHAR(MAX) = CAST(? AS NVARCHAR(MAX)); DECLARE Response NVARCHAR(MAX); DECLARE @status INT; EXEC @status = sys.sp_invoke_external_rest_endpoint @url = @url, @method = 'POST', @headers = @headers, Payload = Payload, @timeout = 60, @retry_count = 2, Response = Response OUTPUT; SELECT @status, Response; """, sql_endpoint, headers, payload, ) status, response_text = cursor.fetchone() if status != 0: raise RuntimeError(f"Reranker endpoint returned HTTP status {status}.") response = json.loads(response_text)["result"] You can see the complete implementation in the 02_azure_sql_reranking.ipynb notebook. Test results for Azure SQL Db Across the three sample questions, Cohere reranking consistently moved the correct SQuAD passage closer to the top: from rank 5 to 1 for the Super Bowl question, 3 to 2 for the Tesla question, and 8 to 1 for the construction question. These examples show how vector search provides a strong candidate set, while reranking applies deeper query-document relevance scoring to improve the final ordering. The results are illustrative rather than a complete quality benchmark, so broader evaluation across many queries is still recommended. Azure Database for PostgreSQL flexible server: pgvector, SQL RRF, and an optional model How it works: PostgreSQL makes the pipeline components explicit. The notebook uses pgvector for vector similarity, PostgreSQL full-text search for keyword retrieval, and SQL to implement RRF. Vector retrieval uses cosine distance: SELECT context_id, title, content, 1 - (embedding <= > % (query_vector) s:: vector) AS similarity FROM squad_docs ORDER BY embedding <= > % (query_vector) s:: vector LIMIT % (candidate_count) s; The hybrid query independently ranks vector and keyword hits, then combines positions rather than raw scores: SELECT d.context_id, COALESCE(1.0 / (60 + v.rank), 0) + COALESCE(1.0 / (60 + k.rank), 0) AS rrf_score FROM squad_docs AS d LEFT JOIN vector_hits AS v USING (context_id) LEFT JOIN keyword_hits AS k USING (context_id) WHERE v.context_id IS NOT NULL OR k.context_id IS NOT NULL ORDER BY rrf_score DESC; This is not a built-in PostgreSQL RRF operator. It is transparent, hand-written SQL over native retrieval primitives, which makes weighting and debugging flexible but leaves implementation and tuning with the application team. The notebook's optional learned stage sends the vector candidates from Python to a Foundry deployment of Cohere Rerank v4.0 Fast. This path was chosen because the tested Flexible Server azure_ai extension version expected the older serverless reranking endpoint contract. Microsoft documentation still describes azure_ai.rank() as a preview function whose default model is Cohere Rerank v3.5, even though that model retired on May 14, 2026. Treat this as a version-specific compatibility issue and verify current extension behavior before selecting an architecture. Azure HorizonDB is a different product path. Its AI Model Management feature can provision Cohere Rerank v4.0 Fast as default-reranker, but that management feature is currently a limited preview. It should not be described as a generally available Flexible Server capability. See 03_azure_postgres_reranking.ipynb for the full SQL and optional external model path. Test results for Azure SQL for PostgreSQL Flexible Server The tests show that PostgreSQL vector search provides a useful candidate set, SQL RRF can substantially improve results when keyword evidence is strong, and the Cohere semantic reranker is the most consistent overall: it moved the correct passage to rank 1 in two tests and from rank 3 to rank 2 in the Tesla test. RRF produced the biggest gain for the construction question, moving the correct passage from outside the vector top five to rank 1, but did not improve every query. The scores across stages are not directly comparable because cosine similarity, RRF score, and Cohere relevance use different scales. Azure Cosmos DB for NoSQL: hybrid search with built-in RRF How it works: Azure Cosmos DB for NoSQL supports native hybrid ranking with VectorDistance, FullTextScore, and RRF inside ORDER BY RANK: SELECT TOP K C.context_id, c.title, c.text FROM c ORDER BY RANK RRF( VectorDistance(c.vector, @query_vector), FullTextScore(c.text, @term1, @term2, @term3) ) The notebook extracts distinct terms from the question before building the full-text part of the query. That token selection is application logic and can materially affect the hybrid ranking, so production evaluation should test analyzers, languages, term extraction, and optional RRF weights. Cosmos DB Semantic Reranker is an SDK-integrated preview feature. The application first runs a query, serializes the resulting documents, and submits those documents with the user's context string: result = container.semantic_rerank( context=question, documents=documents, options={ "return_documents": False, "top_k": min(k, len(documents)), "sort": True, "document_type": "json", "target_paths": "title,text", }, ) The service accepts at most 50 documents per rerank call and returns relevance scores from 0 to 1, plus inference latency and token usage. It uses the Microsoft semantic ranking model also used by Azure AI Search. The reranking call requires Microsoft Entra authentication, the appropriate Semantic Reranker role, and an account-linked inference endpoint. The 04_azure_cosmosdb_reranking.ipynb in the shared repo contains and end-to-end implementation. Test results for Azure Cosmos Db The results show that vector search provides a strong baseline, while hybrid RRF and semantic reranking improve different queries in different ways. Hybrid RRF helps when exact keywords matter, moving the construction answer into the top results, while the semantic reranker delivers the strongest overall ordering, promoting the correct construction passage from hybrid rank 3 to rank 1 and improving the Super Bowl answer from rank 5 to rank 2. However, it does not always place the gold passage first, as seen in the Tesla example, confirming that reranking improves relevance but is query-dependent and should be evaluated across a larger test set. What the examples do and do not show The four services expose different ownership boundaries: • Azure AI Search owns hybrid fusion and learned semantic ranking inside the search service. • Azure SQL owns vector retrieval and outbound REST invocation in this example, while Foundry owns model inference. • PostgreSQL supplies vector and full-text primitives; the application owns the RRF SQL and optional Cohere call. • Cosmos DB provides native hybrid RRF and integrates a separate preview inference call through its SDK. Across three selected questions, the known source passage often moved substantially. That supports the practical value of testing a second-stage ranker. It does not prove that semantic reranking always improves top-1 accuracy, that RRF is universally beneficial, or that scores from different stages can be compared directly. Cosine similarity, RRF score, Azure AI Search reranker score, Cohere relevance, and Cosmos DB semantic relevance all have different definitions and scales. Compare rank positions and task-level metrics, not raw values across systems. Turn the demonstration into an evaluation For a production RAG system, convert the notebook pattern into a repeatable evaluation harness: Build a representative labeled query set from real user tasks. Freeze corpus, chunking, embedding model, dimensions, and candidate counts for each run. Record ranks after retrieval, fusion, and learned reranking. Measure Recall@k or Hit@k to verify that retrieval finds relevant evidence. Measure Mean Reciprocal Rank (MRR) when the position of the first relevant result matters. Use NDCG when judgments include multiple passages or graded relevance. Record latency percentiles, inference usage, request cost, and failure rates. Evaluate the generated answer separately for correctness, citation support, and refusal behavior. Also test the operational cases that a three-question demonstration cannot cover: empty keyword results, missing gold passages, long documents, multilingual text, filters, partial outages, token expiration, throttling, model retirement, and low-confidence scores. Practical guidance Retrieve broadly enough that the correct evidence can reach the learned stage. Use RRF when vector and keyword retrieval provide complementary signals. Rerank a bounded candidate set, commonly 20 to 50 passages, and measure the latency cost. Keep citations and source identifiers through every rank transformation. Version the corpus, embedding model, dimensions, query set, and reranker deployment. Do not hard-code assumptions about model endpoints or lifecycle dates. Verify current service documentation and the deployed extension or SDK version. Add thresholds or fallback behavior only after calibrating scores on your own data. Judge the full RAG chain. Better passage order is valuable only when it improves grounded answers for users. Vector search is built to find plausible candidates quickly. Rank fusion can reconcile retrieval signals, and a learned reranker can decide which candidates best address the question. The right architecture depends on where your data lives, which service boundaries you want to operate, and what your evaluation says about quality, latency, and cost. Resources Companion repository Azure AI Search semantic ranker Azure SQL VECTOR_DISTANCE Azure SQL sp_invoke_external_rest_endpoint Azure Database for PostgreSQL AI functions Microsoft Foundry model retirement schedule Azure Cosmos DB hybrid search Azure Cosmos DB Semantic Reranker SQuAD dataset card Dataset attribution Rajpurkar, P., Zhang, J., Lopyrev, K., and Liang, P. (2016). SQuAD: 100,000+ Questions for Machine Comprehension of Text. EMNLP 2016. SQuAD 1.1 is distributed under CC BY-SA 4.0.AI Gateway tier of API Management now in public preview
Today, we are introducing the AI Gateway tier of Azure API Management, now in public preview. It gives platform teams a purpose-built experience built specifically for AI workloads - publishing and governing models and MCP servers. Controls are configured through policy cards rather than XML and expressions, and the portal experience and control plane are structured around models, MCP servers, and tools rather than APIs. (For brevity, we refer to the AI Gateway tier as AI Gateway throughout the rest of this article.) AI Gateway is built on Azure API Management, bringing proven operational capabilities to AI workloads. The resource runs in your subscription, uses your Entra tenant, and sends telemetry to destinations you control. The operating model will be familiar to existing API Management customers, but the interface is built around AI workloads. The AI Gateway tier is intended for teams that want this focused experience; other API Management tiers remain the right choice when organizations also need general-purpose API management or capabilities not included in the AI Gateway experience. A practical model for platform teams The AI Gateway gives platform teams a shared place to manage models, MCP servers, policies, and observability destinations, with access controlled through Azure RBAC. For example, a central platform group can connect a set of approved models and tools and publish them for application teams. The application teams can test those assets in the test console and build against them without routing every change through the central group. The platform group still owns the shared guardrails and can see how the assets are being used. After an asset is published, developers can create a named runtime key and begin calling the gateway immediately. Bring the models and tools you already use Most organizations don't standardize on a single model provider. Different models are selected based on quality, latency, cost, geography, or specialized capabilities. The preview supports models from Microsoft Foundry including OpenAI, Anthropic, Mistral, and other Foundry hosted models, as well as models hosted in AWS Bedrock, Google Vertex AI, OpenAI, and Anthropic. A guided wizard simplifies importing models from Microsoft Foundry. Other providers can be added by configuring a connection, with backend authentication configured as part of that connection. All published models are available under the same stable endpoint. Applications continue to use supported API formats such as OpenAI Chat Completions and Responses or Anthropic Messages directly or via SDKs. The AI Gateway extends governance beyond models to the MCP servers and tools agents use to interact with enterprise systems. You can expose an existing MCP server over SSE or Streamable HTTP, turn all or selected operations from a REST API into an MCP server by uploading its OpenAPI specification, or use more than 1,400 connector-backed tools from the Power Platform and Logic Apps library. You can also federate multiple MCP servers behind a single server, so an agent connects once and sees the tools across those servers. Backend authentication supports an API key, OAuth client credentials, managed identity, or mTLS. Governance that's built in Organizations need consistent governance across models and MCP servers without requiring every application team to implement those capabilities independently. The AI Gateway portal presents governance policies through an intuitive card-based experience rather than requiring policy XML. The same policies are expressed as JSON properties, making them easy to manage as infrastructure as code and to audit and enforce across a fleet with Azure Policy. In the public preview, those cards cover request and token rate limits, token quotas, Azure AI Content Safety, and fallback to a secondary model. Policies are applied per asset, making it clear which controls protect each model or MCP server. OpenTelemetry-based token metrics The AI Gateway emits token-usage metrics through OpenTelemetry, with attributes following GenAI and cloud semantic conventions. Metrics can be sent to Application Insights, Datadog, Splunk, Grafana Cloud, or another OTLP endpoint. The portal provides a monitoring view over Application Insights data. Better together: Microsoft Foundry and AI Gateway With AI Gateway, teams can extend the same governance controls, for example token rate limits and quotas, across models hosted in Microsoft Foundry and models hosted elsewhere. Foundry and non-Foundry models are published through gateway-managed endpoints, giving applications and agents a consistent way to access governed models regardless of where they are hosted. Foundry-hosted agents can consume curated sets of tools from Foundry toolboxes, with access to the underlying MCP servers and APIs governed through AI Gateway. Together, Microsoft Foundry and AI Gateway cover the enterprise application lifecycle: Foundry for building and running AI applications, and AI Gateway for publishing, governing, and observing models, tools, and MCP servers across your AI estate. The new AI Gateway tier will soon be available through the gateway experience in Microsoft Foundry portal. We are working toward a seamless, integrated AI Gateway experience within Foundry portal and will share more about that work separately. Available today in public preview The AI Gateway tier is available today at no cost in public preview in East US 2 and Sweden Central. Pricing will be shared separately. To provision a resource, add a model or MCP server, and make a first call click this to go to the AI Gateway tier portal and try it. If you prefer to start from code, use a sample to deploy all the required resources for a Foundry-hosted agent configured to access its model and tools through AI Gateway. We look forward to your feedback as we continue to rapidly evolve AI Gateway.5.4KViews4likes9Comments