# Budget Health

> Current spend vs limits, end-of-month forecast, and active alerts. WHEN: "budget status", "am I over budget", "budget health", "will I exceed budget", "budget forecast". INVOKES: list_budgets, forecast_costs, query_costs, list_alerts

- Skill: `azure-samples/budget-health` (Agent Skill)
- Install (CLI): `npx skillmds@latest add azure-samples/budget-health`
- Raw SKILL.md: https://api.skillmd.com/api/skills/azure-samples/budget-health/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Finance & Business
- License: MIT
- Author: Azure-Samples (https://skillmd.com/u/azure-samples)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/azure-samples/budget-health

---


# Budget Health Check

Quick answer to the three questions users actually ask about a budget: *Am I over? Will I overshoot? Is anything firing?*

## Steps

1. **List Budgets** — Call `list_budgets` with the user's scope.
   - If no budgets exist on the scope, skip to the *No budgets found* handoff below.
   - If the call returns an access-denied error, the user lacks Cost Management read access on this scope — surface that distinctly rather than reporting it as "no budgets found."

2. **End-of-Month Forecast** — Call `forecast_costs` with the same scope. It returns one row per day, each tagged `CostStatus` `Actual` or `Forecast`, and the same date can appear as both. For the month-end projection, take one value per date — the `Actual` if present, otherwise the `Forecast` — and sum `PreTaxCost`. Compare that to the budget amount.
   - **No Forecast rows?** If the response has only `Actual` rows, a projection isn't available for this scope — report month-to-date actual and say a forecast couldn't be produced; don't present partial actuals as a month-end projection. This happens on multi-currency scopes (below) and where there's too little history to project.
   - **Multi-currency caveat:** the Cost Management [Forecast API](https://learn.microsoft.com/en-us/rest/api/cost-management/forecast/usage) doesn't return a forecast for scopes that span multiple currencies — a management group or billing account can mix, e.g., USD and GBP, in which case the response comes back as `Actual`-only rows per currency. Re-scope to a single-currency subscription to get a forecast, and never sum across currencies.

3. **Current Month Spend** — Call `query_costs` with timeframe=MonthToDate, groupBy=ServiceName, granularity=None for the spend breakdown by service. If it returns no rows (early in the billing cycle, before current-month data is available), say so rather than implying zero spend — optionally repeat with timeframe=TheLastMonth for recent context.
   - **Multi-currency caveat:** at management-group or billing-account scope, the result may contain multiple `Currency` values. Group by Currency before summing or comparing — don't combine USD and GBP into one total.
   - **Source-of-truth note:** for the budget % use `list_budgets`' `currentSpend.amount` (this is what Azure evaluates Actual-cost budget alerts against; Forecasted alerts evaluate against `forecastSpend`). Use the `query_costs` MTD result only for the service-level drill-down.

4. **Active Alerts** — Call `list_alerts` to surface triggered budget or anomaly alerts. Each alert carries a `periodStartDate` and stays in `Active` status until dismissed, so the list can include alerts from earlier months. Check `periodStartDate`: present only current-period alerts as firing now, and label older ones as prior-period history.

## Presentation

For each budget, show:

- **Budget** — Name, amount, time grain, current spend vs limit (amount and %, with currency code — e.g. `1,200 / 2,000 USD (60%)`)
- **Status** — 🟢 On Track (<80%) | 🟡 Warning (80–95%) | 🔴 Over/Critical (>95%)
- **Forecast** — Projected end-of-month spend; will it exceed the limit? By how much?
- **Active Alerts** — Current-period triggered budget or anomaly alerts (older periods noted separately as history)

Then, briefly: top 3–5 services by MTD spend (from Step 3) so the user can see what's driving the number.

## Handoffs

**If forecast > budget limit**, or if any anomaly alert is firing:

> ⚠️ Projected to exceed budget by $X (Y%). Want me to investigate the drivers?
>
> I can use the **cost-investigation** skill to find what's pushing spend up.

If the user says yes, hand off to **cost-investigation** with the same scope.

**No budgets found on the scope:**

> No budgets are configured on this scope. Without budgets, cost overruns go unnoticed until the invoice arrives.
>
> Want help setting them up? I can use the **budget-setup** skill to recommend amounts based on your spend baseline and create tiered alerts.

If the user says yes, hand off to **budget-setup** with the same scope.

