Map discovered Azure resources into a dependency graph and Mermaid diagram, then propose an entity hierarchy. WHEN: 'map architecture', 'draw resource graph', 'show resource dependencies', 'propose health model hierarchy'. PREREQUISITE: healthmodel-discovery must have run first — this skill refuses to start without `.healthmodel/01-discovery.json` and `.healthmodel/00-brief.md`. DO NOT USE FOR: deploying or designing signals (use healthmodel-design / healthmodel-deploy), generic architecture diagrams unrelated to health models.
How this skill is triggered — by the user, by Claude, or both
Slash command
/azure-healthmodel-skills:healthmodel-architectureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Transform discovered resources into an architecture graph with dependency edges, classify resources by impact, and propose an entity hierarchy. Uses only `az resource list`, `az monitor`, and `jq`.
Transform discovered resources into an architecture graph with dependency edges, classify resources by impact, and propose an entity hierarchy. Uses only az resource list, az monitor, and jq.
.healthmodel/01-discovery.json, .healthmodel/resources.json, and .healthmodel/00-brief.md must exist and contain real data. Check that 01-discovery.json has a subscription field, resources.json has at least one resource, and 00-brief.md has user-filled content (not just the template placeholders). If any file is missing, empty, or still contains only placeholder values, stop immediately and tell the user: "Discovery has not been completed. Load healthmodel-discovery first." Do NOT attempt to create or fill these files yourself.<br/> (never \n) and dark-mode-safe class colors.# Files must exist AND contain real data
test -f .healthmodel/01-discovery.json && test -f .healthmodel/resources.json && test -f .healthmodel/00-brief.md \
|| { echo "STOP: Discovery files missing — run healthmodel-discovery first"; exit 1; }
# discovery.json must have a real subscription ID (UUID format)
jq -e '.subscription | test("^[0-9a-f]{8}-")' .healthmodel/01-discovery.json >/dev/null 2>&1 \
|| { echo "STOP: 01-discovery.json has no valid subscription — run healthmodel-discovery"; exit 1; }
# resources.json must have actual Azure resource IDs (not placeholders)
jq -e '[.[] | select(.id | test("^/subscriptions/[0-9a-f]{8}-"))] | length > 0' .healthmodel/resources.json >/dev/null 2>&1 \
|| { echo "STOP: resources.json has no real Azure resources — run healthmodel-discovery export against a live subscription"; exit 1; }
# brief §1 Azure Scope must have a real subscription ID filled in
grep -qE '[0-9a-f]{8}-[0-9a-f]{4}-' .healthmodel/00-brief.md 2>/dev/null \
|| { echo "STOP: 00-brief.md has no Azure subscription — user must fill in §1 Azure Scope"; exit 1; }
command -v jq >/dev/null
Start from all discovered resources in .healthmodel/resources.json — do not filter by expected types. Every resource in the file is a candidate for the graph.
# List all distinct resource types and counts
jq 'group_by(.type) | map({type: .[0].type, count: length}) | sort_by(-.count)' \
.healthmodel/resources.json
# For any resource type you don't immediately recognize, research it:
# - What does this service do?
# - Is it on the request path, a background service, or infrastructure?
# - What kind of health signals would matter for it?
For each resource, determine its role in the architecture. Use .healthmodel/00-brief.md (especially §2 Critical User Journeys and §4 Top Concerns) as the primary guide. When the brief doesn't cover a resource, research the resource type and ask the user.
Produce edges {from, to, kind} where kind ∈ serves|stores|authenticates|monitors|calls|feeds.
Relationship inference strategies (use all that apply):
tags.environment, tags.application, tags.stamp reveal groupingsDo not assume a fixed topology. The architecture could be anything: microservices, monolith, event-driven, AI pipeline, batch processing, IoT, or a combination.
Read .healthmodel/00-brief.md before classifying:
Standard impact (failure turns parent red); concerns ranked lower map to Limited. Anything not mentioned and not on the request path defaults to Limited or Suppressed.Depends on column instead of guessing from resource types.If the brief is not filled in or sections are blank, fall back to the defaults listed in the brief's §9.
Impact is determined by the resource's role in the user's architecture, not by its Azure type:
| Principle | Impact | Meaning |
|---|---|---|
| On the critical request path — user request fails if this is down | Standard | Failure turns parent red |
| Supports the request path but has fallback/degraded mode | Limited | Visible degradation, doesn't escalate |
| Background/async processing — users don't notice immediately | Limited | Visible, doesn't escalate |
| Telemetry, monitoring, management infrastructure | Suppressed | Informational |
Impact is set on the parent grouping entity, not on its children. When a group of entities is
LimitedorSuppressed, set that impact on the parent entity that groups them. All children within the group useStandard— so failures are visible within the group, but the parent's impact level controls whether the group's health propagates further up the tree. SettingSuppressedon children is redundant and loses the ability to distinguish between siblings within the group.
Any resource type can be
Standard— an Azure OpenAI service powering a chatbot, a PostgreSQL database holding user sessions, a Storage account serving static assets. Don't assume impact from the resource type alone. The brief and the user's architecture determine impact.
Critical path = longest directed path from any public ingress to a stateful node — unless §2 of the brief specifies user journeys, in which case the critical path follows the journeys.
Build the diagram from the actual discovered resources and inferred relationships — not from a template. Save to .healthmodel/02-architecture.md:
graph LR
classDef critical fill:#1a5276,stroke:#2980b9,color:#fff
classDef limited fill:#1c2833,stroke:#7f8c8d,color:#ccc
classDef suppressed fill:#1c2833,stroke:#566573,color:#888
%% Example — replace with actual discovered resources:
INGRESS[Ingress<br/>resource-name]:::critical --> COMPUTE[Compute<br/>resource-name]:::critical
COMPUTE --> DATA[Data Store<br/>resource-name]:::critical
COMPUTE -.-> SIDE[Side Dependency<br/>resource-name]:::limited
COMPUTE -.-> MON[Monitoring<br/>resource-name]:::suppressed
Use the actual resource names from resources.json. The diagram should reflect the real topology — add or remove nodes and edges as the architecture demands.
Also include a resource inventory table and an explicit critical-path call-out.
Design a hierarchy that reflects the actual architecture, not a predefined template. The hierarchy should group resources by their role in the system and the golden signals that matter for each group.
Guiding principles:
hm-myapp). Top-level groups connect directly to the model root.Limited or Suppressed group use Standard impact (see Step 2).Example hierarchies — these are illustrations, not templates. "Root" below means the implicit model root entity (e.g., hm-myapp), NOT a custom e-root entity. Your architecture will likely differ:
Microservices with multi-stamp:
hm-myapp (implicit root — Standard)
├── Failures (Standard) ← children use Standard
├── Latency (Standard)
├── Resource Pressure (Standard)
└── Side groups (as needed)
PaaS web app:
hm-myapp (implicit root — Standard)
├── Frontend (Standard)
├── Database (Standard)
├── Ingress (Standard)
└── Telemetry (Suppressed) ← parent is Suppressed
├── App Insights (Standard) ← children are Standard
└── Log Analytics (Standard)
Event-driven processing:
hm-myapp (implicit root — Standard)
├── Producers (Standard)
├── Message Bus (Standard)
└── Consumers (Standard)
AI-powered application (e.g., RAG chatbot):
hm-myapp (implicit root — Standard)
├── RAG Pipeline (Standard)
│ ├── Backend (Standard)
│ ├── AI Inference (Standard)
│ └── Knowledge Search (Standard)
├── Observability (Suppressed) ← doesn't escalate to root
│ ├── App Telemetry (Standard) ← Standard within group
│ └── Log Analytics (Standard)
└── Platform (Limited) ← visible but won't turn root red
└── Container Platform (Standard)
Batch/ETL pipeline:
hm-myapp (implicit root — Standard)
├── Ingestion (Standard)
├── Processing (Standard)
├── Output (Standard)
└── Orchestration (Standard)
These are starting points. Combine, modify, or ignore them entirely based on what resources.json and the brief tell you. If the architecture doesn't fit any pattern, design the hierarchy from scratch — the user confirms in Step 6.
Save the graph and diagram files now (same format as final output — see below). This ensures the design phase can proceed even if the session is interrupted.
Ask:
If the user requests changes, update the files and re-save before handing off.
.healthmodel/02-graph.json:
{
"nodes": [
{"id": "<resource-id>", "type": "Microsoft.ContainerService/managedClusters", "role": "critical", "stamp": "sc-001"}
],
"edges": [
{"from": "<fd-id>", "to": "<aks-id>", "kind": "serves"}
],
"entityHierarchy": {
"root": "hm-myapp",
"children": [
{"name": "RAG Pipeline", "impact": "Standard", "children": [
{"name": "Backend", "impact": "Standard", "children": []},
{"name": "AI Inference", "impact": "Standard", "children": []}
]},
{"name": "Observability", "impact": "Suppressed", "children": [
{"name": "App Telemetry", "impact": "Standard", "children": []},
{"name": "Log Analytics", "impact": "Standard", "children": []}
]}
]
}
}
Note:
entityHierarchy.rootis the health model name — the implicit root entity created by ARM. Do NOT create a custome-rootentity. Children underSuppressed/Limitedparents useStandardimpact.
Announce: "Architecture mapped. .healthmodel/02-graph.json and .healthmodel/02-architecture.md are written. Load healthmodel-design to continue." Then stop — do not auto-proceed.
| Error | Cause | Fix |
|---|---|---|
01-discovery.json missing | Discovery phase skipped | Run healthmodel-discovery first |
| No edges produced | Resources isolated / no naming convention | Ask user to identify relationships manually |
| Mermaid renders blank in dark mode | Default colors invisible | Use the classDef colors shown above |
| Cyclic dependency detected | DAG instead of tree | Break the cycle by promoting one node to root or side group |
npx claudepluginhub abossard/azure-healthmodel-skills --plugin azure-healthmodel-skillsCreates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.