Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion preview-features/on-demand-sandboxes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@

To gain access to the private preview, email [dts-team@microsoft.com](mailto:dts-team@microsoft.com).

You'll need a Durable Task Scheduler in one of the supported preview regions. You can use
an existing scheduler or create a new one in any of these regions:

- East US 2 (`eastus2`)
- West US 3 (`westus3`)
- North Europe (`northeurope`)
- Australia East (`australiaeast`)

Reply to us with your scheduler name and the region it's in, and we'll enable On-demand
Sandboxes on it.

## Overview

A *sandbox* is an isolated, microVM-backed container that runs a single piece of your
Expand Down Expand Up @@ -86,7 +97,8 @@ flowchart LR
## Get started

On-demand Sandboxes is in private preview. To get access, email
[dts-team@microsoft.com](mailto:dts-team@microsoft.com).
[dts-team@microsoft.com](mailto:dts-team@microsoft.com). You'll need a scheduler in one of
the [supported preview regions](#get-private-preview-access).

Once you're in, follow the step-by-step guide for your SDK:

Expand Down
7 changes: 4 additions & 3 deletions preview-features/on-demand-sandboxes/docs/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ configuration.
## Install the SDK

The on-demand sandbox APIs ship under the `durabletask.azuremanaged.preview.sandboxes`
namespace. Install the Durable Task packages:
namespace. Install the Azure-managed Durable Task package (it pulls in the core
`durabletask` SDK):

```bash
pip install durabletask==1.6.0 durabletask-azuremanaged==1.6.0
pip install durabletask-azuremanaged==1.6.0
```

## Step 1: Declare a sandbox worker profile
Expand Down Expand Up @@ -264,7 +265,7 @@ ENV GRPC_DEFAULT_SSL_ROOTS_FILE_PATH=/etc/ssl/certs/ca-certificates.crt

# Install the Durable Task SDK (with the sandboxes extension), plus your
# activity dependencies.
RUN pip install --no-cache-dir durabletask==1.6.0 durabletask-azuremanaged==1.6.0
RUN pip install --no-cache-dir durabletask-azuremanaged==1.6.0

COPY remote_worker.py /app/remote_worker.py
COPY activities.py /app/activities.py
Expand Down
29 changes: 21 additions & 8 deletions preview-features/on-demand-sandboxes/samples/dotnet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,20 @@ dts-ondemand-sandbox-codegen-demo/
└── Containerfile
```

## Prerequisites
## Prerequisites (local development)

These prerequisites are for running the sample **locally** (building the sandbox image
and running the orchestrator on your machine). To deploy to Azure instead, skip to
[Deploy to Azure (AKS) with `azd`](#deploy-to-azure-aks-with-azd), which has its own
prerequisites.

- .NET 10 SDK
- Docker (for building the sandbox image)
- Azure CLI (`az`), signed in with access to the scheduler, ACR, and Azure OpenAI
- A DTS scheduler + task hub you can hit
- An Azure Container Registry with anonymous pull enabled (so DTS can fetch the sandbox image)
- An Azure OpenAI deployment of a chat model (GPT-4o, GPT-4.1, etc.)
- An Azure Container Registry the image-pull identity can pull from (granted AcrPull)
- Two user-assigned managed identities (image pull + scheduler connect)
- An Azure OpenAI deployment of a chat model (GPT-5.1, GPT-5, GPT-4.1, etc.)
- The Durable Task on-demand sandbox preview packages (`1.25.0-preview.2`) available on
a NuGet feed you can restore from

Expand All @@ -99,11 +106,16 @@ docker build \
-t $IMAGE \
.

# Enable anonymous pull so DTS can fetch the sandbox image without credentials
az acr update --name $ACR --anonymous-pull-enabled true

az acr login --name $ACR
docker push $IMAGE

# DTS pulls the sandbox image using the image-pull managed identity (not anonymous
# pull). Grant that identity AcrPull on the registry -- use the same UMI you pass as
# DTS_SANDBOX_IMAGE_PULL_UMI_CLIENT_ID when running the orchestrator.
az role assignment create \
--assignee "<image-pull UMI client ID>" \
--role AcrPull \
--scope "$(az acr show --name $ACR --query id -o tsv)"
```

> **Note on `--platform linux/amd64`:** Required on Apple Silicon. The `Grpc.Tools`
Expand Down Expand Up @@ -145,7 +157,8 @@ never deployed as a Container App.
> The Durable Task Scheduler is **not created** by this template. You pass in an
> existing one. On-demand Sandboxes is a private-preview feature that must be enabled on
> the scheduler out of band, so the scheduler is patched separately and supplied here by
> name.
> name. The scheduler must be in a supported preview region: East US 2, West US 3, North
> Europe, or Australia East.

### What gets provisioned

Expand All @@ -160,7 +173,7 @@ The deployment also **ensures the task hub** exists, grants the identity the rol
needs (AcrPull, Durable Task data access, Cognitive Services OpenAI User), and a
`postprovision` hook **attaches the identity to your scheduler** (a merge-safe PATCH).

### Prerequisites
### Prerequisites (Azure deployment)

- An existing **DTS scheduler** with the On-demand Sandboxes preview enabled, and its
resource group name.
Expand Down
16 changes: 12 additions & 4 deletions preview-features/on-demand-sandboxes/samples/dotnet/azure.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,19 @@ metadata:
name: dts-ondemand-sandboxes-dotnet
hooks:
predeploy:
shell: sh
run: ./scripts/acr-build.sh
posix:
shell: sh
run: ./scripts/acr-build.sh
windows:
shell: pwsh
run: ./scripts/acr-build.ps1
postprovision:
shell: sh
run: ./scripts/attach-scheduler-identity.sh
posix:
shell: sh
run: ./scripts/attach-scheduler-identity.sh
windows:
shell: pwsh
run: ./scripts/attach-scheduler-identity.ps1
services:
mainapp:
project: ./main-app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# the Grpc.Tools linux_arm64 protoc segfault seen under arm64 emulation on Apple Silicon.

FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
ARG TARGETARCH

WORKDIR /src/dts-ondemand-sandbox-codegen-demo
COPY . .
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# runtime stage.

FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
ARG TARGETARCH

WORKDIR /src/dts-ondemand-sandbox-codegen-demo
COPY . .
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Builds the sandbox worker image server-side using ACR Tasks (az acr build) - no local
# Docker required. Called by azd as a predeploy hook on Windows (the POSIX equivalent is
# acr-build.sh).
#
# The main-app (orchestrator) image is built by azd itself from main-app/Containerfile
# (see azure.yaml docker.remoteBuild), so it is intentionally NOT built here.
#
# The sandbox image is the worker DTS starts on demand. It is not deployed as an azd
# service; its image reference is set on the Container App by infra/main.bicep
# (DTS_SANDBOX_CONTAINER_IMAGE), so it is pushed to that exact tag here.

$ErrorActionPreference = 'Stop'

function Get-RequiredEnv([string]$name) {
$value = [Environment]::GetEnvironmentVariable($name)
if ([string]::IsNullOrEmpty($value)) {
throw "$name must be set"
}
return $value
}

$Registry = Get-RequiredEnv 'AZURE_CONTAINER_REGISTRY_NAME'
$RegistryEndpoint = Get-RequiredEnv 'AZURE_CONTAINER_REGISTRY_ENDPOINT'
$EnvName = Get-RequiredEnv 'AZURE_ENV_NAME'

# The .NET build context is the sample root so Directory.Build.props is available.
function Build-Image([string]$imageRepo, [string]$imageTag, [string]$containerfile) {
$fullImage = "$RegistryEndpoint/${imageRepo}:$imageTag"

Write-Host "==> Building ${imageRepo}:$imageTag via ACR Tasks (--platform linux/amd64)..."
# The classic ACR builder does not auto-populate the BuildKit TARGETARCH arg, so we
# pass it explicitly. We always build linux/amd64 here, so amd64 is correct.
az acr build `
--registry $Registry `
--image "${imageRepo}:$imageTag" `
--platform linux/amd64 `
--build-arg TARGETARCH=amd64 `
--file $containerfile `
. `
--no-logs `
--output none
if ($LASTEXITCODE -ne 0) { throw "az acr build failed for $imageRepo" }

return $fullImage
}

# The sandbox image uses a stable 'latest' tag matching DTS_SANDBOX_CONTAINER_IMAGE in
# infra/main.bicep; DTS pulls it fresh each time it starts a sandbox.
$SandboxImage = Build-Image "dts-ondemand-sandboxes/sandbox-worker-$EnvName" "latest" "sandbox-worker/Containerfile"

Write-Host "==> sandbox image : $SandboxImage"
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# service; its image reference is set on the Container App by infra/main.bicep
# (DTS_SANDBOX_CONTAINER_IMAGE), so it is pushed to that exact tag here.

set -euo pipefail
set -eu

REGISTRY="${AZURE_CONTAINER_REGISTRY_NAME:?AZURE_CONTAINER_REGISTRY_NAME must be set}"
REGISTRY_ENDPOINT="${AZURE_CONTAINER_REGISTRY_ENDPOINT:?AZURE_CONTAINER_REGISTRY_ENDPOINT must be set}"
Expand All @@ -23,10 +23,13 @@ build() {
local full_image="${REGISTRY_ENDPOINT}/${image_repo}:${image_tag}"

echo "==> Building ${image_repo}:${image_tag} via ACR Tasks (--platform linux/amd64)..." >&2
# The classic ACR builder does not auto-populate the BuildKit TARGETARCH arg, so we
# pass it explicitly. We always build linux/amd64 here, so amd64 is correct.
az acr build \
--registry "${REGISTRY}" \
--image "${image_repo}:${image_tag}" \
--platform linux/amd64 \
--build-arg TARGETARCH=amd64 \
--file "${containerfile}" \
. \
--no-logs \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Attaches the sample's user-assigned managed identity to the existing Durable Task
# Scheduler so DTS can use it to pull the sandbox image and let the sandbox worker
# connect back. Runs as an azd postprovision hook on Windows (the POSIX equivalent is
# attach-scheduler-identity.sh). Uses the `durabletask` Azure CLI extension's identity
# command, which adds the identity without removing any that are already attached to
# the scheduler.
#
# NOTE: enabling the On-demand Sandboxes preview *feature* on the scheduler is a
# separate, out-of-band step handled during private-preview onboarding.

$ErrorActionPreference = 'Stop'

function Get-RequiredEnv([string]$name) {
$value = [Environment]::GetEnvironmentVariable($name)
if ([string]::IsNullOrEmpty($value)) {
throw "$name must be set"
}
return $value
}

$SubscriptionId = Get-RequiredEnv 'AZURE_SUBSCRIPTION_ID'
$SchedulerName = Get-RequiredEnv 'DTS_SCHEDULER_NAME'
$SchedulerRg = Get-RequiredEnv 'DTS_SCHEDULER_RESOURCE_GROUP'
$IdentityId = Get-RequiredEnv 'AZURE_USER_ASSIGNED_IDENTITY_RESOURCE_ID'

Write-Host "==> Ensuring the 'durabletask' Azure CLI extension is installed..."
az extension add --name durabletask --upgrade --only-show-errors | Out-Null
if ($LASTEXITCODE -ne 0) { throw "Failed to add the 'durabletask' az extension" }

Write-Host "==> Attaching managed identity to scheduler '$SchedulerName'..."
az durabletask scheduler identity assign `
--subscription $SubscriptionId `
--resource-group $SchedulerRg `
--name $SchedulerName `
--user-assigned $IdentityId | Out-Null
if ($LASTEXITCODE -ne 0) { throw "Failed to assign identity to scheduler '$SchedulerName'" }

$IdentityName = $IdentityId.Substring($IdentityId.LastIndexOf('/') + 1)
Write-Host "==> Done. Identity $IdentityName is attached to '$SchedulerName'."
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# NOTE: enabling the On-demand Sandboxes preview *feature* on the scheduler is a
# separate, out-of-band step handled during private-preview onboarding.

set -euo pipefail
set -eu

SUBSCRIPTION_ID="${AZURE_SUBSCRIPTION_ID:?AZURE_SUBSCRIPTION_ID must be set}"
SCHEDULER_NAME="${DTS_SCHEDULER_NAME:?DTS_SCHEDULER_NAME must be set}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ ENV GRPC_DEFAULT_SSL_ROOTS_FILE_PATH=/etc/ssl/certs/ca-certificates.crt
# Install the Durable Task SDK (with the sandboxes extension), plus pandas for
# the LLM-generated scripts the sandbox executes.
RUN pip install --no-cache-dir \
durabletask==1.6.0 \
durabletask-azuremanaged==1.6.0 \
azure-identity \
"pandas==2.2.*"
Expand Down
31 changes: 21 additions & 10 deletions preview-features/on-demand-sandboxes/samples/python/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# On-demand Sandboxes demo (Python): LLM-generated code interpreter

The Python port of the [.NET demo](../dotnet/README.md). A three-step Durable Task
workflow that demonstrates the **On-demand Sandboxes** preview of Azure Durable
A three-step Durable Task workflow that demonstrates the **On-demand Sandboxes** preview of Azure Durable
Task Scheduler (DTS), using the `durabletask.azuremanaged.preview.sandboxes`
package.

Expand Down Expand Up @@ -32,22 +31,27 @@ python/
registered on the main app worker.
- `generate_code` and `format_answer` run in-process in the main app worker.

## Prerequisites
## Prerequisites (local development)

These prerequisites are for running the sample **locally** (building the sandbox image
and running the orchestrator on your machine). To deploy to Azure instead, skip to
[Deploy to Azure (AKS) with `azd`](#deploy-to-azure-aks-with-azd), which has its own
prerequisites.

- Python 3.12+
- Docker (to build the sandbox image)
- Azure CLI (`az`), signed in with access to the scheduler, ACR, and Azure OpenAI
- A DTS scheduler + task hub with the On-demand Sandboxes preview enabled
- An Azure Container Registry the sandbox platform can pull from
- An Azure Container Registry the image-pull identity can pull from (granted AcrPull)
- Two user-assigned managed identities (image pull + scheduler connect)
- An Azure OpenAI deployment of a chat model (GPT-4o, GPT-4.1, etc.)
- An Azure OpenAI deployment of a chat model (GPT-5.1, GPT-5, GPT-4.1, etc.)

## Install

From the `python/` directory:

```bash
pip install -r requirements.txt
pip install durabletask==1.6.0 durabletask-azuremanaged==1.6.0
```

## Build the sandbox image
Expand All @@ -63,10 +67,16 @@ docker build \
-t $IMAGE \
.

# Enable anonymous pull so DTS can fetch the sandbox image without credentials
az acr update --name $ACR --anonymous-pull-enabled true
az acr login --name $ACR
docker push $IMAGE

# DTS pulls the sandbox image using the image-pull managed identity (not anonymous
# pull). Grant that identity AcrPull on the registry -- use the same UMI you pass as
# DTS_SANDBOX_IMAGE_PULL_UMI_CLIENT_ID when running the orchestrator.
az role assignment create \
--assignee "<image-pull UMI client ID>" \
--role AcrPull \
--scope "$(az acr show --name $ACR --query id -o tsv)"
```

## Run the orchestrator
Expand Down Expand Up @@ -103,7 +113,8 @@ on demand, so it is never deployed as a Container App.
> The Durable Task Scheduler is **not created** by this template. You pass in an
> existing one. On-demand Sandboxes is a private-preview feature that must be enabled on
> the scheduler out of band, so the scheduler is patched separately and supplied here by
> name.
> name. The scheduler must be in a supported preview region: East US 2, West US 3, North
> Europe, or Australia East.

### What gets provisioned

Expand All @@ -118,7 +129,7 @@ The deployment also **ensures the task hub** exists, grants the identity the rol
needs (AcrPull, Durable Task data access, Cognitive Services OpenAI User), and a
`postprovision` hook **attaches the identity to your scheduler** (a merge-safe PATCH).

### Prerequisites
### Prerequisites (Azure deployment)

- An existing **DTS scheduler** with the On-demand Sandboxes preview enabled, and its
resource group name.
Expand Down
16 changes: 12 additions & 4 deletions preview-features/on-demand-sandboxes/samples/python/azure.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,19 @@ metadata:
name: dts-ondemand-sandboxes-python
hooks:
predeploy:
shell: sh
run: ./scripts/acr-build.sh
posix:
shell: sh
run: ./scripts/acr-build.sh
windows:
shell: pwsh
run: ./scripts/acr-build.ps1
postprovision:
shell: sh
run: ./scripts/attach-scheduler-identity.sh
posix:
shell: sh
run: ./scripts/attach-scheduler-identity.sh
windows:
shell: pwsh
run: ./scripts/attach-scheduler-identity.ps1
services:
mainapp:
project: .
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Declarer-app (main_app.py) dependencies.
durabletask==1.6.0
durabletask-azuremanaged==1.6.0
azure-identity>=1.16
openai>=1.40
Loading