con un clic
up
// Creates an azd environment, checks prerequisites (RBAC, model quota), provisions the AI chat app infrastructure via `azd up`, and health-checks the deployed app.
// Creates an azd environment, checks prerequisites (RBAC, model quota), provisions the AI chat app infrastructure via `azd up`, and health-checks the deployed app.
| name | up |
| description | Creates an azd environment, checks prerequisites (RBAC, model quota), provisions the AI chat app infrastructure via `azd up`, and health-checks the deployed app. |
Provision a fresh Azure environment end-to-end and verify the app starts successfully.
When the skill is triggered, always re-read this SKILL.md file from disk before executing, in case it has been updated since the last run.
Then proceed to Step 1 (Choose environment name) immediately — the user must pick an environment before anything else.
All shell commands in this skill must be run using the powershell tool with
mode="sync". Use a short initial_wait (30 seconds) for quick commands like
az account show, az ad signed-in-user show, az role assignment list,
azd env list, azd env new, and azd env set.
Exception — azd up and azd down: These long-running commands must be run
with mode="async" and a short initial_wait (10 seconds) so the user can see
streaming progress output in real time (just like running in a terminal). After
launching, poll frequently using read_powershell with a short delay (15–20
seconds) — this is critical so the user sees output updates as they happen, similar
to watching the command in a terminal. Keep calling read_powershell in a loop
(each call in a new response turn) until the command completes or you receive a
completion notification. Do NOT use long delays like 120 seconds — that defeats the
purpose of streaming output.
Chain short related commands with && or ; into a single powershell call
when they have no branching logic between them.
First, check whether there is already a default azd environment:
$existingEnvs = azd env list -o json 2>$null | ConvertFrom-Json
Find the default environment (the entry where IsDefault is true or the DefaultEnvironment
field is set, depending on the azd version).
Regardless of whether a default environment exists, always prepare a suggested new name for use as a choice.
Scan $existingEnvs for names matching the pattern <prefix><number> (e.g., aichat1,
test-env3, chat-2). If found, take the one with the highest number and suggest
the next increment (e.g., aichat2, test-env4, chat-3).
If no numbered environments exist, generate a default name:
$suffix = -join ((0..9) + ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z') | Get-Random -Count 6)
$suggestedName = "aichat-$suffix"
If a default environment was found, present the user with choices:
<defaultEnvName> — re-provision/update the existing
environment (first choice, include the environment name in the label)<suggestedName> — use the suggested new name from 1bFor example:
Do you want to
azd upthe current environmentaichat2, or create a new one?
If no default environment was found, present the user with choices:
<suggestedName> — use the name generated in 1bThe resource group will be rg-<envName>.
After resolving the environment name, check whether the selected environment already has
AZURE_EXISTING_AIPROJECT_RESOURCE_ID set:
$existingProject = azd env get-value AZURE_EXISTING_AIPROJECT_RESOURCE_ID --environment $envName 2>$null
If the value is non-empty, the environment is pre-configured to use an existing AI project.
Print the short-path steps overview and jump directly to Step 8 (azd up):
Up Skill — Steps Overview (environment:
<envName>, existing AI project)
- ✅ Choose environment name 2–7. ⏭️ Skipped (existing AI project detected)
- Run
azd up- Retrieve the app endpoint
- Health-check the app
- Report results
If the value is empty or not set, print the full-path steps overview and continue to Step 2:
Up Skill — Steps Overview (environment:
<envName>)
- ✅ Choose environment name
- Resolve subscription
- Check RBAC permissions
- Resolve region
- Check chat model quota
- Create the azd environment
- Set subscription, region, and model overrides
- Run
azd up- Retrieve the app endpoint
- Health-check the app
- Report results
Auto-detect the default Azure Subscription ID using this priority order (use the first one found):
AZURE_SUBSCRIPTION_IDazd config get defaults.subscription (may return empty)az account show --query id -o tsv (current Azure CLI login)Present the user with 2 choices:
az account show --query "{id:id, name:name}" -o json) as the default choiceIf no subscription was detected, skip choice 1 and ask the user to provide one directly.
Show the resolved subscription to the user for confirmation before proceeding.
Verify the user has sufficient permissions to create role assignments on the subscription, which is required for provisioning. The user needs Owner or User Access Administrator — either assigned directly or inherited through a group membership.
$principalId = az ad signed-in-user show --query id -o tsv
$subScope = "/subscriptions/<subscriptionId>"
$roles = az role assignment list --assignee $principalId --scope $subScope --query "[].roleDefinitionName" -o json | ConvertFrom-Json
Check if $roles contains Owner or User Access Administrator.
The user may hold the required role through a group membership. Query the user's group memberships and check whether any of those groups have the required roles on the subscription.
$groupIds = az ad signed-in-user get-member-of --query "[].id" -o json | ConvertFrom-Json
If $groupIds is non-empty, check role assignments for each group on the subscription:
$groupRoles = @()
foreach ($gid in $groupIds) {
$gr = az role assignment list --assignee $gid --scope $subScope --query "[].roleDefinitionName" -o json 2>$null | ConvertFrom-Json
if ($gr) { $groupRoles += $gr }
}
Check if $groupRoles contains Owner or User Access Administrator.
azd up will fail because the deployment creates Microsoft.Authorization/roleAssignmentsCheck environment variable AZURE_LOCATION first. If not set,
ask the user — must be one of: eastus, eastus2, swedencentral, westus, westus3.
Default to eastus if the user has no preference.
Show the resolved region to the user for confirmation before proceeding.
Before provisioning, verify the default chat model has sufficient quota in the selected region.
Default model: gpt-4o-mini | SKU: GlobalStandard | Required capacity: 80
$usage = az cognitiveservices usage list --location <region> --subscription <subscriptionId> -o json | ConvertFrom-Json
$modelList = az cognitiveservices model list --location <region> --subscription <subscriptionId> -o json | ConvertFrom-Json
Cache both $usage and $modelList for potential reuse.
$defaultUsageName = "OpenAI.GlobalStandard.gpt-4o-mini"
$entry = $usage | Where-Object { $_.name.value -eq $defaultUsageName }
If the entry exists, compute available = limit - currentValue.
available >= 80, the default model has enough quota — skip to Step 6.available < 80, quota is insufficient — continue to 5c.Report the finding to the user (e.g., "gpt-4o-mini has 40/80 quota available — insufficient").
From the quota usage list, find all GPT entries with Global or GlobalStandard SKUs
that have sufficient available quota:
$gptEntries = $usage | Where-Object {
$_.name.value -match '^OpenAI\.(Global|GlobalStandard)\.gpt-' -and
($_.limit - $_.currentValue) -ge 80
}
For each candidate, cross-reference with $modelList to confirm the model is actually
deployable (exists with format OpenAI and is not retired). Discard any candidate not
confirmed by the model list.
Use this preference order (higher is better):
gpt-4o-minigpt-4.1-minigpt-5-minigpt-4ogpt-4.1gpt-5Within the same model name, prefer GlobalStandard over Global.
Present the top candidate to the user with:
Global or GlobalStandard)Ask for confirmation before proceeding.
For the selected model, look up the version from the model list:
$match = $modelList | Where-Object {
$_.model.name -eq '<selectedModel>' -and
$_.model.format -eq 'OpenAI'
}
If multiple versions exist, prefer the newest Generally Available version. If only preview versions exist, warn the user before proceeding.
Store the resolved chat model name, SKU, and version for use in Step 7.
If no GPT model in Global or GlobalStandard has sufficient quota (≥ 80) in the
selected region, stop and report the issue. Suggest the user try a different region or
request a quota increase.
If the user chose an existing environment in Step 1c, skip this step — the environment already exists. Proceed directly to Step 7.
If the user chose a new environment name, create it:
azd env new $envName --no-prompt
If this fails, stop and report the error.
azd env set AZURE_SUBSCRIPTION_ID <subscriptionId> --environment $envName --no-prompt
azd env set AZURE_LOCATION <region> --environment $envName --no-prompt
Use the values collected in Steps 2 and 4.
If Step 5 determined an alternative chat model, apply the chat model overrides:
azd env set AZURE_AI_CHAT_MODEL_NAME "<selectedChatModel>" --environment $envName --no-prompt
azd env set AZURE_AI_CHAT_DEPLOYMENT_NAME "<selectedChatModel>" --environment $envName --no-prompt
azd env set AZURE_AI_CHAT_DEPLOYMENT_SKU "<selectedChatSku>" --environment $envName --no-prompt
azd env set AZURE_AI_CHAT_MODEL_VERSION "<selectedChatVersion>" --environment $envName --no-prompt
azd env set AZURE_AI_CHAT_MODEL_FORMAT "OpenAI" --environment $envName --no-prompt
azd env set AZURE_AI_CHAT_DEPLOYMENT_CAPACITY "80" --environment $envName --no-prompt
azd upThis provisions infrastructure and deploys the app. It typically takes 10–15 minutes.
Run with mode="async" so the user sees live streaming output:
azd up --environment $envName --no-prompt
After launching, poll with short delays — call read_powershell with a 15–20 second
delay on each turn, and show the user whatever new output appeared. Repeat in a loop
(one read_powershell per response turn) until the command completes. This gives the
user a near-real-time view of provisioning progress. Do NOT use 120-second delays.
azd up fails, report the error and offer to run azd down --environment $envName --force --purge --no-prompt (also mode="async") to clean up.azd up succeeds, proceed to the health check.After azd up succeeds, get the deployed app URL:
$serviceUri = azd env get-value SERVICE_API_URI --environment $envName
If that returns empty, fall back to reading .azure/<envName>/.env and parsing the SERVICE_API_URI line.
Try up to 5 times (15 seconds apart) to reach the app:
$healthy = $false
for ($i = 1; $i -le 5; $i++) {
try {
$resp = Invoke-WebRequest -Uri $serviceUri -UseBasicParsing -TimeoutSec 30 -ErrorAction Stop
if ($resp.StatusCode -ge 200 -and $resp.StatusCode -lt 400) {
$healthy = $true
Write-Host "Attempt $i - HTTP $($resp.StatusCode) - App is running!"
break
}
} catch {
Write-Host "Attempt $i - $($_.Exception.Message)"
}
if ($i -lt 5) { Start-Sleep -Seconds 15 }
}
Print a summary with:
| Field | Value |
|---|---|
| Subscription | <subscriptionId> |
| Environment | $envName |
| Resource Group | rg-$envName |
| Region | <region> |
| Chat Model | <chatModel> (<chatSku>) |
| App URL | $serviceUri |
| Status | ✅ PASS or ❌ FAIL |
azd up succeeded AND health check returned HTTP 2xx/3xx.azd up failed or the app did not respond after 5 retries.If the test failed, ask the user whether to tear down with:
azd down --environment $envName --force --purge --no-prompt
If the test passed, congratulate and remind them the environment is still running (costs apply) and offer to tear it down.