Azure Container Apps Dynamic Sessions — Hyper-V Sandbox for Secure AI Agent Code Execution
Posted on: 4/27/2026 2:10:40 AM
Table of contents
- 1. The Problem: Where to Run AI-Generated Code?
- 2. Architecture Overview
- 3. Two Types of Session Pools
- 4. Session Pool Mechanics and Prewarming
- 5. Security: Hyper-V Isolation
- 6. MCP Integration — Direct AI Agent Access
- 7. Two Models for Hosting MCP Servers on Container Apps
- 8. Real-World Deployment Patterns
- 9. Complete ARM Template Configuration
- 10. Comparison with Alternatives
- 11. Pricing and Cost Optimization
- 12. Limitations to Consider
- Conclusion
- References
When AI Agents can generate and execute code autonomously, the biggest question is no longer "Can AI write code?" but "Where do we run that code safely?". Azure Container Apps Dynamic Sessions were built to solve exactly this — providing Hyper-V isolated environments that start in milliseconds, auto-scale to thousands of concurrent sessions, and natively integrate with MCP (Model Context Protocol) for direct AI agent invocation.
This article deep-dives into the architecture, operational mechanics, security model, and real-world deployment patterns of Dynamic Sessions — from a system design perspective for teams building production AI agent systems.
1. The Problem: Where to Run AI-Generated Code?
Imagine an AI coding assistant receiving the request: "Analyze this 500MB CSV and chart revenue by quarter". The agent generates Python code using pandas + matplotlib, but that code must execute somewhere. Traditional approaches all have issues:
| Approach | Problem | Risk Level |
|---|---|---|
| Run on main server (app process) | Code injection, resource exhaustion, full system crash | Very High |
| Dedicated container (Docker spawn) | 5-30s cold start, manual lifecycle management, poor scaling | Medium |
| Lambda / Cloud Functions | Runtime limits, no filesystem, payload constraints | Low but limited |
| Dedicated VM per request | Extremely expensive, minute-level boot time | Low but costly |
Dynamic Sessions solve all of these: fully isolated Hyper-V es, prewarmed pools with sub-second startup, automated lifecycle management, scaling to thousands of sessions, and native AI agent integration via MCP.
2. Architecture Overview
graph TD
Client["🤖 AI Agent / LLM App"]
MgmtAPI["Management API Endpoint"]
Pool["Session Pool"]
Prewarmed["Prewarmed Sessions
(Hyper-V Isolated)"]
Active1["Session A
identifier: user-123"]
Active2["Session B
identifier: user-456"]
Active3["Session C
identifier: conv-789"]
EntraID["Microsoft Entra ID"]
Client -->|"HTTPS + Bearer Token"| MgmtAPI
EntraID -->|"AuthN/AuthZ"| MgmtAPI
MgmtAPI -->|"Route by identifier"| Pool
Pool --> Prewarmed
Pool --> Active1
Pool --> Active2
Pool --> Active3
style Client fill:#e94560,stroke:#fff,color:#fff
style MgmtAPI fill:#2c3e50,stroke:#fff,color:#fff
style Pool fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style Prewarmed fill:#f8f9fa,stroke:#4CAF50,color:#2c3e50
style Active1 fill:#fff,stroke:#e94560,color:#2c3e50
style Active2 fill:#fff,stroke:#e94560,color:#2c3e50
style Active3 fill:#fff,stroke:#e94560,color:#2c3e50
style EntraID fill:#2c3e50,stroke:#fff,color:#fff
Figure 1: Azure Container Apps Dynamic Sessions — Architecture Overview
3. Two Types of Session Pools
3.1. Code Interpreter Session Pool
Uses platform-managed containers pre-installed with Python (NumPy, pandas, matplotlib), Node.js, and Shell. No image build required — just create the pool and start using it immediately.
When to Choose Code Interpreter?
Your AI agent needs to run simple Python/JS/Shell code: data analysis, chart generation, file processing, script execution. No complex custom dependencies needed. Biggest advantage: zero setup, fastest startup.
3.2. Custom Container Session Pool
Bring-your-own-container — push your image to ACR (Azure Container Registry), configure resources (CPU, RAM), commands, and environment variables. Fully customizable runtime environment.
When to Choose Custom Container?
Workloads requiring specific libraries (TensorFlow, FFmpeg, Puppeteer), custom TCP protocols, proprietary binaries, or production-identical environments for integration testing.
| Criteria | Code Interpreter | Custom Container |
|---|---|---|
| Image requirement | None — uses platform image | Required — push to ACR |
| Languages | Python, Node.js, Shell | Any (depends on image) |
| Startup time | Fastest (pre-warmed) | Fast (pre-warmed from custom image) |
| Custom dependencies | Limited (popular libraries) | Unlimited |
| MCP support | Yes (Python + Shell) | Self-implement if needed |
| Primary use case | LLM code execution, data analysis | Custom compute, proprietary tools |
4. Session Pool Mechanics and Prewarming
The core differentiator of Dynamic Sessions versus self-managed container spawning: Session Pools maintain a set of prewarmed sessions — containers already booted, OS loaded, runtime ready, just waiting for a request to allocate instantly.
sequenceDiagram
participant App as AI Agent App
participant API as Management API
participant Pool as Session Pool
participant PW as Prewarmed Session
participant Active as Active Session
App->>API: POST /api/execute?identifier=user-123
API->>API: Validate Entra ID token
API->>Pool: Route by identifier "user-123"
alt Session exists
Pool->>Active: Forward request
Active-->>App: Response (execution result)
else New identifier
Pool->>PW: Allocate from prewarmed pool
PW->>Active: Become active session
Active-->>App: Response (sub-second)
Pool->>Pool: Replenish prewarmed pool
end
Note over Active: Cooldown timer starts
Note over Active: No activity → auto-destroy
Figure 2: Request flow and prewarming mechanism
4.1. Identifier-based Routing
Every request must include ?identifier=<value>. This is how the Pool knows which session a request belongs to:
- If the identifier already exists → route to the active session
- If the identifier is new → allocate a new session from the prewarmed pool
- Identifier is a free-form string (4-128 characters): can be user ID, conversation ID, or task ID
4.2. Lifecycle and Cooldown
Sessions are automatically destroyed when the cooldown period expires (configurable, defaults to 600 seconds). This ensures resources are not wasted. You can query session status via /.management/getSession and list all sessions via /.management/listSessions.
5. Security: Hyper-V Isolation
This is the most critical factor when running untrusted code. Dynamic Sessions don't use standard container isolation (Linux namespaces/cgroups) — they use Hyper-V isolation, meaning each session runs inside its own lightweight VM.
graph LR
subgraph Host["Azure Host Machine"]
subgraph HV1["Hyper-V VM 1"]
S1["Session A
user-123"]
end
subgraph HV2["Hyper-V VM 2"]
S2["Session B
user-456"]
end
subgraph HV3["Hyper-V VM 3"]
S3["Session C
conv-789"]
end
end
S1 -.->|"❌ Cannot access"| S2
S2 -.->|"❌ Cannot access"| S3
style Host fill:#f8f9fa,stroke:#2c3e50,color:#2c3e50
style HV1 fill:#fff,stroke:#e94560,color:#2c3e50
style HV2 fill:#fff,stroke:#e94560,color:#2c3e50
style HV3 fill:#fff,stroke:#e94560,color:#2c3e50
style S1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style S2 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style S3 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
Figure 3: Hyper-V isolation model — each session is a separate VM
Important Security Note
While sessions are isolated from each other, everything within a single session (files, env vars, processes) is accessible by code running in that session. Never inject secrets or credentials into a session if the code running inside is untrusted. If you need Azure resource access, use managed identity with minimal permissions and enable managedIdentitySettings.lifecycle: "Main" cautiously.
5.1. Network Security
By default, sessions have no outbound network access. This is defense-in-depth: even if an attacker escapes the application , they still cannot make external calls. You can enable it via sessionNetworkConfiguration.status: "EgressEnabled" when needed (e.g., sessions calling external APIs).
5.2. Authentication Flow
All Management API requests require a Microsoft Entra ID token with the Azure ContainerApps Session Executor role on the session pool resource:
// C# - Get token from managed identity or DefaultAzureCredential
using Azure.Identity;
var credential = new DefaultAzureCredential();
var token = credential.GetToken(
new TokenRequestContext(new[] { "https://dynamicsessions.io/.default" })
);
// Send with header: Authorization: Bearer {token.Token}
# Python - Azure Identity
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
token = credential.get_token("https://dynamicsessions.io/.default")
# Header: Authorization: Bearer {token.token}
6. MCP Integration — Direct AI Agent Access
The standout feature (preview since March 2026): enable MCP on a session pool, and the platform automatically exposes a /mcp endpoint following the JSON-RPC 2.0 standard. AI agents (Claude, GitHub Copilot, Azure Foundry) connect directly and invoke tools without middleware code.
sequenceDiagram
participant Agent as AI Agent (Claude/Copilot)
participant MCP as /mcp Endpoint
participant Sandbox as Hyper-V Sandbox
Agent->>MCP: initialize (JSON-RPC 2.0)
MCP-->>Agent: capabilities: [launchShell, runShellCommand, runPythonCode]
Agent->>MCP: tools/call → launchShell
MCP->>Sandbox: Create environment
Sandbox-->>MCP: environmentId: "env-abc"
MCP-->>Agent: environmentId
Agent->>MCP: tools/call → runPythonCodeInRemoteEnvironment
Note right of Agent: code: "import pandas as pd
df = pd.read_csv('data.csv')
print(df.describe())"
MCP->>Sandbox: Execute Python code
Sandbox-->>MCP: stdout output
MCP-->>Agent: execution result
Figure 4: AI Agent → MCP → Sandbox communication flow
6.1. Three Platform-Managed MCP Tools
| Tool | Function | Use Case |
|---|---|---|
launchShell | Creates a new environment, returns environmentId | First step in every workflow |
runShellCommandInRemoteEnvironment | Executes shell commands in an existing environment | Package installation, file management, script execution |
runPythonCodeInRemoteEnvironment | Executes Python code in an existing environment | Data analysis, ML inference, chart generation |
6.2. Configuring MCP on a Session Pool
Just one property in the ARM/Bicep template:
{
"type": "Microsoft.App/sessionPools",
"apiVersion": "2025-02-02-preview",
"properties": {
"containerType": "PythonLTS",
"poolManagementType": "Dynamic",
"mcpServerSettings": {
"isMCPServerEnabled": true
},
"dynamicPoolConfiguration": {
"executionType": "Timed",
"cooldownPeriodInSeconds": 600
},
"scaleConfiguration": {
"maxConcurrentSessions": 100,
"readySessionInstances": 10
}
}
}
After deployment, retrieve the API key via Azure CLI:
az rest --method POST \
--uri "https://management.azure.com/subscriptions/{subId}/resourceGroups/{rg}/providers/Microsoft.App/sessionPools/{pool}/fetchMCPServerCredentials" \
--uri-parameters api-version=2025-02-02-preview \
--query "apiKey" -o tsv
Agents connect using endpoint https://{pool}.{envId}.{region}.azurecontainerapps.io/mcp with the x-ms-apikey header.
7. Two Models for Hosting MCP Servers on Container Apps
Beyond Dynamic Sessions (platform-managed MCP), you can also deploy a custom MCP server as a standalone container app. The two models serve different purposes:
| Criteria | Standalone Container App | Dynamic Sessions (Managed MCP) |
|---|---|---|
| Custom tools | Define any tools you want | Only 3 platform-defined tools |
| Languages | Any (MCP SDK: .NET, Python, TS, Go, Java) | Python + Shell execution only |
| Authentication | Microsoft Entra ID (built-in auth) | API key (x-ms-apikey) |
| Isolation | Container-level | Hyper-V per session |
| Scaling | Revision-based autoscale (scale-to-zero) | Per-session, pool-managed |
| Use case | MCP server with complex business logic | Sandboxed code execution |
Combining Both Models
In practice, many teams use both: a standalone container app as the primary MCP server (exposing custom tools: database queries, internal API calls, workflow management), and Dynamic Sessions for the "execute_code" tool — when the agent needs to run generated code, the request is proxied to the session pool. This leverages both custom logic and isolation.
8. Real-World Deployment Patterns
8.1. AI Data Analyst Agent
graph LR
User["User"]
App["Web App / API"]
LLM["Azure OpenAI / Claude"]
DS["Dynamic Session
(Code Interpreter)"]
Blob["Azure Blob Storage"]
User -->|"Upload CSV + question"| App
App -->|"Prompt + context"| LLM
LLM -->|"Generated Python code"| App
App -->|"Execute code
identifier=user-id"| DS
DS -->|"Read/Write file"| DS
DS -->|"Chart image"| Blob
Blob -->|"Chart URL"| App
App -->|"Results + chart"| User
style User fill:#f8f9fa,stroke:#2c3e50,color:#2c3e50
style App fill:#2c3e50,stroke:#fff,color:#fff
style LLM fill:#e94560,stroke:#fff,color:#fff
style DS fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style Blob fill:#f8f9fa,stroke:#2c3e50,color:#2c3e50
Figure 5: AI Data Analyst pattern with Dynamic Sessions
8.2. Multi-tenant Code Playground
Each tenant gets a unique identifier → fully isolated sessions. 15-minute cooldown → automatic cleanup. Egress disabled → tenants cannot make external calls (unless you allow it). Scales to hundreds of concurrent tenants without infrastructure management.
8.3. CI/CD Pipeline with Secure Test Execution
Run test suites in Dynamic Sessions instead of on build agents. Benefits: tests don't affect each other (Hyper-V isolation), no build agent cleanup needed, automatic scaling based on PR volume.
9. Complete ARM Template Configuration
{
"type": "Microsoft.App/sessionPools",
"apiVersion": "2024-08-02-preview",
"name": "my-ai-session-pool",
"location": "southeastasia",
"properties": {
"environmentId": "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.App/managedEnvironments/{env}",
"poolManagementType": "Dynamic",
"containerType": "CustomContainer",
"scaleConfiguration": {
"maxConcurrentSessions": 50,
"readySessionInstances": 5
},
"dynamicPoolConfiguration": {
"executionType": "Timed",
"cooldownPeriodInSeconds": 900
},
"customContainerTemplate": {
"registryCredentials": {
"server": "myregistry.azurecr.io",
"identity": "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{id}"
},
"containers": [{
"image": "myregistry.azurecr.io/my-:latest",
"name": "",
"resources": { "cpu": 0.5, "memory": "1Gi" },
"env": [
{ "name": "SANDBOX_MODE", "value": "restricted" }
]
}],
"ingress": { "targetPort": 8080 }
},
"sessionNetworkConfiguration": {
"status": "EgressDisabled"
}
}
}
10. Comparison with Alternatives
| Criteria | Dynamic Sessions | AWS Lambda | Google Cloud Run Jobs | Self-managed Docker |
|---|---|---|---|---|
| Cold start | < 1s (prewarmed) | 100ms-10s (varies) | 1-10s | 5-30s |
| Isolation | Hyper-V (VM-level) | Firecracker microVM | gVisor | Linux namespaces |
| Stateful session | Yes (cooldown-based) | No | No | Self-managed |
| MCP integration | Yes (native) | No | No | Self-implement |
| Max runtime | Configurable cooldown | 15 minutes | 24 hours | Unlimited |
| Custom container | Yes | Yes (image) | Yes | Yes |
| Scale model | Pool-managed auto | Per-invocation | Task-based | Manual/K8s HPA |
11. Pricing and Cost Optimization
Dynamic Sessions are billed based on resource consumption of the session pool (vCPU-second + memory GiB-second). Key optimization strategies:
- Reduce
readySessionInstancesduring off-peak hours — prewarmed sessions consume resources even when not allocated - Shorter cooldown periods for one-shot workloads (e.g., code execution) — 60-120s instead of the default 600s
- Right-size container resources — code interpreter typically needs only 0.25 vCPU + 0.5Gi RAM unless processing large datasets
- Use Code Interpreter pools instead of Custom Container when possible — less image management overhead
12. Limitations to Consider
Key Considerations Before Adoption
- MCP feature is in preview (API version
2025-02-02-preview) — breaking changes possible - Sessions are ephemeral — no persistent storage. Results must be uploaded to external storage (Blob, DB) before session cooldown expires
- Managed identity in sessions allows untrusted code to create tokens — use with extreme caution, assign minimal permissions only
- Only Python + Shell for managed MCP — if you need Rust, Go, or Java, use Custom Container + standalone MCP
- Outbound network disabled by default — must enable if code needs external API calls (but consider security trade-offs)
Conclusion
Azure Container Apps Dynamic Sessions provide a purpose-built solution for the problem of "running AI-generated code safely at scale". With Hyper-V isolation, prewarmed sub-second pools, and native MCP support, they are a critical building block for any AI agent system requiring code execution capabilities.
The greatest strength lies in operational simplicity: no container lifecycle management, no cleanup concerns, no infrastructure to build. Just create a session pool, assign an identity, and your AI agent starts executing code safely.
With MCP integration deepening across the ecosystem (Azure Foundry, GitHub Copilot, Claude), Dynamic Sessions are becoming the standard bridge between AI reasoning and real-world code execution.
References
- Dynamic sessions in Azure Container Apps - Microsoft Learn
- Use dynamic sessions in Azure Container Apps - Microsoft Learn
- Host MCP servers on Azure Container Apps - Microsoft Learn
- Even simpler to Safely Execute AI-generated Code with Dynamic Sessions - Microsoft Tech Community
- What's new in Azure Container Apps at Ignite'25 - Microsoft Tech Community
Node.js 24 — Native TypeScript, Permission Model & V8 13.6 Reshape Backend Development
News Feed System Design — Fan-out, Caching & Ranking at Scale for Millions of Users
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.