azure app service
439 TopicsStrapi on App Service: Quick start
In this quick start guide, you will learn how to create and deploy your first Strapi site on Azure App Service Linux, using Azure Database for MySQL or PostgreSQL, along with other necessary Azure resources. This guide utilizes an ARM template to install the required resources for hosting your Strapi application.2.3KViews1like2CommentsPart 3: Client-Side Multi-Agent Orchestration on Azure App Service with Microsoft Agent Framework
In Part 2 of this series, I showed you how to build sophisticated multi-agent systems on Azure App Service using Azure AI Foundry Agents—server-side managed agents that run as Azure resources. Now I want to show you another alternative that gives you full control over agent orchestration, chat history management, and provider flexibility: client-side agents using ChatClientAgent. But this alternative raises an important question: How do you choose between client-side and server-side agents? This is an important question that points to a fundamental choice in Agent Framework: client-side agents vs. server-side agents. I'm not going to go into extreme detail here; my goal for this post is to show you how to build client-side multi-agent systems with ChatClientAgent and Azure App Service, but I will highlight the key differences and trade-offs that are going through my mind when considering this to help you make an informed decision. In Part 2, I mentioned: "In my next blog post, I'll demonstrate an alternative approach using a different agent type—likely the Azure OpenAI ChatCompletion agent type—which doesn't create server-side Foundry resources. Instead, you orchestrate the agent behavior yourself while still benefiting from the Agent Framework's unified programming model." Today, I'm delivering on that promise! We're going to rebuild the same travel planner sample using ChatClientAgent—a client-side agent type that gives you complete control over orchestration, chat history, and agent lifecycle. In this post, we'll explore: ✅ Client-side agent orchestration with full workflow control ✅ ChatClientAgent architecture and implementation patterns ✅ When to choose client-side vs. server-side agents ✅ How Azure App Service supports both approaches equally well ✅ Managing chat history your way (Cosmos DB, Redis, or any storage you choose) 🔗 Full Sample Code: https://github.com/Azure-Samples/app-service-maf-openai-travel-agent-dotnet The Key Question: Who's in Charge? When building multi-agent systems with Agent Framework, you face a fundamental architectural decision. Microsoft Agent Framework supports multiple agent types, but the choice typically comes down to: Server-Side (Foundry Agents - Part 2) Azure AI Foundry manages agent lifecycle, threads, and execution Agents exist as Azure resources in your AI Project Conversation history stored in Foundry threads Built-in orchestration patterns and features Client-Side (ChatClientAgent - This Post) Your application code manages agent lifecycle and orchestration Agents are C# objects created on-demand Conversation history stored wherever you choose (Cosmos DB, Redis, etc.) You write the orchestration logic yourself Both approaches run well on Azure App Service—the platform doesn't care which agent type you use. What matters is which approach fits your requirements better. What's Different: ChatClientAgent Architecture Let's see what changes when you switch from Foundry agents to ChatClientAgent. The Same Multi-Agent Workflow Both samples implement the exact same travel planner with 6 specialized agents: Currency Converter Agent - Real-time exchange rates Weather Advisor Agent - Forecasts and packing tips Local Knowledge Agent - Cultural insights Itinerary Planner Agent - Day-by-day schedules Budget Optimizer Agent - Cost allocation Coordinator Agent - Final assembly The agents collaborate through the same 4-phase workflow: Phase 1: Parallel information gathering (Currency + Weather + Local) Phase 2: Itinerary planning Phase 3: Budget optimization Phase 4: Final assembly Same workflow, different execution model. How ChatClientAgent Works Here's the architecture stack for the client-side approach: The architecture shows: Your Application Code: TravelPlanningWorkflow orchestrating 6 ChatClientAgents with client-side chat history Microsoft.Agents.AI: ChatClientAgent wrapper adding instructions and tools Microsoft.Extensions.AI: IChatClient abstraction with Azure OpenAI implementation Azure Services: Azure OpenAI, Cosmos DB for chat history, and external APIs Key components: TravelPlanningWorkflow - Your orchestration code that coordinates agent execution ChatClientAgent - Agent Framework wrapper that adds instructions and tools to IChatClient IChatClient - Standard abstraction from Microsoft.Extensions.AI Client-Side Chat History - Dictionary storing conversation per agent (you manage this!) Azure OpenAI - Direct chat completion API calls (no AI Project endpoint needed) Cosmos DB - Your choice for chat history persistence Implementation: BaseAgent Pattern Here's how you create a ChatClientAgent in code: public abstract class BaseAgent : IAgent { protected readonly ChatClientAgent Agent; protected abstract string AgentName { get; } protected abstract string Instructions { get; } // Constructor for simple agents without tools protected BaseAgent( ILogger logger, IOptions<AgentOptions> options, IChatClient chatClient) { Agent = new ChatClientAgent(chatClient, new ChatClientAgentOptions { Name = AgentName, Instructions = Instructions }); } // Constructor for agents with tools (weather, currency APIs) protected BaseAgent( ILogger logger, IOptions<AgentOptions> options, IChatClient chatClient, ChatOptions chatOptions) { Agent = new ChatClientAgent(chatClient, new ChatClientAgentOptions { Name = AgentName, Instructions = Instructions, ChatOptions = chatOptions // Tools via AIFunctionFactory }); } public async Task<ChatMessage> InvokeAsync( IList<ChatMessage> chatHistory, CancellationToken cancellationToken = default) { var response = await Agent.RunAsync( chatHistory, thread: null, options: null, cancellationToken); return response.Messages.LastOrDefault() ?? new ChatMessage(ChatRole.Assistant, "No response generated."); } } What's happening here? You create a ChatClientAgent by wrapping an IChatClient You provide instructions (the agent's system prompt) Optionally, you provide tools via ChatOptions (using AIFunctionFactory ) When you call RunAsync , you pass the chat history yourself The agent returns a response, and you decide what to do with the chat history Compare this to Foundry agents where you create the agent once in Azure AI Foundry, and the platform manages threads and execution for you. Client-Side Chat History Management One of the biggest differences is you control the chat history: public class WorkflowState { // Each agent gets its own conversation history public Dictionary<string, List<ChatMessage>> AgentChatHistories { get; set; } = new(); public List<ChatMessage> GetChatHistory(string agentType) { if (!AgentChatHistories.ContainsKey(agentType)) { AgentChatHistories[agentType] = new List<ChatMessage>(); } return AgentChatHistories[agentType]; } } Workflow orchestration: // Phase 1: Currency Converter Agent var currencyChatHistory = state.GetChatHistory("CurrencyConverter"); currencyChatHistory.Add(new ChatMessage(ChatRole.User, $"Convert {request.Budget} {request.Currency} to local currency for {request.Destination}")); var currencyResponse = await _currencyAgent.InvokeAsync(currencyChatHistory, cancellationToken); currencyChatHistory.Add(currencyResponse); // You manage the history! // Store in workflow state for downstream agents state.AddToContext("CurrencyInfo", currencyResponse.Text ?? ""); Benefits: Store chat history in Cosmos DB, Redis, SQL, or any data store Query conversation history with your own logic Implement custom retention policies Export chat logs for analytics or compliance With Foundry agents, chat history lives in Foundry threads—you don't directly control where or how it's stored. This may be fine for many scenarios, but if you need custom storage or compliance, client-side management is powerful. Tool Integration with AIFunctionFactory External API tools (weather, currency) are registered as C# methods: // Weather Service public class NWSWeatherService : IWeatherService { [Description("Get weather forecast for a US city")] public async Task<WeatherForecast> GetWeatherAsync( [Description("City name (e.g., 'San Francisco')")] string city, [Description("State code (e.g., 'CA')")] string state, CancellationToken cancellationToken = default) { // Implementation calls NWS API } } // Register as tools with ChatClientAgent var weatherTools = AIFunctionFactory.Create(weatherService); var chatOptions = new ChatOptions { Tools = weatherTools }; var agent = new ChatClientAgent(chatClient, new ChatClientAgentOptions { Name = "WeatherAdvisor", Instructions = "Provide weather forecasts and packing recommendations...", ChatOptions = chatOptions }); The agent can now call GetWeatherAsync via function calling—same capability as Foundry agents, but configured in code instead of the portal. Why Choose Client-Side Agents (ChatClientAgent)? Here's when ChatClientAgent shines: ✅ Full Orchestration Control You write the workflow logic: // Phase 1: Run 3 agents in parallel (your code!) var currencyTask = GatherCurrencyInfoAsync(request, state, progress, cancellationToken); var weatherTask = GatherWeatherInfoAsync(request, state, progress, cancellationToken); var localTask = GatherLocalKnowledgeAsync(request, state, progress, cancellationToken); await Task.WhenAll(currencyTask, weatherTask, localTask); // Phase 2: Sequential itinerary planning (your code!) await PlanItineraryAsync(request, state, progress, cancellationToken); With Foundry agents, orchestration patterns are limited to what the platform provides. ✅ Cost-Effective No separate agent infrastructure: ChatClientAgent: Pay only for Azure OpenAI API calls Foundry Agents: Pay for Azure OpenAI + AI Project resources + agent storage For high-volume scenarios, this can add up to significant savings. ✅ DevOps-Friendly Everything in code: Agent definitions tracked in Git Testable with unit tests CI/CD pipelines deploy everything together No manual portal configuration steps Infrastructure as Code (Bicep) covers all resources ✅ Flexible Chat History Store conversations your way: Cosmos DB for global distribution and rich queries Redis for ultra-low latency caching SQL Database for complex relational queries Blob Storage for long-term archival Custom encryption and retention policies ✅ Provider Flexibility Works with any IChatClient: Azure OpenAI (this sample) OpenAI directly Local models via Ollama Azure AI Foundry model catalog Custom chat implementations Switching providers is just a configuration change—no agent re-creation needed. ✅ Multi-Agent Coordination Patterns Implement complex workflows: Parallel execution (Phase 1 in our sample) Sequential dependencies (Phase 2-4) Conditional branching based on agent responses Agent-to-agent negotiation Hierarchical supervisor patterns Custom retry logic per agent You have complete freedom to orchestrate however your scenario requires. Why Choose Server-Side Agents (Azure AI Foundry)? To be fair, Foundry agents from Part 2 have their own advantages and this post isn't about dismissing them. They are a powerful option for many scenarios. Here are some reasons to choose Foundry agents: ✅ Managed Lifecycle Platform handles the heavy lifting: Agents persist as Azure resources Threads automatically manage conversation state Runs track execution progress server-side No orchestration code to write or maintain ✅ Built-In Features Rich capabilities out of the box: File search for RAG scenarios Code interpreter for data analysis Automatic conversation threading Built-in retry and error handling ✅ Portal UI Configure without code: Create agents in Azure AI Foundry portal Test agents interactively View conversation threads and runs Adjust instructions without redeployment ✅ Less Code Simpler for basic scenarios: // Foundry Agent (Part 2 sample) var agent = await agentsClient.CreateAgentAsync( "gpt-4o", instructions: "You are a travel planning expert...", tools: new List<ToolDefinition> { new FunctionTool(...) }); var thread = await agentsClient.CreateThreadAsync(); var run = await agentsClient.CreateRunAsync(thread.Id, agent.Id); No need to manage chat history, orchestration logic, or tool registration in code. When to Choose Which Approach Here's my take on a decision guide. This isn't exhaustive, but it covers key considerations. Others may disagree based on their priorities, but this is how I think about it: Requirement ChatClientAgent Foundry Agents Complex multi-agent workflows ✅ Full control ⚠️ Limited patterns Custom chat history storage ✅ Any data store ❌ Foundry threads only Cost optimization ✅ LLM calls only ⚠️ + Infrastructure Code-first DevOps ✅ Everything in Git ⚠️ Portal config needed Provider flexibility ✅ Any IChatClient ⚠️ Azure only Built-in RAG (file search) ❌ DIY ✅ Built-in Portal UI for testing ❌ Code only ✅ Full UI Quick prototypes ⚠️ More code ✅ Fast setup Learning curve ⚠️ More concepts ✅ Guided setup Use ChatClientAgent when: You need complex multi-agent coordination Cost optimization is important You want full control over orchestration Code-first DevOps is a priority You need custom chat history management Use Foundry Agents when: Simple single-agent or basic multi-agent scenarios You want built-in RAG and file search Portal-based configuration is preferred Quick prototyping and experimentation Managed infrastructure over custom code Azure App Service: Perfect for Both Here's the great part: Azure App Service supports both approaches equally well. The Same Architecture Both samples use identical infrastructure. What's the same: ✅ Async request-reply pattern (202 Accepted → poll status) ✅ Service Bus for reliable message delivery ✅ Cosmos DB for task state with 24-hour TTL ✅ WebJob for background processing ✅ Managed Identity for authentication ✅ Premium App Service tier for Always On What's different: ChatClientAgent: Azure OpenAI endpoint directly ( https://ai-xyz.openai.azure.com/ ) Foundry Agents: AI Project endpoint ( https://ai-xyz.services.ai.azure.com/api/projects/proj-xyz ) ChatClientAgent: Chat history in Cosmos DB (your control) Foundry Agents: Chat history in Foundry threads (platform managed) Azure App Service doesn't care which you choose. It just runs your .NET code, processes messages from Service Bus, and stores state in Cosmos DB. The agent execution model is an implementation detail. You can easily switch between approaches without changing your hosting platform, and even use a hybrid approach if desired. Get Started Today Ready to try client-side multi-agent orchestration on Azure App Service? 🔗 GitHub Repository: https://github.com/Azure-Samples/app-service-maf-openai-travel-agent-dotnet The repository includes: ✅ Complete .NET 9 source code with 6 specialized ChatClientAgents ✅ Infrastructure as Code (Bicep) for one-command deployment ✅ Web UI with real-time progress tracking ✅ Comprehensive README and architecture documentation ✅ External API integrations (weather, currency) ✅ Client-side chat history management with Cosmos DB Deploy in Minutes # Clone the repository git clone https://github.com/Azure-Samples/app-service-maf-openai-travel-agent-dotnet.git cd app-service-maf-openai-travel-agent-dotnet # Login to Azure azd auth login # Provision infrastructure and deploy the API azd up This provisions: Azure App Service (P0v4 Premium Windows) Azure Service Bus (message queue) Azure Cosmos DB (state + chat history storage) Azure AI Services (AI Services resource) GPT-4o model deployment (GlobalStandard 50K TPM) Then manually deploy the WebJob following the README instructions. Compare with Part 2 Want to see the differences firsthand? Deploy both samples: Part 2 - Server-Side Foundry Agents: 🔗 https://github.com/Azure-Samples/app-service-maf-workflow-travel-agent-dotnet Part 3 - Client-Side ChatClientAgent (this post): 🔗 https://github.com/Azure-Samples/app-service-maf-openai-travel-agent-dotnet Same travel planner, same workflow, same results—different execution model. Try both and see which fits your needs! Key Takeaways ✅ Microsoft Agent Framework offers choice: Client-side (ChatClientAgent) vs. Server-side (Foundry Agents) ✅ ChatClientAgent gives you full control: Orchestration, chat history, agent lifecycle—you manage it all in code ✅ Foundry Agents give you convenience: Managed infrastructure, built-in features, portal UI—let the platform handle the details ✅ Azure App Service supports both equally: Same async request-reply pattern, same WebJob architecture, same infrastructure ✅ Pick the right tool for your needs: Complex coordination and cost control → ChatClientAgent. Simple scenarios and managed infrastructure → Foundry Agents. Whether you choose client-side or server-side agents, Azure App Service provides the perfect platform for long-running AI workloads—reliable, scalable, and fully managed. What's Next? This completes our three-part series on building AI agents with Microsoft Agent Framework on Azure App Service: Part 1: Introduction to Agent Framework and async request-reply pattern Part 2: Multi-agent systems with server-side Foundry Agents Part 3 (this post): Client-side multi-agent orchestration with ChatClientAgent What would you like to see next? More advanced orchestration patterns? Integration with other Azure services? Let me know in the comments what you'd like to learn about next and I'll do my best to deliver!208Views1like1CommentLow-Light Image Enhancer (Python + OpenCV) on Azure App Service
Low-light photos are everywhere: indoor team shots, dim restaurant pics, grainy docs. This post shows a tiny Python app (Flask + OpenCV) that fixes them with explainable image processing—not a heavyweight model. We’ll walk the code that does the real work (CLAHE → gamma → brightness → subtle saturation) and deploy it to Azure App Service for Linux. What you’ll build A Flask web app that accepts an image upload, runs a fast enhancement pipeline (CLAHE → gamma → brightness → subtle saturation), and returns base64 data URIs for an instant before/after view in the browser—no storage required for the basic demo. Architecture at a glance Browser → /enhance (multipart form): sends an image + optional tunables (clip_limit, gamma, brightness). Flask → Enhancer: converts the upload to a NumPy RGB array and calls LowLightEnhancer.enhance_image(...). Response: returns JSON with original and enhanced images as base64 PNG data URIs for immediate rendering. Prerequisites An Azure subscription Azure Developer CLI (azd) installed (Optional) Python 3.9+ on your dev box for reading the code or extending it Deploy with azd git clone https://github.com/Azure-Samples/appservice-ai-samples.git cd appservice-ai-samples/lowlight-enhancer azd init azd up When azd up finishes, open the printed URL, upload a low-light photo, and compare the result side-by-side. Code walkthrough (the parts that matter) 1) Flask surface area (app.py) File size guard: app = Flask(__name__) app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16 MB Two routes: GET / - renders the simple UI POST /enhance - the JSON API the UI calls via XHR/fetch Parameter handling with sane defaults: clip_limit = float(request.form.get('clip_limit', 2.0)) gamma = float(request.form.get('gamma', 1.2)) brightness = float(request.form.get('brightness', 1.1)) 2) Zero-temp-file processing + data-URI response (app.py) process_uploaded_image keeps the hot path tight: convert to RGB → enhance → convert both versions to base64 PNG and return them inline. def process_uploaded_image(file_storage, clip_limit=2.0, gamma=1.2, brightness=1.1): # PIL → NumPy (RGB) img_pil = Image.open(file_storage) if img_pil.mode != 'RGB': img_pil = img_pil.convert('RGB') img_array = np.array(img_pil) # Enhance enhanced = LowLightEnhancer().enhance_image( img_array, clip_limit=clip_limit, gamma=gamma, brightness_boost=brightness ) # Back to base64 data URIs for instant display def pil_to_base64(pil_img): buf = io.BytesIO(); pil_img.save(buf, format='PNG') return base64.b64encode(buf.getvalue()).decode('utf-8') enhanced_pil = Image.fromarray(enhanced) return { 'original': f'data:image/png;base64,{pil_to_base64(img_pil)}', 'enhanced': f'data:image/png;base64,{pil_to_base64(enhanced_pil)}' } 3) The enhancement core (enhancer.py) LowLightEnhancer implements a classic pipeline that runs great on CPU: class LowLightEnhancer: def __init__(self): self.clip_limit = 2.0 self.tile_grid_size = (8, 8) def enhance_image(self, image, clip_limit=2.0, gamma=1.2, brightness_boost=1.1): # Normalize to RGB if the input came in as OpenCV BGR is_bgr = self._detect_bgr(image) rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) if is_bgr else image # 1) CLAHE on L-channel (LAB) for local contrast without color blowout lab = cv2.cvtColor(rgb, cv2.COLOR_RGB2LAB) l, a, b = cv2.split(lab) clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=self.tile_grid_size) l = clahe.apply(l) # 2) Gamma correction (perceptual brightness curve) l = self._apply_gamma_correction(l, gamma) # 3) Gentle overall lift l = np.clip(l * brightness_boost, 0, 255).astype(np.uint8) # Recombine + small saturation nudge for a natural look enhanced = cv2.cvtColor(cv2.merge([l, a, b]), cv2.COLOR_LAB2RGB) enhanced = self._boost_saturation(enhanced, factor=1.1) return cv2.cvtColor(enhanced, cv2.COLOR_RGB2BGR) if is_bgr else enhanced CLAHE on L (not RGB) avoids the “oversaturated neon” artifact common with naive histogram equalization. Gamma via LUT (below) is fast and lets you brighten mid-tones without crushing highlights. A tiny brightness multiplier brings the image up just a bit after contrast/curve changes. A +10% saturation helps counter the desaturation that often follows brightening. 4) Fast gamma with a lookup table (enhancer.py) def _apply_gamma_correction(self, image, gamma: float) -> np.ndarray: inv_gamma = 1.0 / gamma table = np.array([((i / 255.0) ** inv_gamma) * 255 for i in range(256)], dtype=np.uint8) return cv2.LUT(image, table) Notes: With gamma = 1.2, inv_gamma ≈ 0.833 → curve brightens mid-tones (exponent < 1). cv2.LUT applies the 256-entry mapping efficiently across the image. 5) Bounded color pop: subtle saturation boost (enhancer.py) def _boost_saturation(self, image: np.ndarray, factor: float) -> np.ndarray: hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV).astype(np.float32) hsv[:, :, 1] = np.clip(hsv[:, :, 1] * factor, 0, 255) return cv2.cvtColor(hsv.astype(np.uint8), cv2.COLOR_HSV2RGB) Notes: Working in HSV keeps hue and brightness stable while gently lifting color. The clip to [0, 255] prevents out-of-gamut surprises. Tuning cheatsheet (which knob to turn, and when) Too flat / muddy → raise clip_limit from 2.0 → 3.0–4.0 (more local contrast). Still too dark → raise gamma from 1.2 → 1.4–1.6 (brightens mid-tones). Harsh or “crunchy” → lower clip_limit, or drop brightness_boost to 1.05–1.1. Colors feel washed out → increase saturation factor a touch (e.g., 1.1 → 1.15). What to try next Expose more controls in the UI (e.g., tile grid size, saturation factor). Persist originals/results to Azure Blob Storage and add shareable links. Add a background job for batch processing using the CLI helper. Conclusion The complete sample code and deployment templates are available in the appservice-ai-samples repository Ready to build your own AI chat app? Clone the repo and run azd up to get started in minutes! For more Azure App Service AI samples and best practices, check out the Azure App Service AI integration documentation85Views0likes0CommentsPart 2: Build Long-Running AI Agents on Azure App Service with Microsoft Agent Framework
Last week, I shared how to build long-running AI agents on Azure App Service with Microsoft Agent Framework. If you haven't seen that post yet, I would recommend starting there as this post builds on the foundations introduced there including getting started with Microsoft Agent Framework. The response so far was great, and one comment in particular stood out: "Thanks for the example. Nice job! Just curious (I still have to investigate the ins and outs of MAF) but why didn't you use the workflow pattern/classes of MAF? I thought that was meant to be the way to connect agents and let them cooperate (even in long running job situations)." — Michel_Schep Great question! You're absolutely right in questioning this—the initial sample I created was designed to demonstrate the async request-reply architecture for handling long-running operations on App Service with a single agent. Today, we're taking the next step: a multi-agent workflow sample that addresses exactly what you asked about and is the next leap in building agentic apps in the cloud. In this post, we'll explore: ✅ Building multi-agent systems with specialized, collaborating AI agents ✅ When to create agents in code vs. using Azure AI Foundry portal ✅ Orchestrating complex workflows with parallel and sequential execution ✅ Real-world patterns for production multi-agent applications 🔗 Full Sample Code: https://github.com/Azure-Samples/app-service-maf-workflow-travel-agent-dotnet Why Multi-Agent Systems? The single-agent pattern I showed last week works great for straightforward tasks. But real-world AI applications often need specialized expertise across different domains. That's where multi-agent systems shine. The Travel Planning Challenge Imagine planning a trip to Tokyo. You need: Currency expertise for budget conversion and exchange rates Weather knowledge for packing recommendations and seasonal planning Local insights about customs, culture, and etiquette Itinerary skills to create day-by-day schedules Budget optimization to allocate funds across categories Coordination to assemble everything into a cohesive plan With a single agent handling all of this, you get a "jack of all trades, master of none" situation. The prompts become complex, the agent loses focus, and results can be inconsistent. Enter Multi-Agent Workflows Instead of one generalist agent, we can create 6 or more specialized agents, each with a focused responsibility: Currency Converter Agent - Real-time exchange rates (Frankfurter API integration) Weather Advisor Agent - Forecasts and packing tips (National Weather Service API) Local Knowledge Agent - Cultural insights and customs Itinerary Planner Agent - Day-by-day activity scheduling Budget Optimizer Agent - Cost allocation and optimization Coordinator Agent - Final assembly and formatting Each agent has: 🎯 Clear, focused instructions specific to its domain 🛠️ Specialized tools (weather API, currency API) 📊 Defined inputs and outputs for predictable collaboration ✅ Testable behavior that's easy to validate Additionally, if you wanted to extend this even further, you could create even more agents and give some of your specialist agents even more knowledge by connecting additional tools and MCP servers. The possibilities are endless, and I hope this post inspires you to start thinking about what you can build and achieve. What Makes This Possible? Microsoft Agent Framework All of this is powered by Microsoft Agent Framework—a comprehensive platform for building, deploying, and managing AI agents that goes far beyond simple chat completions. Understanding Agent Framework vs. Other Approaches Before diving into the details, it's important to understand what Agent Framework is. Unlike frameworks like Semantic Kernel where you orchestrate AI behavior entirely in your application code with direct API calls, Agent Framework provides a unified abstraction for working with AI agents across multiple backend types. Agent Framework supports several agent types (see documentation): Simple agents based on inference services - Agents built on any IChatClient implementation, including: Azure OpenAI ChatCompletion Azure AI Foundry Models ChatCompletion OpenAI ChatCompletion and Responses Any other Microsoft.Extensions.AI.IChatClient implementation Server-side managed agents - Agents that live as Azure resources: Azure AI Foundry Agent (used in this sample) OpenAI Assistants Custom agents - Fully custom implementations of the AIAgent base class Proxy agents - Connections to remote agents via protocols like A2A In this sample, we use Azure AI Foundry Agents—the server-side managed agent type. When you use these Foundry agents: Agents are Azure resources - They exist on the server-side in Azure AI Foundry, not just as code patterns Execution happens on Foundry - Agent runs execute on Azure's infrastructure with built-in state management You get structured primitives - Agents, Threads, and Runs are first-class concepts with their own lifecycles Server-side persistence - Conversation history and context are managed by the platform This server-side approach is convenient because the platform manages state and execution for you. However, other agent types (like ChatCompletion-based agents) give you more control over orchestration while still benefiting from the unified Agent Framework programming model. In my next blog post, I'll demonstrate an alternative approach using a different agent type—likely the Azure OpenAI ChatCompletion agent type—which doesn't create server-side Foundry resources. Instead, you orchestrate the agent behavior yourself while still benefiting from the Agent Framework's unified programming model. If you're new to Agent Framework, here's what makes it special: 🔄 Persistent Agents: Server-side agents that maintain context across multiple interactions, not just one-off API calls 💬 Conversation Threads: Organized conversation history and state management that persists across agent runs 🎯 Agent Runs: Structured execution with progress tracking and lifecycle management—you can monitor exactly what your agents are doing 🔁 Multi-Turn Interactions: Complex workflows with iterative AI processing, where agents can refine and improve their outputs 🛠️ Tool Integration: Extensible function calling and integration capabilities—agents can call external APIs, execute code, and interact with real-world systems In our sample, Agent Framework handles: Creating and managing 6 specialized agents programmatically Maintaining conversation context as agents collaborate Tracking execution progress across workflow phases Managing agent lifecycle (creation, execution, cleanup) Integrating external APIs (weather, currency) seamlessly The beauty of Agent Framework is that it makes complex multi-agent orchestration feel natural. You focus on defining what your agents should do, and the framework handles the infrastructure, state management, and execution—all running on Azure AI Foundry with enterprise-grade reliability. The Multi-Agent Workflow Here's how these agents collaborate to create a comprehensive travel plan in the sample I put together: Execution Phases Phase 1: Parallel Information Gathering (10-40%) Currency, Weather, and Local Knowledge agents execute simultaneously No dependencies = maximum performance Results stored in workflow state for downstream agents Phase 2: Itinerary Planning (40-70%) Itinerary Planner uses context from all Phase 1 agents Weather data influences activity recommendations Local knowledge shapes cultural experiences Currency conversion informs budget-conscious choices Phase 3: Budget Optimization (70-90%) Budget Optimizer analyzes the proposed itinerary Allocates funds across categories (lodging, food, activities, transport) Provides cost-saving tips without compromising the experience Phase 4: Final Assembly (90-100%) Coordinator compiles all agent outputs Formats comprehensive travel plan with tips Returns structured, user-friendly itinerary Benefits of This Architecture ✅ Faster Execution: Parallel agents complete in ~30% less time ✅ Better Quality: Specialized agents produce more focused, accurate results ✅ Easy Debugging: Each agent's contribution is isolated and traceable ✅ Maintainable: Update one agent without affecting others ✅ Scalable: Add new agents (flight booking, hotel search) without refactoring ✅ Testable: Validate each agent independently with unit tests The Complete Architecture Here's how everything fits together on Azure App Service: This architecture builds on the async request-reply pattern from our previous post, adding: ✅ Multi-agent orchestration in the background worker ✅ Parallel execution of independent agents for performance ✅ Code-generated agents for production-ready DevOps ✅ External API integration (weather, currency) for real-world data ✅ Progress tracking across workflow phases (10% → 40% → 70% → 100%) Get Started Today Ready to build your own multi-agent workflows on Azure App Service? Try out the sample today! 🔗 GitHub Repository: https://github.com/Azure-Samples/app-service-maf-workflow-travel-agent-dotnet The repository includes: ✅ Complete .NET 9 source code with 6 specialized agents ✅ Infrastructure as Code (Bicep) for one-command deployment ✅ Complete web UI with real-time progress tracking ✅ Comprehensive README with architecture documentation ✅ External API integrations (weather, currency) Deploy in Minutes git clone https://github.com/Azure-Samples/app-service-maf-workflow-travel-agent-dotnet.git cd app-service-maf-workflow-travel-agent-dotnet azd auth login azd up The azd up command provisions: Azure App Service (P0v4 Premium) Azure Service Bus (message queue for async processing) Azure Cosmos DB (state storage with 24-hour TTL) Azure AI Foundry (AI Services + Project for Agent Framework) GPT-4o model deployment (GlobalStandard 50K TPM) Then manually deploy the WebJob following the README instructions. What's Next? Extend This Pattern This sample demonstrates production-ready patterns you can extend: 🛠️ Add More Specialized Agents Flight Expert Agent - Search and compare flight prices Hotel Specialist Agent - Find accommodations based on preferences Activity Planner Agent - Book tours, restaurants, events Transportation Agent - Plan routes, transit passes, car rentals 🤝 Implement Agent-to-Agent Communication Agents negotiate conflicting recommendations Hierarchical structures with supervisor agents Voting mechanisms for decision-making 🧠 Add Advanced Capabilities RAG (Retrieval Augmented Generation) for destination-specific knowledge bases Memory to remember user preferences across trips Vision models to analyze travel photos and recommend similar destinations Multi-language support for international travelers 📊 Production Enhancements Authentication - Microsoft Entra AD for user identity Application Insights - Distributed tracing and custom metrics VNet Integration - Private endpoints for security Auto-Scaling - Scale workers based on queue depth Webhooks - Notify users when their travel plan is ready Key Takeaways ✅ Multi-agent systems provide specialized expertise and better results than single generalist agents ✅ Azure App Service provides a simple, reliable platform for long-running multi-agent workflows ✅ Async request-reply pattern with Service Bus + Cosmos DB ensures scalability and resilience ✅ External API integration makes agents more useful with real-world data ✅ Parallel execution of independent agents dramatically improves performance Whether you're building travel planners, document processors, research assistants, or other AI-powered applications, multi-agent workflows on Azure App Service give you the flexibility and sophistication you need. Learn More Microsoft Agent Framework Documentation - Complete guide to Agent Framework Original Blog Post - Single-agent async patterns on App Service Azure App Service Best Practices - Production deployment patterns Async Request-Reply Pattern - Architecture guidance Azure App Service WebJobs - Background processing documentation We Want to Hear From You! Thanks again to Michel_Schep for the great question that inspired this follow-up sample! Have you built multi-agent systems with Agent Framework? Are you using Azure App Service to host your AI and intelligent apps? We'd love to hear about your experience in the comments below. Questions about multi-agent workflows on App Service? Drop a comment and our team will help you get started. Happy building! 🚀386Views1like0CommentsFollow-Up to ‘Important Changes to App Service Managed Certificates’: October 2025 Update
This post provides an update to the Tech Community article ‘Important Changes to App Service Managed Certificates: Is Your Certificate Affected?’ and covers the latest changes introduced since July 2025. With the November 2025 update, ASMC now remains supported even if the site is not publicly accessible, provided all other requirements are met. Details on requirements, exceptions, and validation steps are included below. Background Context to July 2025 Changes As of July 2025, all ASMC certificate issuance and renewals use HTTP token validation. Previously, public access was required because DigiCert needed to access the endpoint https://<hostname>/.well-known/pki-validation/fileauth.txt to verify the token before issuing the certificate. App Service automatically places this token during certificate creation and renewal. If DigiCert cannot access this endpoint, domain ownership validation fails, and the certificate cannot be issued. October 2025 Update Starting October 2025, App Service now allows DigiCert's requests to the https://<hostname>/.well-known/pki-validation/fileauth.txt endpoint, even if the site blocks public access. If there’s a request to create an App Service Managed Certificate (ASMC), App Service places the domain validation token at the validation endpoint. When DigiCert tries to reach the validation endpoint, App Service front ends present the token, and the request terminates at the front end layer. DigiCert's request does not reach the workers running the application. This behavior is now the default for ASMC issuance for initial certificate creation and renewals. Customers do not need to specifically allow DigiCert's IP addresses. Exceptions and Unsupported Scenarios This update addresses most scenarios that restrict public access, including App Service Authentication, disabling public access, IP restrictions, private endpoints, and client certificates. However, a public DNS record is still required. For example, sites using a private endpoint with a custom domain on a private DNS cannot validate domain ownership and obtain a certificate. Even with all validations now relying on HTTP token validation and DigiCert requests being allowed through, certain configurations are still not supported for ASMC: Sites configured as "Nested" or "External" endpoints behind Traffic Manager. Only "Azure" endpoints are supported. Certificates requested for domains ending in *.trafficmanager.net are not supported. Testing Customers can easily test whether their site’s configuration or set-up supports ASMC by attempting to create one for their site. If the initial request succeeds, renewals should also work, provided all requirements are met and the site is not listed in an unsupported scenario.898Views1like0CommentsExpanding the Public Preview of the Azure SRE Agent
We are excited to share that the Azure SRE Agent is now available in public preview for everyone instantly – no sign up required. A big thank you to all our preview customers who provided feedback and helped shape this release! Watching teams put the SRE Agent to work taught us a ton, and we’ve baked those lessons into a smarter, more resilient, and enterprise-ready experience. You can now find Azure SRE Agent directly in the Azure Portal and get started, or use the link below. 📖 Learn more about SRE Agent. 👉 Create your first SRE Agent (Azure login required) What’s New in Azure SRE Agent - October Update The Azure SRE Agent now delivers secure-by-default governance, deeper diagnostics, and extensible automation—built for scale. It can even resolve incidents autonomously by following your team’s runbooks. With native integrations across Azure Monitor, GitHub, ServiceNow, and PagerDuty, it supports root cause analysis using both source code and historical patterns. And since September 1, billing and reporting are available via Azure Agent Units (AAUs). Please visit product documentation for the latest updates. Here are a few highlights for this month: Prioritizing enterprise governance and security: By default, the Azure SRE Agent operates with least-privilege access and never executes write actions on Azure resources without explicit human approval. Additionally, it uses role-based access control (RBAC) so organizations can assign read-only or approver roles, providing clear oversight and traceability from day one. This allows teams to choose their desired level of autonomy from read-only insights to approval-gated actions to full automation without compromising control. Covering the breadth and depth of Azure: The Azure SRE Agent helps teams manage and understand their entire Azure footprint. With built-in support for AZ CLI and kubectl, it works across all Azure services. But it doesn’t stop there—diagnostics are enhanced for platforms like PostgreSQL, API Management, Azure Functions, AKS, Azure Container Apps, and Azure App Service. Whether you're running microservices or managing monoliths, the agent delivers consistent automation and deep insights across your cloud environment. Automating Incident Management: The Azure SRE Agent now plugs directly into Azure Monitor, PagerDuty, and ServiceNow to streamline incident detection and resolution. These integrations let the Agent ingest alerts and trigger workflows that match your team’s existing tools—so you can respond faster, with less manual effort. Engineered for extensibility: The Azure SRE Agent incident management approach lets teams reuse existing runbooks and customize response plans to fit their unique workflows. Whether you want to keep a human in the loop or empower the Agent to autonomously mitigate and resolve issues, the choice is yours. This flexibility gives teams the freedom to evolve—from guided actions to trusted autonomy—without ever giving up control. Root cause, meet source code: The Azure SRE Agent now supports code-aware root cause analysis (RCA) by linking diagnostics directly to source context in GitHub and Azure DevOps. This tight integration helps teams trace incidents back to the exact code changes that triggered them—accelerating resolution and boosting confidence in automated responses. By bridging operational signals with engineering workflows, the agent makes RCA faster, clearer, and more actionable. Close the loop with DevOps: The Azure SRE Agent now generates incident summary reports directly in GitHub and Azure DevOps—complete with diagnostic context. These reports can be assigned to a GitHub Copilot coding agent, which automatically creates pull requests and merges validated fixes. Every incident becomes an actionable code change, driving permanent resolution instead of temporary mitigation. Getting Started Start here: Create a new SRE Agent in the Azure portal (Azure login required) Blog: Announcing a flexible, predictable billing model for Azure SRE Agent Blog: Enterprise-ready and extensible – Update on the Azure SRE Agent preview Product documentation Product home page Community & Support We’d love to hear from you! Please use our GitHub repo to file issues, request features, or share feedback with the team4.6KViews2likes3CommentsAnnouncing the Public Preview of the New App Service Quota Self-Service Experience
Update 10/30/2025: The App Service Quota Self-Service experience is back online after a short period where we were incorporating your feedback and making needed updates. As this is public preview, availability and features are subject to change as we receive and incorporate feedback. What’s New? The updated experience introduces a dedicated App Service Quota blade in the Azure portal, offering a streamlined and intuitive interface to: View current usage and limits across the various SKUs Set custom quotas tailored to your App Service plan needs This new experience empowers developers and IT admins to proactively manage resources, avoid service disruptions, and optimize performance. Quick Reference - Start here! If your deployment requires quota for ten or more subscriptions, then file a support ticket with problem type Quota following the instructions at the bottom of this post. If any subscription included in your request requires zone redundancy (note that most Isolated v2 deployments require ZR), then file a support ticket with problem type Quota following the instructions at the bottom of this post. Otherwise, leverage the new self-service experience to increase your quota automatically. Self-service Quota Requests For non-zone-redundant needs, quota alone is sufficient to enable App Service deployment or scale-out. Follow the provided steps to place your request. 1. Navigate to the Quotas resource provider in the Azure portal 2. Select App Service (Pubic Preview) Navigating the primary interface: Each App Service VM size is represented as a separate SKU. If the intention is to be able to scale up or down within a specific offering (e.g., Premium v3), then equivalent number of VMs need to be requested for each applicable size of that offering (e.g., request 5 instances for both P1v3 and P3v3). As with other quotas, you can filter by region, subscription, provider, or usage. Note that your portal will now show "App Service (Public Preview)" for the Provider name. You can also group the results by usage, quota (App Service VM type), or location (region). Current usage is represented as App Service VMs. This allows you to quickly identify which SKUs are nearing their quota limits. Adjustments can be made inline: no need to visit another page. This is covered in detail in the next section. Total Regional VMs: There is a SKU in each region called Total Regional VMs. This SKU summarizes your usage and available quota across all individual SKUs in that region. There are three key points about using Total Regional VMs. You should never request Total Regional VMs quota directly - it will automatically increase in response to your request for individual SKU quota. If you are unable to deploy a given SKU, then you must request more quota for that SKU to unblock deployment. For your deployment to succeed, you must have sufficient quota in the individual SKU as well as Total Regional VMs. If either usage is at its respective limit, then you will be unable to deploy and must request more of that individual SKU's quota to proceed. In some regions, Total Regional VMs appears as "0 of 0" usage and limit and no individual SKU quotas are shown. This is an indication that you should not interact with the portal to resolve any quota-related issues in this region. Instead, you should try the deployment and observe any error messages that arise. If any error messages indicate more quota is needed, then this must be requested by filing a support ticket with problem type Quota following the instructions at the bottom of this post so that App Service can identify and fix any potential quota issues. In most cases, this will not be necessary, and your deployment will work without requesting quota wherever "0 of 0" is shown for Total Regional VMs and no individual SKU quotas are visible. See the example below: 3. Request quota adjustments Clicking the pen icon opens a flyout window to capture the quota request: The quota type (App Service SKU) is already populated, along with current usage. Note that your request is not incremental: you must specify the new limit that you wish to see reflected in the portal. For example, to request two additional instances of P1v2 VMs, you would file the request like this: Click submit to send the request for automatic processing. How quota approvals work: Immediately upon submitting a quota request, you will see a processing dialog like the one shown: If the quota request can be automatically fulfilled, then no support request is needed. You should receive this confirmation within a few minutes of submission: If the request cannot be automatically fulfilled, then you will be given the option to file a support request with the same information. In the example below, the requested new limit exceeds what can be automatically granted for the region: 4. If applicable, create support ticket When creating a support ticket, you will need to repopulate the Region and App Service plan details; the new limit has already been populated for you. If you forget the region or SKU that was requested, you can reference them in your notifications pane: If you choose to create a support ticket, then you will interact with the capacity management team for that region. This is a 24x7 service, so requests may be created at any time. Once you have filed the support request, you can track its status via the Help + support dashboard. Known issues The self-service quota request experience for App Service is in public preview. Here are some caveats worth mentioning while the team finalizes the release for general availability: Closing the quota request flyout window will stop meaningful notifications for that request. You can still view the outcome of your quota requests by checking actual quota, but if you want to rely on notifications for alerts, then we recommend leaving the quota request window open for the few minutes that it is processing. Some SKUs are not yet represented in the quota dashboard. These will be added later in the public preview. The Activity Log does not currently provide a meaningful summary of previous quota requests and their outcomes. This will also be addressed during the public preview. As noted in the walkthrough, the new experience does not enable zone-redundant deployments. Quota is an inherently regional construct, and zone-redundant enablement requires a separate step that can only be taken in response to a support ticket being filed. Quota API documentation is being drafted to enable bulk non-zone redundant quota requests without requiring you to file a support ticket. Filing a Support Ticket If your deployment requires zone redundancy or contains many subscriptions, then we recommend filing a support ticket with issue type "Technical" and problem type "Quota": We want your feedback! If you notice any aspect of the experience that does not work as expected, or you have feedback on how to make it better, please use the comments below to share your thoughts!2KViews3likes3CommentsAdd Sidecars to Azure App Service for Linux—via GitHub Actions or Azure Pipelines
Sidecars on Azure App Service let you run helper containers (telemetry, OTEL/monitoring agents, lightweight APIs, caches, AI helpers) alongside your main app—same app, shared lifecycle, localhost networking—without changing your core code. We’ve published ready-to-use templates for both GitHub Actions and Azure Pipelines (VSTS) so you can pick your CI/CD flavor and ship. Pick your CI/CD GitHub Actions: Two sample workflows—one for built-in runtimes (code-based apps) and one for containerized apps—to attach one or more sidecars via App Service’s sitecontainers configuration. Azure Pipelines (VSTS): Two YAML templates—AzureWebApp@1 for code-based apps and AzureWebAppContainer@1 for containerized apps—that build and deploy your app and declare sidecars in a single run (mark one container isMain: true, others as sidecars). When to use which Code-based app on built-in Linux runtime (Python/Node/.NET/Java/PHP, etc.) Use the “blessed/built-in runtime” template; your app keeps running on the App Service runtime, sidecars run next to it. Custom container (Web App for Containers) Use the “containers” template to build/push multiple images and deploy them together. Quick start (both options) Add the template to your repo (workflow for GitHub; YAML for VSTS). Wire up auth (OIDC or service connection) and set app name, resource group, registry, and sidecar images/ports. Run the pipeline; in the Azure portal you’ll see your main app plus defined sidecars. Links GitHub Actions samples (code-based & container) — GitHub Actions samples: add sidecars to Azure App Service for Linux. Azure Pipelines samples (code-based & container) — Azure Pipeline samples: add sidecars to Azure App Service for Linux. Drop in a template, describe your sidecars, and ship—same App Service, more capability.140Views0likes0CommentsUbuntu-Powered Runtimes on Azure App Service for Linux: Leaner, Faster, Stronger
We’re updating the OS foundation for new code-based stacks on Azure App Service for Linux. Every new major version of our supported stacks will target Ubuntu going forward - this includes the new versions for .NET 10, Python 3.14, Node 24, PHP 8.5 and Java 25 - all expected to rollout in the next couple of months. Existing stacks remain on Debian, and nothing changes for your current apps unless you choose to move. Why Ubuntu? Because we manage the OS for you, this change is about platform gains that quietly benefit your apps without adding work for your teams. Builds on Debian’s ecosystem: Ubuntu inherits Debian’s rich package universe while moving faster upstream. This lets the platform adopt newer toolchains and libraries more predictably, improving compatibility and unblocking modern dependencies. LTS stability with long runway: Ubuntu LTS follows a 5-year support lifecycle giving us a stable, well-maintained base to operate at scale. What’s changing (and what isn’t) Changing: New .NET 10, Python 3.14, Node 24, PHP 8.5 and Java 25 code-based stacks will run on Ubuntu images. Not changing: Your existing apps stay on Debian. No forced migrations. Operational parity: Deployment flows (Oryx, GitHub Actions, Azure CLI), scaling, diagnostics, and networking continue to work as before. What this means for you No action required for existing apps. When creating a new app or upgrading to .NET 10, Python 3.14, Node 24, PHP 8.5 and Java 25, you’ll get the Ubuntu-based stack by default. When upgrading, verify any native packages your app installs at build/start, since Ubuntu often provides equal or newer versions and names may differ. Quick FAQ Do I need to move now? No. Existing apps stay on Debian. Migrate only if you want the newer runtimes and platform improvements. Will my build behavior change? Expected to be neutral-to-positive. Leaner images and fresher toolchains can reduce build and cold-start times. Any breaking differences? None anticipated for supported frameworks. If you pin specific distro package versions, confirm availability on Ubuntu during upgrade. By standardizing new stacks on Ubuntu LTS, we preserve Debian’s strengths while unlocking a faster cadence, long-term security coverage, and leaner images that translate to better reliability and performance—delivered transparently by the platform.172Views0likes0CommentsPython 3.14 is now available on Azure App Service for Linux
If you’ve been waiting to run Python 3.14 in on Azure App Service - it’s here. Azure App Service for Linux now offers Python 3.14 as a first-class runtime. You can create a new 3.14 app through the Azure portal, automate it with the Azure CLI, or roll it out using your favorite ARM/Bicep templates — and App Service continues to handle the OS, runtime updates, and patching for you so you can stay focused on code. Why Python 3.14 matters Python 3.14 (released October 7, 2025) lands with real performance and runtime improvements. Faster under load. Internal interpreter work reduces overhead in common call paths and improves memory behavior, which can translate to lower latency and less CPU churn in web apps and APIs. Smarter concurrency. Python 3.14 continues the rollout of subinterpreters and a free-threaded build (no GIL), making it easier to take advantage of multi-core parallelism for CPU-bound or high-throughput workloads. In 3.14, that free-threaded mode is more mature and shows significantly better multi-threaded performance than earlier releases. Developer quality-of-life. You get a more helpful interactive REPL (better highlighting and error hints), cleaner typing through deferred annotations, and new template string syntax (“t-strings”) for safe, structured interpolation. All of that is now available to you on App Service for Linux. What you should do next If you’re currently running an older Python version on App Service for Linux, this is a good moment to validate on 3.14: Stand up a staging app or deployment slot on Python 3.14. Run your normal tests and watch request latency, CPU, and memory. Confirm that any native wheels or pinned dependencies you rely on install and import cleanly. Most apps will only need minor adjustments — and you’ll walk away with a faster, more capable runtime on a platform that keeps the underlying infrastructure patched and production-ready for you.140Views1like0Comments