Skip to content

Commit d8cb5e2

Browse files
authored
Merge pull request #65 from Azure-Samples/feature/migrate-to-agent-framework
Feature/migrate to agent framework
2 parents 00803cc + 9238501 commit d8cb5e2

19 files changed

+1484
-619
lines changed

.gitignore

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,14 @@ appsettings.json
4747
.env.*.local
4848
.azure/
4949

50+
# Azurite storage emulator files
5051
__azurite_db_blob__.json
51-
5252
__azurite_db_blob_extent__.json
53-
53+
__azurite_db_queue__.json
54+
__azurite_db_queue_extent__.json
55+
__azurite_db_table__.json
5456
__blobstorage__/
57+
__queuestorage__/
58+
AzuriteConfig
59+
5560
src/nohup.out

LOCAL_DEVELOPMENT.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,159 @@
22

33
This document explains how local development authentication works for this Azure Functions project.
44

5+
## Quick Start
6+
7+
### Option A: With Docker (Recommended)
8+
9+
The fastest way to get started is using Docker Compose:
10+
11+
```bash
12+
# Start both Azurite and DTS emulator
13+
docker compose up -d
14+
15+
# Generate local settings from your Azure environment
16+
./scripts/generate-settings.sh
17+
18+
# Run the Functions app
19+
cd src
20+
func start
21+
```
22+
23+
**Dashboard URLs:**
24+
25+
- DTS Dashboard: <http://localhost:8082/>
26+
- Azurite Blob: <http://localhost:10000/>
27+
28+
To stop the emulators:
29+
30+
```bash
31+
docker compose down
32+
```
33+
34+
### Option B: Without Docker - Native Azurite + Azure Storage Backend
35+
36+
If Docker is not available, you can use native Azurite and Azure Storage for Durable Functions:
37+
38+
```bash
39+
# 1. Install Azurite globally via npm
40+
npm install -g azurite
41+
42+
# 2. Start Azurite in a separate terminal
43+
azurite
44+
45+
# 3. Temporarily switch to Azure Storage backend (see configuration below)
46+
47+
# 4. Generate local settings
48+
./scripts/generate-settings.sh
49+
50+
# 5. Run the Functions app
51+
cd src
52+
func start
53+
```
54+
55+
**Configuration changes for Azure Storage backend:**
56+
57+
Temporarily update `src/host.json` durableTask section:
58+
59+
```json
60+
"durableTask": {
61+
"hubName": "%TASKHUB_NAME%",
62+
"storageProvider": {
63+
"type": "azureStorage",
64+
"connectionStringName": "AzureWebJobsStorage"
65+
},
66+
"tracing": {
67+
"traceInputsAndOutputs": true
68+
}
69+
}
70+
```
71+
72+
Your `local.settings.json` should have:
73+
74+
```json
75+
{
76+
"Values": {
77+
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
78+
"TASKHUB_NAME": "default"
79+
}
80+
}
81+
```
82+
83+
**Note:** This approach uses Azure Storage (via Azurite) instead of DTS for orchestration state. You won't have the DTS dashboard, but all Durable Functions features will work.
84+
85+
### Switching Between Backends
86+
87+
Use the provided helper script to easily switch between DTS and Azure Storage:
88+
89+
```bash
90+
# Switch to Azure Storage (for environments without Docker)
91+
./scripts/switch-storage-backend.sh azureStorage
92+
93+
# Switch back to DTS (when Docker is available)
94+
./scripts/switch-storage-backend.sh dts
95+
```
96+
97+
PowerShell:
98+
99+
```powershell
100+
# Switch to Azure Storage
101+
.\scripts\switch-storage-backend.ps1 azureStorage
102+
103+
# Switch to DTS
104+
.\scripts\switch-storage-backend.ps1 dts
105+
```
106+
107+
The script automatically updates your `host.json` configuration and provides instructions for the required environment setup.
108+
109+
## Prerequisites
110+
111+
Before you begin, ensure you have:
112+
113+
1. **Docker** installed for running the Durable Task Scheduler emulator
114+
2. **Azurite** installed for local Azure Storage emulation
115+
3. **Azure CLI** installed and configured
116+
117+
## Durable Task Scheduler Setup
118+
119+
This project uses the **Durable Task Scheduler** (DTS) for orchestration instead of Azure Storage. For local development, you need to run the DTS emulator.
120+
121+
### 1. Start the DTS Emulator
122+
123+
Pull and run the DTS emulator Docker container:
124+
125+
```bash
126+
# Pull the emulator image
127+
docker pull mcr.microsoft.com/dts/dts-emulator:latest
128+
129+
# Run the emulator (exposes ports 8080 for gRPC and 8082 for dashboard)
130+
docker run -d -p 8080:8080 -p 8082:8082 mcr.microsoft.com/dts/dts-emulator:latest
131+
```
132+
133+
The emulator exposes two ports:
134+
- **8080**: gRPC endpoint for the Functions app to connect
135+
- **8082**: Dashboard UI at http://localhost:8082/
136+
137+
### 2. Start Azurite
138+
139+
The Azure Functions runtime still requires Azurite for some components:
140+
141+
```bash
142+
azurite start
143+
```
144+
145+
### 3. Verify Configuration
146+
147+
Check that your `local.settings.json` includes these DTS-specific settings:
148+
149+
```json
150+
{
151+
"Values": {
152+
"DTS_CONNECTION_STRING": "Endpoint=http://localhost:8080;Authentication=None",
153+
"TASKHUB_NAME": "default"
154+
}
155+
}
156+
```
157+
5158
## Authentication Approach
6159

7160
This project uses **Azure Managed Identity** for authentication - both in production AND for local development. **No API keys are required!**
@@ -64,6 +217,16 @@ func start
64217

65218
The Azure Functions runtime will automatically use your Azure credentials via `DefaultAzureCredential`.
66219

220+
### 5. Monitor Orchestrations
221+
222+
You can monitor orchestration instances in real-time using the DTS dashboard:
223+
224+
1. Open <http://localhost:8082/> in your browser
225+
2. Click on your task hub (default: **default**)
226+
3. View orchestration status, history, and execution details
227+
228+
**Note**: The DTS emulator stores data in memory, so all orchestration data is lost when the container stops.
229+
67230
## Benefits of This Approach
68231

69232
**No secrets to manage** - No API keys in config files or environment variables

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,59 @@ azd down --purge
182182

183183
> **Note**: The first run automatically creates an Azure AD app registration with OAuth2 scope `access_as_user` for authentication.
184184
185+
### Local Development with Emulators
186+
187+
For local development, Snippy uses the **Durable Task Scheduler (DTS) emulator** and **Azurite** for storage.
188+
189+
#### With Docker (Recommended)
190+
191+
The easiest way to run both emulators:
192+
193+
```bash
194+
# Start both emulators
195+
docker compose up -d
196+
197+
# Generate local.settings.json from your Azure environment
198+
./scripts/generate-settings.sh
199+
200+
# Run the Functions app
201+
cd src
202+
func start
203+
```
204+
205+
**Available Dashboards:**
206+
207+
* **DTS Dashboard**: <http://localhost:8082/> - Monitor orchestration instances, view execution history
208+
* **Azurite**: Runs on ports 10000-10002 for Blob, Queue, and Table services
209+
210+
#### Without Docker
211+
212+
If Docker is not available, you can use native Azurite with Azure Storage backend:
213+
214+
```bash
215+
# 1. Install Azurite globally
216+
npm install -g azurite
217+
218+
# 2. Switch to Azure Storage backend
219+
./scripts/switch-storage-backend.sh azureStorage
220+
221+
# 3. Start Azurite in a separate terminal
222+
azurite
223+
224+
# 4. Generate settings and run
225+
./scripts/generate-settings.sh
226+
cd src
227+
func start
228+
```
229+
230+
To switch back to DTS when Docker becomes available:
231+
232+
```bash
233+
./scripts/switch-storage-backend.sh dts
234+
```
235+
236+
For detailed setup instructions and troubleshooting, see [LOCAL_DEVELOPMENT.md](LOCAL_DEVELOPMENT.md).
237+
185238
---
186239

187240
## Guidance

docker-compose.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
version: '3.8'
2+
3+
services:
4+
# Azure Storage Emulator (Azurite)
5+
azurite:
6+
image: mcr.microsoft.com/azure-storage/azurite:latest
7+
container_name: snippy-azurite
8+
ports:
9+
- "10000:10000" # Blob service
10+
- "10001:10001" # Queue service
11+
- "10002:10002" # Table service
12+
volumes:
13+
- azurite-data:/data
14+
command: azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0
15+
restart: unless-stopped
16+
17+
# Durable Task Scheduler Emulator
18+
dts-emulator:
19+
image: mcr.microsoft.com/dts/dts-emulator:latest
20+
container_name: snippy-dts-emulator
21+
ports:
22+
- "8080:8080" # gRPC endpoint for Function App connection
23+
- "8082:8082" # Dashboard UI
24+
restart: unless-stopped
25+
26+
volumes:
27+
azurite-data:
28+
name: snippy-azurite-data

infra/app/api.bicep

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ module api 'br/public:avm/res/web/site:0.15.1' = {
7676
scaleAndConcurrency: {
7777
instanceMemoryMB: instanceMemoryMB
7878
maximumInstanceCount: maximumInstanceCount
79+
alwaysReady: [
80+
{
81+
name: 'http'
82+
instanceCount: 1
83+
}
84+
{
85+
name: 'durable'
86+
instanceCount: 1
87+
}
88+
]
7989
}
8090
runtime: {
8191
name: runtimeName

infra/main.bicep

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,11 @@ module api './app/api.bicep' = {
225225
EMBEDDING_MODEL_DEPLOYMENT_NAME: openai.outputs.embeddingDeploymentName
226226
AGENTS_MODEL_DEPLOYMENT_NAME: openai.outputs.chatDeploymentName
227227
COSMOS_VECTOR_TOP_K: '30'
228-
AZURE_OPENAI_ENDPOINT: openai.outputs.aiServicesEndpoint
228+
AZURE_OPENAI_ENDPOINT: openai.outputs.azureOpenAIServiceEndpoint
229229
PROJECT_ENDPOINT: openai.outputs.aiFoundryProjectEndpoint
230230
AZURE_CLIENT_ID: apiUserAssignedIdentity.outputs.clientId
231231
DTS_CONNECTION_STRING: 'Endpoint=${dts.outputs.dts_URL};Authentication=ManagedIdentity;ClientID=${apiUserAssignedIdentity.outputs.clientId}'
232-
TASKHUBNAME: dts.outputs.TASKHUB_NAME
232+
TASKHUB_NAME: dts.outputs.TASKHUB_NAME
233233
}
234234
}
235235
dependsOn: [

scripts/generate-settings.ps1

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,26 @@ $cosmosEndpoint = ($envValues | Select-String 'COSMOS_ENDPOINT="([^"]*)"').Match
77
$azureOpenAIEndpoint = ($envValues | Select-String 'AZURE_OPENAI_ENDPOINT="([^"]*)"').Matches.Groups[1].Value
88
$projectEndpoint = ($envValues | Select-String 'PROJECT_ENDPOINT="([^"]*)"').Matches.Groups[1].Value
99
$azureWebJobsStorage = ($envValues | Select-String 'AZUREWEBJOBSSTORAGE="([^"]*)"').Matches.Groups[1].Value
10+
$dtsUrl = ($envValues | Select-String 'DTS_URL="([^"]*)"').Matches.Groups[1].Value
11+
$taskhubName = ($envValues | Select-String 'TASKHUB_NAME="([^"]*)"').Matches.Groups[1].Value
12+
13+
# Use default taskhub name if not found
14+
if ([string]::IsNullOrEmpty($taskhubName)) {
15+
$taskhubName = "SnippyTaskHub"
16+
}
1017

1118
# Create or update local.settings.json
1219
Write-Host "Generating local.settings.json in src directory..."
1320
$settingsJson = @"
1421
{
1522
"IsEncrypted": false,
1623
"Values": {
24+
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
1725
"AzureWebJobsSecretStorageType": "files",
1826
"FUNCTIONS_WORKER_RUNTIME": "python",
1927
"PYTHON_ENABLE_WORKER_EXTENSIONS": "True",
28+
"DTS_CONNECTION_STRING": "Endpoint=http://localhost:8080;Authentication=None",
29+
"TASKHUB_NAME": "default",
2030
"COSMOS_DATABASE_NAME": "dev-snippet-db",
2131
"COSMOS_CONTAINER_NAME": "code-snippets",
2232
"BLOB_CONTAINER_NAME": "snippet-backups",
@@ -34,7 +44,14 @@ $settingsJson | Out-File -FilePath "src/local.settings.json" -Encoding utf8
3444
Write-Host ""
3545
Write-Host "✅ local.settings.json generated successfully!" -ForegroundColor Green
3646
Write-Host ""
37-
Write-Host "📝 Note: This configuration uses Azure credential authentication (no API key)." -ForegroundColor Cyan
47+
Write-Host "📝 Note: This configuration uses:" -ForegroundColor Cyan
48+
Write-Host " - Durable Task Scheduler emulator at http://localhost:8080" -ForegroundColor Cyan
49+
Write-Host " - Azure credential authentication for Azure services (no API key)" -ForegroundColor Cyan
3850
Write-Host " - Make sure you're logged in: az login" -ForegroundColor Cyan
3951
Write-Host " - You should have been automatically assigned the 'Cognitive Services OpenAI User' role" -ForegroundColor Cyan
40-
Write-Host " - If you get authentication errors, verify your role assignment in the Azure Portal" -ForegroundColor Cyan
52+
Write-Host ""
53+
Write-Host "🐳 Before running 'func start', start the DTS emulator:" -ForegroundColor Yellow
54+
Write-Host " docker compose up -d" -ForegroundColor Yellow
55+
Write-Host " # Or manually: docker run -d -p 8080:8080 -p 8082:8082 mcr.microsoft.com/dts/dts-emulator:latest" -ForegroundColor Yellow
56+
Write-Host ""
57+
Write-Host "📊 DTS Dashboard will be available at: http://localhost:8082/" -ForegroundColor Yellow

0 commit comments

Comments
 (0)