| name | cost-optimization |
| description | Surface right-sizing recommendations (Azure Advisor) filtered by SKU policy and flagged against existing commitments, plus quick-win cleanup candidates. WHEN: "optimize costs", "reduce spending", "right-size", "savings opportunities", "save money", "oversized", "wasted resources". INVOKES: query_costs, generate_query, validate_query, execute_query, get_benefit_recommendations, list_benefit_utilization |
| license | MIT |
| metadata | {"version":"1.0.0"} |
Cost Optimization
Identify what to right-size, what to clean up, and what new commitments to consider. Right-sizing recommendations are filtered against Azure Policy SKU restrictions and flagged for overlap with existing reservations / savings plans, so recommendations don't fight existing commitments.
This skill uses cost data, Azure Advisor recommendations, and ARG inventory/configuration only — apply utilization-based recommendations with normal change-control review.
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: Top Cost Contributors
Call query_costs with timeframe=MonthToDate, groupBy=ServiceName,ResourceGroupName. Identify the top 5–10 cost drivers — these are where optimization effort pays off.
Multi-currency caveat: at management-group or billing-account scope, the result may contain multiple Currency values. Rank contributors per currency — don't combine USD and GBP into one number.
Blob storage shortcut: if Storage (ServiceName = "Storage") is among the top contributors, recommend enabling smart tier on the account(s) — it automatically moves blobs between access tiers based on usage to reduce cost. Point the user to Optimize Azure Blob Storage costs with smart tier. Surface this as a recommendation and link only — don't estimate the savings.
Step 2: Advisor Cost Recommendations (via ARG)
Call execute_query to pull Azure Advisor cost-category recommendations:
advisorresources
| where type =~ 'microsoft.advisor/recommendations'
| where subscriptionId in ('<sub-id-1>', '<sub-id-2>')
| where tostring(properties.category) == 'Cost'
| project resourceId=tostring(properties.resourceMetadata.resourceId),
shortDescription=tostring(properties.shortDescription.problem),
extendedProperties=properties.extendedProperties
| limit 100
extendedProperties content varies widely by recommendationSubCategory and maturityLevel (many cost recs are Preview):
- Reservation / savings-plan purchases carry the dollar figures —
annualSavingsAmount (annual), savingsAmount (monthly, ≈ annual ÷ 12), savingsCurrency — plus sku / displaySKU, term, qty, region. Use these directly; don't recompute.
- Usage-optimization, cleanup, and monitoring recommendations (e.g., autoscaler tuning, unattached-disk review) often carry only descriptive fields (region, resource SKU/size, product name) and no savings amount. Don't invent a number for these — surface them qualitatively.
Don't conflate savingsAmount (monthly) with annualSavingsAmount (annual).
Handle the unquantified ones. Since many cost recs return no dollar figure, don't silently drop them. Split the output into Quantified (rows with a non-null savings amount, sorted descending) and Non-quantified (rows without one, surfaced as a short list with the recommendation text and the impacted resource). Where savings amounts exist, watch for currency variation — extendedProperties.savingsCurrency may differ across rows; group or note it before summing.
Advisor needs ~7+ days of utilization data; new or recently-changed resources won't have recommendations yet.
Step 3: SKU Policy Filter
Check Azure Policy for SKU restrictions on the scope (see the cost-guardrails skill for the canonical query against policyresources). This filter applies to recommendations that move a resource to a different SKU (right-size). For each such recommendation, mark its target SKU as:
- ✅ Allowed — proceed
- 🚫 Blocked by policy — note the next allowed alternative if you can identify one from the policy parameters
Reservation-purchase recommendations propose committing to the SKU already in use, so this SKU-policy gate doesn't apply to them.
Step 4: Commitment Overlap Check
For each right-sizing recommendation, qualitatively check whether the current SKU might be covered by a reservation or savings plan. If a billing scope is available, call list_benefit_utilization to see whether active commitments exist and how heavily they're used. This tool reports utilization per commitment but not which SKUs each one covers, so treat it as a signal — not proof — that downsizing could affect a commitment:
- 🟡 If active commitments exist (especially highly-utilized ones), flag the recommendation. Downsizing can strand a commitment unless another workload absorbs the freed capacity, the reservation is exchanged, or the user waits for it to expire.
- Hand off to the commitment-analysis skill for the SKU-level coverage view and remediation options (exchange, refund, switch to Savings Plan).
This is a qualitative flag, not a dollar reconciliation. A precise apples-to-apples comparison requires per-SKU retail vs negotiated pricing and is out of scope here.
Negotiated pricing can also invert a recommendation (a discounted current SKU may be cheaper than the target SKU at retail). For that comparison, hand off to the pricing-estimate skill, which can pull the org's pricesheet.
Step 5: Cleanup Candidates
Call execute_query to surface common quick wins (example for unattached managed disks — adapt for unused public IPs, snapshots, etc.):
Resources
| where type =~ 'Microsoft.Compute/disks'
| where subscriptionId in ('<sub-id-1>', '<sub-id-2>')
| where properties.diskState == 'Unattached'
| project name, resourceGroup, sku=sku.name,
sizeGB=properties.diskSizeGB, tags,
createdTime=properties.timeCreated
| limit 20
Use properties.diskState == 'Unattached' — not isnull(managedBy). On a detached disk managedBy is an empty string (""), not null, so an isnull/isempty check silently misses genuinely unattached disks. diskState is the signal Azure Advisor itself uses.
For each candidate, surface the resource name, RG, owner tag (tags.Owner / tags.CostCenter / tags.Team if present), and estimated cost.
⚠️ These resources appear unused but may be intentionally parked for DR, cutover, compliance, or future use. Always confirm with the owner before deleting. Flag any without an owner tag as "needs owner assignment first."
Step 6: New Commitment Recommendations
Call get_benefit_recommendations. Present the top 3–5 with the API-reported savings figures. Frame these as additions to the current portfolio; if you're about to downsize a SKU, don't recommend a new reservation for it. Advisor's Cost category (Step 2) can also surface reservation purchases — de-duplicate so the same commitment isn't counted in both the right-sizing and new-commitment sections.
Presentation
Group recommendations by category, with the highest-impact items first.
- Right-sizing — Table: Resource, current SKU → target SKU, annual savings (from Advisor's
annualSavingsAmount), status (✅ safe / 🚫 policy-blocked / 🟡 commitment overlap). Route any reservation-purchase recommendations from Step 2 to New commitments below, not here.
- Cleanup candidates — Resource, RG, owner tag, estimated monthly cost. Repeat the "confirm with owner before deleting" caveat.
- New commitments — Top recommendations from
get_benefit_recommendations with API-reported savings.
- Storage tiering (only if Storage is a top contributor) — Recommend enabling blob smart tier, with the docs link. No savings estimate.
- Caveats — Single closing line: utilization is inferred from Advisor signals only; re-check for commitment / negotiated-price overlap if you have an EA/MCA agreement.