| name | cost-guardrails |
| description | Check Azure Policy SKU/region restrictions, tag compliance, and budget coverage via Azure Resource Graph. WHEN: "what SKUs are allowed", "can I deploy this", "check policy", "allowed VMs", "will this be denied", "tag compliance", "budget coverage", "governance health". INVOKES: generate_query, validate_query, execute_query, list_budgets |
| license | MIT |
| metadata | {"version":"1.0.0"} |
Cost Governance & Guardrails
Check Azure Policy cost guardrails (SKU/region restrictions), cost-allocation tag compliance, and budget coverage across a scope. All policy lookups go through Azure Resource Graph (policyresources table).
ARG queries against policyresources require read access at the scope. Empty results may mean the caller lacks visibility into assigned policies — not that none exist.
All ARG queries below take subscription-id placeholders (<sub-id-1>, <sub-id-2>) — replace with the target subscriptions. To target a management group, first resolve member subs via ResourceContainers | where type == 'microsoft.resources/subscriptions' | where properties.managementGroupAncestorsChain has '<mg-name>' | project subscriptionId.
Run every ARG query through the generate → validate → execute workflow. The queries below are ready to run, but pass each one to validate_query first — it confirms the syntax and property paths before you spend a call on execute_query. If you need to adapt a query to a different resource type or field, draft it with generate_query (a natural-language prompt), then validate and execute.
Step 1: List Policy Assignments
Call execute_query to enumerate policy assignments and read their parameters. Don't filter by subscriptionId — MG- and tenant-level assignments cascade down to subscriptions, and filtering would drop them.
policyresources
| where type =~ 'microsoft.authorization/policyassignments'
| project assignmentName = name,
displayName = tostring(properties.displayName),
scope = tostring(properties.scope),
enforcementMode = tostring(properties.enforcementMode),
parameters = properties.parameters
| limit 100
The chosen guardrail values live in parameters (e.g. listOfAllowedSKUs, listOfAllowedLocations). The policy definition only holds the schema and defaults, so there's no need to join it.
Step 2: Filter to SKU / Region Restrictions
Re-filter the Step 1 result (or re-run with this filter appended) for the policies that restrict SKUs or regions:
... | where displayName has 'sku' or displayName has 'location'
or isnotempty(parameters.listOfAllowedSKUs)
or isnotempty(parameters.listOfAllowedLocations)
Read the allowed values straight from parameters:
{ "listOfAllowedSKUs": { "value": ["Standard_B2s", ...] } }
{ "listOfAllowedLocations": { "value": ["eastus", "westeurope"] } }
Also check enforcementMode before reporting a restriction as binding: Default means the assignment is enforced (a Deny policy blocks non-compliant deployments); DoNotEnforce means it's evaluated for compliance only and does not block deployments.
If nothing returns: "No SKU or region restrictions detected on this scope — all SKUs and regions are allowed."
Step 3: Tag Compliance
Check coverage on standard cost-allocation tags via execute_query with this Azure Resource Graph query. Default to CostCenter / Owner / Environment; adjust to the user's actual standard if they have one.
Resources
| where subscriptionId in ('<sub-id-1>', '<sub-id-2>')
| where isnull(tags.CostCenter) or isnull(tags.Owner) or isnull(tags.Environment)
| summarize missingRequiredTag=count() by type
| order by missingRequiredTag desc
| limit 10
Tag-key lookups in Resource Graph are case-sensitive (tags.CostCenter won't match a costcenter key), so use the exact casing of the organization's tag names to avoid over-reporting.
Step 4: Budget Coverage
Call list_budgets on the scope. List which subscriptions / resource groups have a budget and which don't. For setting or reviewing budgets, point to the budget-setup and budget-health skills.
Presentation
- Allowed SKUs (if the user asked about a specific resource type) — list the permitted SKUs from Step 2. For pricing on those SKUs, point to the pricing-estimate skill.
- Tag compliance — Top resource types missing the standard cost-allocation tags.
- Budget coverage — Scopes covered vs uncovered.
Defaults shown (standard cost-allocation tags) are a starting point — adjust to your organization's standards.
Example
User: "Can I deploy a Standard_E64s_v5 VM?"
- Run Steps 1–2 → parse
listOfAllowedSKUs and enforcementMode from the relevant assignment.
- Reply: "
Standard_E64s_v5 is not in the allowed list (Standard_B2s, Standard_D2s_v5, Standard_D4s_v5). The assignment is enforced (enforcementMode = Default), so Azure Policy would deny the deployment. For pricing on the allowed SKUs, run the pricing-estimate skill."
If enforcementMode = DoNotEnforce, say the deployment would be flagged non-compliant but not blocked.