Azure Container Apps Dynamic Sessions — Hyper-V Sandbox for Secure AI Agent Code Execution

Posted on: 4/27/2026 2:10:40 AM

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:

ApproachProblemRisk Level
Run on main server (app process)Code injection, resource exhaustion, full system crashVery High
Dedicated container (Docker spawn)5-30s cold start, manual lifecycle management, poor scalingMedium
Lambda / Cloud FunctionsRuntime limits, no filesystem, payload constraintsLow but limited
Dedicated VM per requestExtremely expensive, minute-level boot timeLow 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

< 1sNew session startup time
Hyper-VHardware virtualization isolation
30+ RegionsGlobal availability on Azure
MCP NativeModel Context Protocol integration

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.

CriteriaCode InterpreterCustom Container
Image requirementNone — uses platform imageRequired — push to ACR
LanguagesPython, Node.js, ShellAny (depends on image)
Startup timeFastest (pre-warmed)Fast (pre-warmed from custom image)
Custom dependenciesLimited (popular libraries)Unlimited
MCP supportYes (Python + Shell)Self-implement if needed
Primary use caseLLM code execution, data analysisCustom 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

ToolFunctionUse Case
launchShellCreates a new environment, returns environmentIdFirst step in every workflow
runShellCommandInRemoteEnvironmentExecutes shell commands in an existing environmentPackage installation, file management, script execution
runPythonCodeInRemoteEnvironmentExecutes Python code in an existing environmentData 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:

CriteriaStandalone Container AppDynamic Sessions (Managed MCP)
Custom toolsDefine any tools you wantOnly 3 platform-defined tools
LanguagesAny (MCP SDK: .NET, Python, TS, Go, Java)Python + Shell execution only
AuthenticationMicrosoft Entra ID (built-in auth)API key (x-ms-apikey)
IsolationContainer-levelHyper-V per session
ScalingRevision-based autoscale (scale-to-zero)Per-session, pool-managed
Use caseMCP server with complex business logicSandboxed 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

CriteriaDynamic SessionsAWS LambdaGoogle Cloud Run JobsSelf-managed Docker
Cold start< 1s (prewarmed)100ms-10s (varies)1-10s5-30s
IsolationHyper-V (VM-level)Firecracker microVMgVisor Linux namespaces
Stateful sessionYes (cooldown-based)NoNoSelf-managed
MCP integrationYes (native)NoNoSelf-implement
Max runtimeConfigurable cooldown15 minutes24 hoursUnlimited
Custom containerYesYes (image)YesYes
Scale modelPool-managed autoPer-invocationTask-basedManual/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 readySessionInstances during 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