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
policyresourcesrequire 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 viaResourceContainers | 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_queryfirst — it confirms the syntax and property paths before you spend a call onexecute_query. If you need to adapt a query to a different resource type or field, draft it withgenerate_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.CostCenterwon't match acostcenterkey), 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
listOfAllowedSKUsandenforcementModefrom the relevant assignment. - Reply: "
Standard_E64s_v5is 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.