.NETAzureDeploymentAI Agents

Deploy a .NET AI Agent to Azure Container Apps

Take a .NET AI agent from your laptop to production on Azure Container Apps: containerize it, wire up secrets with managed identity, deploy, and scale to zero when idle.

An agent running in a console window is a demo. To make it a product, it has to run somewhere reachable, handle real traffic, keep its secrets safe, and not cost money while it sits idle. Azure Container Apps hits that sweet spot for .NET agents: it runs your container as a serverless service, scales out under load, and scales to zero when nobody’s calling — you pay for what you use.

This guide takes a minimal API-wrapped agent to production. It assumes you already have an agent like the one from our tool-using agent tutorial, exposed over an HTTP endpoint.

Step 1: Wrap the agent in a minimal API

Container Apps expects an HTTP service, so expose your agent with a tiny endpoint:

using Microsoft.Agents.AI;
using Azure.AI.OpenAI;
using Azure.Identity;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

var chatClient = new AzureOpenAIClient(
        new Uri(Environment.GetEnvironmentVariable("AOAI_ENDPOINT")!),
        new DefaultAzureCredential())
    .GetChatClient("gpt-4o-mini");

var agent = chatClient.CreateAIAgent(
    name: "SupportBot",
    instructions: "You help customers with orders and returns.");

app.MapPost("/ask", async (AskRequest req) =>
    Results.Ok(new { answer = (await agent.RunAsync(req.Message)).ToString() }));

app.MapGet("/health", () => Results.Ok("healthy"));

app.Run();

record AskRequest(string Message);

Note the endpoint reads its Azure OpenAI endpoint from an environment variable and authenticates with DefaultAzureCredential — no keys in code. That pays off in the next steps.

Step 2: Containerize it

Add a Dockerfile using a multi-stage build so the final image only contains the runtime, not the SDK:

FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app

FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app
COPY --from=build /app .
EXPOSE 8080
ENV ASPNETCORE_URLS=http://+:8080
ENTRYPOINT ["dotnet", "AgentDemo.dll"]

Build and test locally to confirm it runs before you push anything to the cloud:

docker build -t agent-demo .
docker run -p 8080:8080 -e AOAI_ENDPOINT=... agent-demo

Step 3: Push to Azure Container Registry

Container Apps pulls from a registry. Create one and push your image:

az acr create -g agents-rg -n agentsregistry --sku Basic
az acr login -n agentsregistry
docker tag agent-demo agentsregistry.azurecr.io/agent-demo:v1
docker push agentsregistry.azurecr.io/agent-demo:v1

Step 4: Deploy — and handle secrets the right way

Here’s the part people get wrong: don’t paste your Azure OpenAI key into an environment variable. Because the agent uses DefaultAzureCredential, you can give the Container App a managed identity and grant that identity access to your Azure OpenAI resource. No key ever exists in your config.

az containerapp create \
  --name agent-demo \
  --resource-group agents-rg \
  --environment agents-env \
  --image agentsregistry.azurecr.io/agent-demo:v1 \
  --target-port 8080 \
  --ingress external \
  --system-assigned \
  --env-vars AOAI_ENDPOINT=https://<your-resource>.openai.azure.com \
  --min-replicas 0 \
  --max-replicas 5

Then grant the app’s managed identity the Cognitive Services OpenAI User role on your Azure OpenAI resource. Now the container authenticates with its own identity — nothing to leak.

--min-replicas 0 is the money-saver: when no requests arrive, the app scales to zero and costs nothing. The first request after idle incurs a cold start (typically a second or two for .NET), which is fine for most agent workloads.

Step 5: Scale on the right signal

The default scaling is HTTP-concurrency based, which suits synchronous agent endpoints. If your agent does long-running work, consider a queue-based design (Container Apps can scale on queue length via KEDA) so a burst of requests doesn’t overwhelm a few replicas. Set --max-replicas to a ceiling that respects your Azure OpenAI quota — scaling the app past your token-per-minute limit just moves the bottleneck.

Step 6: See what it’s doing

Enable logging so you can debug in production:

az containerapp logs show -n agent-demo -g agents-rg --follow

For real observability, wire up OpenTelemetry in the app and point it at Azure Monitor. Agent traces — which tools were called, how long each model round-trip took — are invaluable when an agent misbehaves, and far more useful than raw logs.

Note: Azure CLI flags and role names occasionally change. Verify commands against the current Azure Container Apps docs for your CLI version; the architecture — containerize, push, deploy with managed identity, scale to zero — is what matters and is stable.

Takeaway

Azure Container Apps gives a .NET agent a production home without you managing servers: a container, a managed identity instead of secrets, scale-to-zero economics, and KEDA-based scaling when you need it. Containerize once, and the same image runs identically on your laptop and in the cloud — which is exactly the property you want when an agent starts handling real users.


Have a correction or a topic you want covered? Email mani.bc72@gmail.com.