Skill v1.0.0
currentTrusted Publisher100/100version: "1.0.0" name: running-demo description: Run break/fix demo scenarios with browser verification. Use when asked to demo, break the app, or show the SRE Agent working.
Running the Demo
This skill drives the full demo using Playwright MCP for browser control. Execute each step — don't just describe them.
Setup
# AKS is a private cluster — kubectl from your local workstation won't work without VPN/jumpbox.# Use `Invoke-AksCommand` (wraps `az aks command invoke` for human-operator polling/diagnostics).# The SRE Agent uses the built-in RunKubectl* system tools; this helper is for human operators.. .\scripts\_aks-helpers.ps1$rg = (azd env get-value RESOURCE_GROUP)$aks = (azd env get-value AKS_CLUSTER_NAME)$pg = (az postgres flexible-server list -g $rg --query '[0].name' -o tsv)$r = Invoke-AksCommand -ResourceGroup $rg -ClusterName $aks `-Command "kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}'" -Quiet$ip = ($r.logs -replace '[^\d\.]','').Trim()$storeUrl = "http://$ip"$agentUrl = (azd env get-value AGENT_PORTAL_URL) # deep-links to this agent's blade — sign in if prompted
When observing or prompting the SRE Agent, use its built-in RunKubectlReadCommand and RunKubectlWriteCommand tools for Kubernetes.
Scenario 1: Database Outage
Step 1: Show healthy state
- Use Playwright MCP to navigate to
$storeUrl - Take a screenshot — show products loading, status bar says "ALL SYSTEMS OPERATIONAL"
- Navigate to
$storeUrl/api/health— show"status":"healthy","db_connected":true
Step 2: Break it
.\.github\skills\running-demo\scripts\break-sql.ps1
Wait 30 seconds for the app to notice.
Step 3: Show the break in the browser
- Navigate to
$storeUrl— should show "SERVICE DISRUPTION" overlay - Take a screenshot — this is the degraded UI the audience should see
- Navigate to
$storeUrl/api/health— show"status":"unhealthy","db_connected":false
Step 4: Watch the SRE Agent
- Navigate to
$agentUrl— the agent portal - Look for a new incident thread (
postgres-unreachablescheduled-query alert, routed to thezava-databaseresponse plan) - The agent should investigate and run
az postgres flexible-server start - Poll PostgreSQL state every 60s — let the agent do its thing, do NOT run the fix script:
``powershell az postgres flexible-server show -g $rg -n $pg --query state -o tsv ``
- Wait until state = "Ready" (typically 3-5 min)
- Both database scenarios share
postgres-unreachable, with response-plan merge
disabled. Wait for Azure Monitor's monitor condition to become Resolved before Scenario 2. Alert state (New, Acknowledged, Closed) is separate: closing an alert does not reset a still-fired condition. The agent should close only its owned alert after recovery when its tools permit that operation, or report closure blocked and let auto-mitigation clear the condition. Diagnose each fault from ARM state (Stopped versus Ready but unreachable), not the error text alone.
Step 5: Show recovery
- Wait 15s after PG is Ready for pods to reconnect
- Navigate to
$storeUrl— products should load again - Take a screenshot — show recovery
Do not run fix-sql.ps1 as part of the demo. It exists for post-demo cleanup or developer iteration only — running it during the demo invalidates the result. If the agent doesn't fix the incident, that is the result; show it and move on.
Scenario 2: Network Partition
Step 1: Show healthy state
- Navigate to
$storeUrl— confirm healthy - Take screenshot
Step 2: Break it
Heads-up if you just ran Scenario 1: both DB scenarios sharepostgres-unreachable. Wait formonitorCondition == Resolvedbefore injectingthe network fault. Closing the previous alert alone does not reset its condition,and a still-fired condition can prevent a fresh investigation.
.\.github\skills\running-demo\scripts\break-network.ps1
Wait 30 seconds.
Step 3: Show the break
- Navigate to
$storeUrl— should show "SERVICE DISRUPTION" with ETIMEDOUT errors - Take screenshot — note: error says "timeout" not "connection refused" (server is up but unreachable)
Step 4: Watch the agent
- Check SRE Agent portal for investigation
- Agent needs to find the K8s NetworkPolicy with
RunKubectlReadCommandusingkubectl get networkpolicy -n zava-demo -o yaml, then remove it withRunKubectlWriteCommandusingkubectl delete networkpolicy database-tier-isolation -n zava-demo- this is harder than Scenario 1 and may take longer - Poll for NetworkPolicy removal (the AKS API server is private — go through ARM):
``powershell Invoke-AksCommand -ResourceGroup $rg -ClusterName $aks -Command "kubectl get networkpolicy -n zava-demo" ``
- Do not run
fix-network.ps1as part of the demo — same rule as Scenario 1: the script is post-demo cleanup, not an agent-failure fallback.
Step 5: Show recovery
- Navigate to
$storeUrl— products load - Take screenshot
Scenario 3: Missing Index
Step 1: Show healthy state
- Navigate to
$storeUrl— confirm healthy
Step 2: Break it
# Drops idx_products_category_name AND idx_products_category so neither existing# category index can mask the missing-index scenario. Also rolls the# api deployment to clear PG plan cache + restart the OTel exporter, then# verifies AppRequests telemetry is flowing before launching the load Job.# Variants are seeded automatically on first deploy (50 originals + 120,000# size/color/edition variants from seed.js), so this is a single command..\.github\skills\running-demo\scripts\break-db-perf.ps1
If the telemetry query fails, resolve the query or access error before retrying; failure is not evidence of zero traffic. If the query succeeds with no recent AppRequests, verify application instrumentation and ingestion. Use -SkipTelemetryCheck only when an empty workspace is intentional.
Step 3: Show degraded performance
- Navigate to
$storeUrl/api/diagnostics - Confirm both category indexes are absent and
seq_scanincreases.
index_usage_pct is cumulative and need not fall to zero for this run.
- Take screenshot
- (
break-db-perf.ps1already launched a 15-min in-cluster Kubernetes Job (zava-cat-loadin thezava-demonamespace) that hammers/api/products/category/<X>over the cluster-internal Service DNS. This pushes real traffic past the alert's 30ms threshold — the 1Hz__probeis excluded by the alert KQL. The Job auto-cleans 60s after completion viattlSecondsAfterFinished;fix-db-perf.ps1also deletes it explicitly. Run with-NoLoadto skip.)
Step 4: Watch agent
- Monitor SRE Agent portal - it should detect slow response times via App Insights, inspect the query with
QueryZavaPostgres, and run the bounded category-index repair throughRepairZavaPostgresIndexes. - Do not run
fix-db-perf.ps1as part of the demo — same rule as the other scenarios: the script is post-demo cleanup, not an agent-failure fallback.
Step 5: Show recovery
- Verify the index has been recreated by reading the diagnostics endpoint
(cleaner than trying to round-trip a quoted SQL literal through PowerShell → az aks command invoke → kubectl exec → node argv — embedded quotes don't survive that chain reliably on Windows): ``powershell $diag = Invoke-RestMethod "$storeUrl/api/diagnostics" $diag.indexes | Where-Object { $_.index_name -eq 'idx_products_category_name' } ($diag.scan_stats | Where-Object { $_.table_name -eq 'products' }).index_usage_pct `` Confirm the affected category query returns to baseline under comparable load. Recheck its full query shape, including ordering and pagination. A rising index scan count or the load Job ending does not by itself prove performance recovery.
- Navigate to
$storeUrl— fast loading
Scenario 4: Bad Deploy / Rollback
Step 1: Show healthy state
- Navigate to
$storeUrl— confirm healthy, products load - Take screenshot
Step 2: Break it
# Ships a bad config rollout: kubectl set env deployment/zava-api FAULT_INJECT=500.# This mutates the pod template -> a NEW rollout revision (the deployment signal),# and GET /api/products starts returning HTTP 500. The liveness AND readiness probes# both hit /livez (and /api/health stays green too), so pods stay Running and only the app route regresses.# The 1Hz in-cluster self-probe hits /api/products, so the 5xx signal builds with no# external load. Verifies AppRequests telemetry is flowing first (-SkipTelemetryCheck# to bypass on a brand-new deploy)..\.github\skills\running-demo\scripts\break-bad-deploy.ps1
A failed telemetry query stops the script before fault injection. Resolve query errors separately from a successful query showing no recent requests; do not bypass the check merely because a query failed.
Step 3: Show the break
- Navigate to
$storeUrl/api/products— returns HTTP 500 - Navigate to
$storeUrl/api/health— still"status":"healthy","db_connected":true(the deploy regressed the app route, not the DB). Take a screenshot to make the point: platform-healthy, app-broken.
Step 4: Watch the agent
- Check the SRE Agent portal for a new incident from
Zava-http-5xx-errors - The agent should rule out the DB/network/slow-query conditions, then correlate the 5xx spike with the recent rollout and roll back:
``powershell Invoke-AksCommand -ResourceGroup $rg -ClusterName $aks -Command "kubectl rollout history deployment/zava-api -n zava-demo" ``
- Remediation is
kubectl rollout undo deployment/zava-api -n zava-demo(rollback to the previous good revision) - Do not run
fix-bad-deploy.ps1as part of the demo — same rule as the other scenarios: the script is post-demo cleanup, not an agent-failure fallback.
Step 5: Show recovery
- Navigate to
$storeUrl/api/products— returns 200 again - Navigate to
$storeUrl— products load; take screenshot
Scenario 5: Compound Independent Faults
This proof-of-concept scenario overlaps Scenario 3 and Scenario 4 by 90 seconds. It demonstrates how to compare two nearby alerts before deciding whether they share a cause.
Step 1: Confirm healthy state
- Navigate to
$storeUrland$storeUrl/api/health - Confirm products load and the database is connected
Step 2: Break both paths
.\.github\skills\running-demo\scripts\break-compound.ps1
The script drops both category indexes, starts the sustained category load, waits 90 seconds, then deploys FAULT_INJECT=500.
Step 3: Verify the overlap
$storeUrl/api/productsreturns HTTP 500 while/api/healthremains healthy.- Query
/api/diagnostics; both category indexes are absent and product scans are sequential. - Confirm the
zava-cat-loadJob is active throughInvoke-AksCommand. - Expect both
Zava-products-query-slowandZava-http-5xx-errorswithin 5-10 minutes.
Step 4: Review the investigation
Confirm that the investigation compares the available evidence:
- 5xx failures are app-local (
localhost:3001) and correlate with the rollout. - PostgreSQL CPU/latency rises, but its slow queries succeed and create no failed PG dependencies.
Zava-db-cpu-saturationis present but disabled.
Alert timestamps identify temporal overlap, not causation. Use request, dependency, deployment, and PostgreSQL telemetry to establish whether a mechanism is shared.
This scenario is intentionally narrow. It demonstrates one correlation approach and does not represent every incident pattern or guarantee a particular model outcome.
Step 5: Cleanup
Let the SRE Agent remediate during a demo. For post-demo cleanup or test teardown:
.\.github\skills\running-demo\scripts\fix-compound.ps1
Verify /api/products returns 200, both indexes exist, and the load Job is gone.
Chat demo: interrogate the hub firewall (network device)
No break needed — this shows the agent treating the hub Azure Firewall as a queryable "network device" in the hub-and-spoke topology.
- Open the agent chat (
$agentUrl) and ask:
> "Inspect the hub Azure Firewall: summarize its egress allow-list (rule collections), and query the AZFW* Log Analytics tables for anything denied for the agent subnet in the last hour."
- Expect the agent to read the firewall policy over ARM (
az network firewall policy ..., covered by its Reader role) and run KQL againstAZFWApplicationRule/AZFWNetworkRule. - Optional follow-up — "Is the firewall in the path between the app and PostgreSQL?" The correct answer is no: it gates only the agent's own egress; the app↔PG path is governed by the platform-spoke NSG and the in-cluster Kubernetes NetworkPolicy. This confirms the agent has the topology boundary right.
This is a read/diagnostic demonstration, not a break/fix — the firewall gates the agent's own egress, so breaking it would disable the agent itself.
Watching the SRE Agent
In a separate shell, view investigation progress through the data-plane API:
.\scripts\watch-agent.ps1 # list all threads.\scripts\watch-agent.ps1 -Show -Title slow # details for latest matching incident.\scripts\watch-agent.ps1 -Tail -Title slow # poll for new messages until Resolved/Closed/Mitigated
Investigation time varies by scenario and environment. Use -Tail to follow progress before deciding whether manual cleanup is needed.
Playwright MCP Usage
Use these Playwright MCP tools throughout:
browser_navigate— go to URLsbrowser_snapshot— see page content (use to verify text like "SERVICE DISRUPTION" or "healthy")browser_screenshot— capture visual statebrowser_click— interact with elements if needed
If Playwright MCP is not available, fall back to port-forward via az aks command invoke + curl:
# Test the API directly via the public ingress (still public — only the cluster API server is private)Invoke-RestMethod "$storeUrl/api/health"# Or exec inside an api pod for internal checks:Invoke-AksCommand -ResourceGroup $rg -ClusterName $aks -Command "kubectl exec -n zava-demo deploy/zava-api -- wget -qO- http://localhost:3001/api/health"