---
name: azure-daily-cost-report
description: "Every morning: yesterday's Azure cost against the 7-day average, with the top services and resource groups and the one that moved. Use when the user asks for this, or when it runs on a schedule."
---

# Azure daily cost report

Every morning: yesterday's Azure cost against the 7-day average, with the top services and resource groups and the one that moved.

Cost analysis in the Azure portal is thorough, and that is the problem: by the time you have picked the scope, the date range and the grouping, the meeting has moved on. Most teams only look when the monthly invoice is higher than expected, three weeks after the change that caused it.

The agent calls the Cost Management Query API once a morning for the last eight days, grouped by service and then by resource group, and compares yesterday with the week before it. A database tier someone bumped for a load test shows up the next day by name, not at month end.

## Two ways to get the data

Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.

## Route A: API or MCP server

### What you need

- The Cost Management Reader role (or Reader) on the subscription or billing scope, used through `az login`, a service principal, or a managed identity.
- Calls go through `az rest` or any HTTP client with a token for `https://management.azure.com/`.

If something is missing, say what and stop; do not invent numbers.

### Steps

1. **Fix the scope**: Use a subscription (`/subscriptions/{subscriptionId}`) for one environment, or a billing account or management group to cover several. Costs are in the billing currency of that scope.
2. **Query daily cost by service** (Azure): `POST https://management.azure.com/{scope}/providers/Microsoft.CostManagement/query?api-version=2026-06-01` (for example with `az rest`) with `type: "ActualCost"`, `timeframe: "Custom"`, a `timePeriod` covering the last 8 days, `granularity: "Daily"`, `aggregation: {totalCost: {name: "Cost", function: "Sum"}}` and `grouping: [{type: "Dimension", name: "ServiceName"}]`. Follow `nextLink` if present.
3. **Query by resource group** (Azure): Run the same query grouped by `ResourceGroupName`, for yesterday only. Some older Enterprise Agreement scopes name the cost column `PreTaxCost` instead of `Cost`; use whichever the response lists in `columns`.
4. **Compare**: Yesterday's total against the average of the 7 days before. Rank services and resource groups by cost and by change, and name any that rose more than 30% and $20. If yesterday is far below the average, say the data may still be filling in.
5. **Report**: Yesterday's cost, the change, the top five services and top three resource groups with their change, month to date, and one line on what moved.

## Route B: the browser

### What you need

- Signed in to the Azure portal with the Cost Management Reader role (or Reader) on the subscription or billing scope; a billing account scope needs a billing reader role there.

If something is missing, say what and stop; do not invent numbers.

### Steps

Start at https://portal.azure.com/#view/Microsoft_Azure_CostManagement/Menu/~/costanalysis. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **Pick the scope**: The link opens **Cost Management** > **Cost analysis**. Click the scope name at the top and choose the subscription, or a management group or billing account to cover several. The currency shown is the billing currency of that scope.
2. **Daily cost by service**: Switch the view to **Daily costs** (the customizable view), set the date picker to a custom range covering the last 8 days, keep **Granularity** at `Daily` and set **Group by** to `Service name`. Costs are **Actual cost** by default; leave that.
3. **Download the table**: The chart legend caps the number of services and merges the rest into "Other", so click **Download** and choose Excel or CSV for the per-day, per-service rows. From the file, take yesterday's total, the average of the 7 days before, and each service's change.
4. **Resource groups and month to date**: Change **Group by** to `Resource group name` with the date range set to yesterday only and read the top three. Then switch to the **Accumulated costs** view with the date set to this month for month to date and the portal's forecast line.
5. **Report**: Yesterday's cost and the change against the 7-day average, the top five services and top three resource groups with their change, month to date, and a line on what moved. Flag any service up more than 30% and $20.

Note: Azure services report usage on their own schedules, so yesterday can keep filling in for several hours after midnight, sometimes a day. Cost analysis rounds in the chart; use the download for exact figures. Saved views belong to the person, so an agent changing the view does not affect colleagues, but save nothing.

## The report

- **Yesterday's cost** and the change against the 7-day average.
- **Top services** with their change.
- **Top resource groups** with their change.
- **Month to date** in the billing currency.
- One line on what moved and where to look.

## Post it to Briefkin

When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.

```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
  -H "authorization: Bearer $BRIEFKIN_TOKEN" \
  -H "content-type: application/json" \
  -d @- <<'JSON'
{
  "v": 1,
  "event_id": "azure-daily-cost-report/<date of this run, e.g. 2026-10-16>",
  "item_key": "azure-daily-cost-report",
  "project": "Acme Azure",
  "source": "Azure daily cost report skill",
  "kind": "metric",
  "title": "Yesterday cost $612, 13% above the 7-day average",
  "metric": {
    "label": "Azure cost yesterday",
    "value": 612.48,
    "prefix": "$",
    "better": "lower",
    "period_start": "<start of the period, ISO 8601>",
    "period_end": "<end of the period, ISO 8601>"
  },
  "glance": [
    {
      "type": "Grid",
      "props": {
        "columns": 3
      },
      "children": [
        {
          "type": "Stat",
          "props": {
            "label": "7-day average",
            "value": 540,
            "prefix": "$"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Month to date",
            "value": 8742,
            "prefix": "$"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Top service",
            "value": "Virtual Machines"
          }
        }
      ]
    }
  ],
  "widget": [
    {
      "type": "Table",
      "props": {
        "columns": [
          "Service",
          "Yesterday",
          "vs 7-day avg"
        ],
        "align": [
          "left",
          "right",
          "right"
        ],
        "rows": [
          [
            "Virtual Machines",
            "$241.30",
            "+2%"
          ],
          [
            "Azure SQL Database",
            "$118.60",
            "0%"
          ],
          [
            "Azure Cosmos DB",
            "$92.15",
            "+197%"
          ],
          [
            "Storage",
            "$64.20",
            "+3%"
          ],
          [
            "Bandwidth",
            "$28.40",
            "-4%"
          ],
          [
            "Everything else",
            "$67.83",
            "+5%"
          ]
        ]
      }
    },
    {
      "type": "Bars",
      "props": {
        "unit": "USD",
        "items": [
          {
            "label": "rg-prod-app",
            "value": 402.1
          },
          {
            "label": "rg-data",
            "value": 148.25
          },
          {
            "label": "rg-shared",
            "value": 62.13
          }
        ]
      }
    },
    {
      "type": "Callout",
      "props": {
        "text": "Cosmos DB in rg-data went from about $31 to $92 a day. Provisioned throughput on the events container was raised on Oct 15.",
        "tone": "warn"
      }
    }
  ],
  "size": "md"
}
JSON
```

Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.

Set `period_start` and `period_end` to the window the number covers: the tile names it from them ("Last 7 days", "Today", "This month"). For a count right now (open items, a balance), send `"period_label": ""` so no period shows; for another name, send it as `period_label` (at most 24 characters).

## Run it on a schedule

Suggested: Every day at 8:00 (`0 8 * * *`). From cron, with the agent signed in on that machine:

```bash
0 8 * * * claude -p "Run the azure-daily-cost-report skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```

Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/azure-daily-cost-report#schedule

Source: https://briefkin.dev/skills/azure-daily-cost-report
