Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
40a54a9
Add Durable Task Scheduler skill
greenie-msft Feb 11, 2026
28d208e
Update DTS skill to include RBAC guidance and SKU guidance
greenie-msft Feb 13, 2026
44c659e
Add DTS to architecture guidance table for workflow
greenie-msft Feb 13, 2026
7ee8a8e
Address PR #919 feedback: fix auth levels, capitalization, and Bicep …
greenie-msft Feb 26, 2026
5029f1d
Move DTS deployment content to azure-deploy skill
greenie-msft Feb 26, 2026
86216ff
Pin NuGet package versions to latest stable
greenie-msft Feb 26, 2026
9f0ae81
Update plugin/skills/azure-prepare/references/services/durable-task-s…
greenie-msft Feb 26, 2026
b69b461
Fix link checker failures
greenie-msft Feb 26, 2026
a98054c
Add DTS to research.md service mapping to fix orphan check
greenie-msft Feb 26, 2026
ab371ec
Update plugin/skills/azure-prepare/references/research.md
greenie-msft Feb 26, 2026
8c8d03e
Address Copilot review: fix plan.md ref, add Bicep params, align UAMI…
greenie-msft Feb 26, 2026
61fcec3
Restructure DTS as directory with per-language sub-files
greenie-msft Feb 26, 2026
4ce7a98
Fix link checker: replace cross-skill link in bicep.md with text refe…
greenie-msft Feb 26, 2026
3ce0c82
Address Copilot review: standardize host.json, fix snippets
greenie-msft Feb 26, 2026
be1b711
Update plugin/skills/azure-prepare/references/research.md
paulyuk Feb 26, 2026
34955c3
Move Learn More to top, standardize env vars across all files
greenie-msft Feb 26, 2026
4f730c4
fix: capitalize DTS SKU names in Bicep examples (Consumption/Dedicated)
greenie-msft Feb 27, 2026
7e25a86
feat: add DTS dashboard RBAC for deploying user
greenie-msft Feb 27, 2026
4b62382
fix: address PR review comments
greenie-msft Feb 27, 2026
60c0174
revert: remove DTS deploy recipe from azure-deploy skill
greenie-msft Feb 28, 2026
dc928d3
Add DTS integration tests and update routing to choose Durable Task S…
greenie-msft Mar 3, 2026
c57898a
Add DTS integration test for azure-prepare and azure-deploy. Address …
Mar 4, 2026
ba0ddfe
chore: bump azure-deploy to 1.0.4 and azure-prepare to 1.0.3
Mar 4, 2026
5f4cd17
fix: correct relative links to durable-task-scheduler folder
Mar 4, 2026
301d39f
fix: resolve remaining conflict markers in azure-deploy SKILL.md
Mar 4, 2026
a9cc058
docs: expand ACA/AKS abbreviations to full names in DTS references
Mar 4, 2026
88d9040
fix: add taskHubs to DTS Bicep resource requirement in SKILL.md routi…
greenie-msft Mar 4, 2026
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
2 changes: 1 addition & 1 deletion plugin/skills/azure-deploy/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: "Execute Azure deployments for ALREADY-PREPARED applications that h
license: MIT
metadata:
author: Microsoft
version: "1.0.3"
version: "1.0.4"
---

# Azure Deploy
Expand Down
16 changes: 16 additions & 0 deletions plugin/skills/azure-deploy/references/pre-deploy-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,22 @@ azd up --no-prompt

---

## Service-Specific Checks

### Durable Functions — Verify DTS Backend

> **⛔ MANDATORY**: If the plan includes Durable Functions, verify infrastructure uses **Durable Task Scheduler** (DTS), NOT Azure Storage.

Check that `infra/` Bicep files contain:
- `Microsoft.DurableTask/schedulers` resource
- `Microsoft.DurableTask/schedulers/taskHubs` child resource
- `Durable Task Data Contributor` RBAC role assignment
- `DURABLE_TASK_SCHEDULER_CONNECTION_STRING` app setting

If any are missing, **STOP** and invoke **azure-prepare** to regenerate with the durable recipe.

---

## Non-AZD Deployments

**For Azure CLI / Bicep:**
Expand Down
3 changes: 2 additions & 1 deletion plugin/skills/azure-prepare/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: "Prepare Azure apps for deployment (infra Bicep/Terraform, azure.ya
license: MIT
metadata:
author: Microsoft
version: "1.0.2"
version: "1.0.3"
---

# Azure Prepare
Expand Down Expand Up @@ -63,6 +63,7 @@ Activate this skill when user wants to:
| Azure Functions, function app, serverless function, timer trigger, HTTP trigger, func new | Stay in **azure-prepare** — prefer Azure Functions templates in Step 4 |
| APIM, API Management, API gateway, deploy APIM | Stay in **azure-prepare** — see [APIM Deployment Guide](references/apim.md) |
| AI gateway, AI gateway policy, AI gateway backend, AI gateway configuration | **azure-aigateway** |
| workflow, orchestration, multi-step, pipeline, fan-out/fan-in, saga, long-running process, durable | Stay in **azure-prepare** — select **durable** recipe in Step 4. **MUST** load [durable.md](references/services/functions/durable.md) and [DTS reference](references/services/durable-task-scheduler/README.md). Generate `Microsoft.DurableTask/schedulers` + `taskHubs` Bicep resources. |

> ⚠️ Check the user's **prompt text** — not just existing code. Critical for greenfield projects with no codebase to scan. See [full routing table](references/specialized-routing.md).

Expand Down
11 changes: 9 additions & 2 deletions plugin/skills/azure-prepare/references/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ Select hosting stack and map components to Azure services.
| Event-driven | ✓ | ✓✓ | |
| Variable traffic | | ✓✓ | ✓ |
| Complex dependencies | ✓✓ | | ✓ |
| Long-running processes | ✓✓ | | ✓ |
| Long-running processes | ✓✓ | ✓ (Durable Functions) | ✓ |
| Workflow / orchestration | | ✓✓ (Durable Functions + DTS) | |
| Minimal ops overhead | | ✓✓ | ✓ |

## Service Mapping
Expand Down Expand Up @@ -51,7 +52,13 @@ Select hosting stack and map components to Azure services.
| Message Queue | Service Bus |
| Pub/Sub | Event Grid |
| Streaming | Event Hubs |
| Workflow | Logic Apps, Durable Functions |

### Workflow & Orchestration

| Need | Service | Notes |
|------|---------|-------|
| Multi-step workflow / orchestration | **Durable Functions + Durable Task Scheduler** | DTS is the **required** managed backend for Durable Functions. Do NOT use Azure Storage or MSSQL backends. See [durable.md](services/functions/durable.md). |
| Low-code / visual workflow | Logic Apps | For integration-heavy, low-code scenarios |

### Supporting (Always Include)

Expand Down
3 changes: 3 additions & 0 deletions plugin/skills/azure-prepare/references/research.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ After architecture planning, research each selected component to gather best pra
| **Integration** | | |
| API Management | [APIM](apim.md) | `azure-aigateway` (invoke for AI Gateway policies) |
| Logic Apps | [Logic Apps](services/logic-apps/README.md) | — |
| **Workflow & Orchestration** | | |
| Durable Functions | [Durable Functions](services/functions/durable.md), [Durable Task Scheduler](services/durable-task-scheduler/README.md) | — |
| Durable Task Scheduler | [Durable Task Scheduler](services/durable-task-scheduler/README.md) | — |
| **Security & Identity** | | |
| Key Vault | [Key Vault](services/key-vault/README.md) | `azure-security`, `azure-keyvault-expiration-audit` |
| Managed Identity | — | `azure-security`, `entra-app-registration` |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Durable Task Scheduler

Build reliable, fault-tolerant workflows using durable execution with Azure Durable Task Scheduler.

## When to Use

- Long-running workflows requiring state persistence
- Distributed transactions with compensating actions (saga pattern)
- Multi-step orchestrations with checkpointing
- Fan-out/fan-in parallel processing
- Workflows requiring human interaction or external events
- Stateful entities (aggregators, counters, state machines)
- Multi-agent AI orchestration
- Data processing pipelines

## Framework Selection

| Framework | Best For | Hosting |
|-----------|----------|---------|
| **Durable Functions** | Serverless event-driven apps | Azure Functions |
| **Durable Task SDKs** | Any compute (containers, VMs) | Azure Container Apps, Azure Kubernetes Service, App Service, VMs |

> **💡 TIP**: Use Durable Functions for serverless with built-in triggers. Use Durable Task SDKs for hosting flexibility.

## Quick Start - Local Emulator

```bash
# Start the emulator (see https://mcr.microsoft.com/v2/dts/dts-emulator/tags/list for available versions)
docker pull mcr.microsoft.com/dts/dts-emulator:latest
docker run -d -p 8080:8080 -p 8082:8082 --name dts-emulator mcr.microsoft.com/dts/dts-emulator:latest

# Dashboard available at http://localhost:8082
```

## Workflow Patterns

| Pattern | Use When |
|---------|----------|
| **Function Chaining** | Sequential steps, each depends on previous |
| **Fan-Out/Fan-In** | Parallel processing with aggregated results |
| **Async HTTP APIs** | Long-running operations with HTTP polling |
| **Monitor** | Periodic polling with configurable timeouts |
| **Human Interaction** | Workflow pauses for external input/approval |
| **Saga** | Distributed transactions with compensation |
| **Durable Entities** | Stateful objects (counters, accounts) |

## Connection & Authentication

| Environment | Connection String |
|-------------|-------------------|
| Local Development (Emulator) | `Endpoint=http://localhost:8080;Authentication=None;TaskHub=default` |
| Azure (System-Assigned MI) | `Endpoint=https://<scheduler>.durabletask.io;Authentication=ManagedIdentity;TaskHub=default` |
| Azure (User-Assigned MI) | `Endpoint=https://<scheduler>.durabletask.io;Authentication=ManagedIdentity;ClientID=<uami-client-id>;TaskHub=default` |

> **⚠️ NOTE**: Durable Task Scheduler uses identity-based authentication only — no connection strings with keys. When using a User-Assigned Managed Identity (UAMI), you must include the `ClientID` in the connection string.

## Troubleshooting

| Error | Cause | Fix |
|-------|-------|-----|
| **403 PermissionDenied** on gRPC call (e.g., `client.start_new()`) | Function App managed identity lacks RBAC on the Durable Task Scheduler resource, or IP allowlist blocks traffic | 1. Assign `Durable Task Data Contributor` role (`0ad04412-c4d5-4796-b79c-f76d14c8d402`) to the identity (SAMI or UAMI) scoped to the Durable Task Scheduler resource. For UAMI, also ensure the connection string includes `ClientID=<uami-client-id>`. 2. Ensure the scheduler's `ipAllowlist` includes `0.0.0.0/0` (an empty list denies all traffic). 3. RBAC propagation can take up to 10 minutes — restart the Function App after assigning roles. |
| **Connection refused** to emulator | Emulator container not running or wrong port | Verify container is running: `docker ps` and confirm port 8080 is mapped |
| **403 despite correct RBAC** | Scheduler IP allowlist is empty (denies all) | Set `ipAllowlist: ['0.0.0.0/0']` in Bicep or update via CLI: `az durabletask scheduler update --ip-allowlist '0.0.0.0/0'` |
| **TaskHub not found** | Task hub not provisioned or name mismatch | Ensure the `TaskHub` parameter in the `DURABLE_TASK_SCHEDULER_CONNECTION_STRING` matches the provisioned task hub name |
| **403 Forbidden** on DTS dashboard | Deploying user lacks RBAC on the scheduler | Assign `Durable Task Data Contributor` role to your own user identity (not just the Function App MI) scoped to the scheduler resource — see [Bicep Patterns](bicep.md) for the dashboard role assignment snippet |

## References

- [.NET](dotnet.md) — packages, setup, examples, determinism, retry, SDK
- [Python](python.md) — packages, setup, examples, determinism, retry, SDK
- [Java](java.md) — dependencies, setup, examples, determinism, retry, SDK
- [JavaScript](javascript.md) — packages, setup, examples, determinism, retry, SDK
- [Bicep Patterns](bicep.md) — scheduler, task hub, RBAC, CLI provisioning
- [Official Documentation](https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler)
- [Durable Functions Overview](https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview)
- [Sample Repository](https://github.com/Azure-Samples/Durable-Task-Scheduler)
- [Choosing an Orchestration Framework](https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/choose-orchestration-framework)
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Durable Task Scheduler — Bicep Patterns

Bicep templates for provisioning the Durable Task Scheduler, task hubs, and RBAC role assignments.

## Scheduler + Task Hub

```bicep
// Parameters — define these at file level or pass from a parent module
param schedulerName string
param location string = resourceGroup().location

@allowed(['Consumption', 'Dedicated'])
@description('Use Consumption for quickstarts/variable workloads, Dedicated for high-demand/predictable throughput')
param skuName string = 'Consumption'

resource scheduler 'Microsoft.DurableTask/schedulers@2025-11-01' = {
name: schedulerName
location: location
properties: {
sku: { name: skuName }
ipAllowlist: ['0.0.0.0/0'] // Required: empty list denies all traffic
}
}

resource taskHub 'Microsoft.DurableTask/schedulers/taskHubs@2025-11-01' = {
parent: scheduler
name: 'default'
}
```

## SKU Selection

| SKU | Best For |
|-----|----------|
| **Consumption** | quickstarts, variable or bursty workloads, pay-per-use |
| **Dedicated** | High-demand workloads, predictable throughput requirements |

> **💡 TIP**: Start with `Consumption` for development and variable workloads. Switch to `Dedicated` when you need consistent, high-throughput performance.

> **⚠️ WARNING**: The scheduler's `ipAllowlist` **must** include at least one entry (e.g., `['0.0.0.0/0']` for allow-all). An empty array `[]` denies **all** traffic, causing 403 errors on gRPC calls even with correct RBAC.

## RBAC — Durable Task Data Contributor

The Function App's managed identity **must** have the `Durable Task Data Contributor` role on the scheduler resource. Without it, the app receives **403 PermissionDenied** on gRPC calls.

```bicep
// Assumes the UAMI principal ID is passed from the base template's identity module
param functionAppPrincipalId string

var durableTaskDataContributorRoleId = '0ad04412-c4d5-4796-b79c-f76d14c8d402'

resource durableTaskRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(scheduler.id, functionAppPrincipalId, durableTaskDataContributorRoleId)
scope: scheduler
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', durableTaskDataContributorRoleId)
principalId: functionAppPrincipalId
principalType: 'ServicePrincipal'
}
}
```

## RBAC — Dashboard Access for Developers

To allow developers to view orchestration status and history in the [DTS dashboard](https://portal.azure.com), assign the same `Durable Task Data Contributor` role to the deploying user's identity. Without this, the dashboard returns **403 Forbidden**.

```bicep
// Accept the deploying user's principal ID (azd auto-populates this from AZURE_PRINCIPAL_ID)
param principalId string = ''

resource dashboardRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!empty(principalId)) {
name: guid(scheduler.id, principalId, durableTaskDataContributorRoleId)
scope: scheduler
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', durableTaskDataContributorRoleId)
principalId: principalId
principalType: 'User'
}
}
```

> **💡 TIP**: This is the same role used for the Function App's managed identity, but assigned with `principalType: 'User'` to the developer. See the [sample repo](https://github.com/Azure-Samples/Durable-Task-Scheduler/blob/main/samples/infra/main.bicep) for a full example.

## Connection String App Setting

Include these entries in the Function App resource's `siteConfig.appSettings` array:

```bicep
// UAMI client ID from base template identity module - REQUIRED for UAMI auth
param uamiClientId string

{
name: 'DURABLE_TASK_SCHEDULER_CONNECTION_STRING'
value: 'Endpoint=${scheduler.properties.endpoint};TaskHub=${taskHub.name};Authentication=ManagedIdentity;ClientID=${uamiClientId}'
}
```

> **⚠️ IMPORTANT**: The base templates use User Assigned Managed Identity (UAMI). You **must** include `ClientID=<uami-client-id>` in the connection string. Without it, the Durable Task SDK cannot resolve the correct identity.

> **⚠️ WARNING**: Always use `scheduler.properties.endpoint` to get the scheduler URL. Do **not** construct it manually — the endpoint includes a hash suffix and region (e.g., `https://myscheduler-abc123.westus2.durabletask.io`).

## Provision via CLI

> **💡 TIP**: When hosting Durable Functions, use a **Flex Consumption** plan (`FC1` SKU) rather than the legacy Consumption plan (`Y1`). Flex Consumption supports identity-based storage connections natively and handles deployment artifacts correctly.

```bash
# Install the durabletask CLI extension (if not already installed)
az extension add --name durabletask

# Create scheduler (consumption SKU for getting started)
az durabletask scheduler create \
--resource-group myResourceGroup \
--name my-scheduler \
--location eastus \
--sku consumption
```
Loading
Loading