Spend · LLM Cost Metrics

LLM Cost Metrics: what did this cost?

LLM Cost Metrics puts what the provider billed beside what this machine measured, two figures never summed, with estimates, unknown rates, unallocated receipts and failed attempts counted apart and every receipt one click away. Below them sits the cost case queue, and each case's Cost section breaks its spend down by purpose. Billing Guard does the same-scope reconciliation, day by day.

For: the engineer asked what an incident or a fix cost, and the owner who has to explain the bill

What it does, and why it helps

The page asks one question: what did this cost? Under the heading, the readiness line says how old the prepared read is (30 minutes is its window). The scope bar's repository applies to the whole page. Environment, service and time narrow the case list and every panel whose reader takes them, and a panel that cannot take one says so.

The page leads with Billed and measured, in this scope, six figures, on the desktop as on the hosted page. Provider billed is the provider cost report Billing Guard reads, for the provider account rather than one repository, over the scope's start to now (Any time reads the 90 days the read allows; an end date is not applied to the bill). Measured usage sums the cost receipts on the cases in scope, each timed inside the window. Estimates are labelled estimate, never invoice evidence, and browser session tokens land there, never in the measured or billed figure. Unknown rate counts the receipts with no price and adds them to no figure. Unallocated counts measured receipts that name no spend purpose. Costly failed attempts prices the runs that ended failed: a build that opened no pull request, a scope run that wrote no brief and a validation run that returned no verdict record how they ended; a receipt that does not say is not judged. An estimate you enter by hand can carry an outcome too, and the receipt shows it, but an estimate never counts as measured spend. A figure nothing reported reads not reported, never zero, and each currency is its own amount, never converted.

Under it on the desktop sits Cost per incident, above the queue: every case in the repository that carries a cost receipt, open or closed, the most measured spend first. Each row shows the case, its status, the measured spend, the estimate and the receipts at an unknown rate, three columns never summed. A case with no receipt is not a row, because no receipt is not a cost of zero, and a spend under a cent reads to four places rather than $0.00. A row opens the case in place on its Cost section, and Billing Guard's Cases with a cost is the same table. This list is not narrowed by environment, service or time.

The two headline figures are never summed and no difference is computed between them: The bill covers the provider account; the measured figure covers the cases in this scope. The same-scope comparison is Billing Guard's, per day and model, and the panel repeats its count of days reconciled, days with a finding and days not checked. Every figure opens its receipts in one click: provider and model, source record, time, rate version (not recorded when the repository sets none), allocation (the case or cases, the spend purpose, a share and its owner), basis and amount. A receipt attached to two cases is one row naming both and counted once.

The queue below lists open cost cases, overdue first, then by severity, under The queue, opened on cost. A cost case opens from a cost event a production events collector sends, from a hand report, or from a reconciliation discrepancy once the materiality rule is recorded. When none is open, the empty state names the Production events gateway's condition: none configured (This is a missing source, not a clean bill.), failed, stale for over 24 hours, idle, or measured (a measured zero for what the collectors report, not for the whole provider bill).

Opening a case lands on its Cost section. Provider invoice and Provider bill name the invoice joined to the case, or say none is. Originating run prices the session the case is attributed to. Investigation, Remediation, Validation and Production impact each read measured, refunded and estimated amounts apart and count unknown-rate receipts; a purpose no receipt names reads not recorded. Measured charges, Refunds, Other currencies and Estimates follow, and Add an estimate records one from a member rate or a model, a rate per hour, hours and a currency (USD, EUR or GBP), kept apart from measured charges. Beside the queue, a panel joins the request log this machine captured into single, replayed, repeated and duplicate charge requests.

Budgets are stated per surface, on the page itself. Billing Guard never caps, blocks or throttles spend. On this machine, a monthly LLM budget set under Settings, Monthly LLM budget, holds agent actions that would spend once the month's measured spend reaches it: a Build it click is refused, a validation run does not start, a spending action through the action gate waits in the approval queue on budget_exceeded, and the unattended scope and build schedules start nothing and write the reason to the daemon log and status. When this machine is bound to a team that set a monthly budget on repoops.ai, the team's budget is the one in force and Settings says so; otherwise the Settings value applies. The spend is the measured usage figure above for the calendar month, so estimates never count toward it. A line above the figures says whether the hold is on, and the hold names the budget, the spend and the month. When the spend cannot be read, nothing is held and the line says the hold failed open. It holds actions on this machine, not provider spend. Hosted budget alerts, set by an owner or admin, notify once a period; they are alerts, not caps.

On the hosted dashboard, LLM Cost Metrics opens repoops.ai/team/costs. It leads with the billed and measured panel described below, then Measured this month (priced applied actions), Forecast (an estimate, not an invoice), Monthly budget, the daily trend, spend by verb and by actor, and Spend is not the same as your invoice. Those figures are the actions RepoOps agents applied, not the provider bill. Below the billed and measured panel, Open cost cases lists the open cost cases in your scope, overdue first, then by severity; when none is open it says whether the cost source in your scope is missing, idle, stale or failed, or a measured zero, rather than reading zero. A row, or a cost case's link, opens the case in place on this page, on its Cost section; the old repoops.ai/team/llm-cost address redirects here with its query string. The panel's measured figure is the team's case cost receipts in your repository scope; its billed figure is the provider bills your desktops attached to cases, one entry per bill, and reads not reported where none is attached, because the provider key stays on the desktop. A receipt a desktop publishes carries how its scope, build or validation run ended, and a hosted validation run records whether it returned a verdict, so failed attempts count those there; a receipt that does not say is not judged. The hosted Cost section carries the same Investigation, Remediation, Validation and Production impact rows, and the Costs page CSV export follows the repository you scoped it to. There is no currency or workload selector on either app.

The pain. An incident costs model time to investigate and to fix, and the provider bill arrives weeks later as one number. Adding what the machine measured to what the provider billed counts the same work twice, and an empty cost list reads as a clean bill when nothing was watching.

The point of view. A cost figure should say where it came from and open to its receipts. Billed and measured are two measures of overlapping work and stay apart; an unknown rate is counted and left unpriced; a source that is missing is named, not read as zero.

What gets easier. Answering what something cost. A figure opens to its receipts with the model, the rate version and the allocation, a case's Cost section splits its spend by purpose, and Billing Guard explains a day where the bill and the records disagree.

When it helps. When someone asks what an incident, an investigation or a fix cost, and when the monthly bill needs explaining.

Its limits. Nothing here caps provider spend: Billing Guard reports, the local monthly LLM budget holds this machine's spending actions rather than the provider account, and hosted budget alerts notify. The bill covers the provider account, not one repository, so it is never compared with the measured figure here. Only scope runs, builds and validation runs record whether a run failed, and a validation run records a receipt only on the cases its package or experiment names. The hosted billed figure is the bills desktops attached to cases, not a provider account total. A cost case opens only from the Production events gateway, a hand report or a recorded reconciliation discrepancy.

Understand it in 30 seconds

30.1 s, captions on. Narration: Microsoft Zira Desktop (provisional voice; an approved narration source is pending).Transcript
Read the narration
  1. 0:00 The provider billed one figure. This machine measured another.
  2. 0:06 Different scopes, so the page never adds them.
  3. 0:09 Billing Guard compares them day by day.
  4. 0:13 Every figure opens its receipts.
  5. 0:15 An unknown rate is counted, not priced.
  6. 0:18 Validation runs on this machine count too.
  7. 0:23 At the budget, builds, validation runs and schedules wait.
  8. 0:27 Provider spend is never capped.

Synthetic example. Read the guide

Where to find it

  • Desktop: LLM Cost Metrics, the fifth primary page.
  • Hosted: repoops.ai/team/costs, under LLM Cost Metrics in the sidebar. A cost case's link opens the case there, on its Cost section; the old repoops.ai/team/llm-cost address redirects to it.
  • API: /api/ai-incidents?class=cost, /api/integrations

When to use it

What did fixing this incident cost?

Situation. A production case was investigated and fixed last week. Someone asks what the model work cost.

What you do. Open the case from its page, or from Billing Guard's Cases with a cost, and read its Cost section.

What you see. Investigation and Remediation read measured amounts; Validation and Production impact read not recorded where no receipt names them. Measured charges lists any receipt at an unknown rate apart. Provider bill reads No bill is attached to this case until an invoice is attached from Billing Guard.

What it establishes. A figure for the measured work, with what is unknown named. It is not a share of the provider bill, and the page does not pretend it is.

The bill looks higher than the work

Situation. Provider billed reads far above Measured usage for the last 30 days.

What you do. Read the note under the figures, then open Unallocated and Unknown rate, then open Billing Guard.

What you see. The note says the bill covers the provider account and the measured figure covers the cases in scope, so no difference is computed. Unknown rate lists receipts counted and not priced. Billing Guard's days show which ones reconciled, which have a finding and which were not checked.

What it establishes. You explain the gap from its parts: work outside any case, other repositories on the same account, unpriced receipts, and the days Billing Guard flagged. No figure on the page claims the gap is waste.

Before you start

Supported versions
Read against origin/main at 154f31d3f, after v0.3.2 and LDG-1002 part 1.
Where it runs
Local: LLM Cost Metrics, with the six figures and their receipts, the queue, the request-log panel and the tools; each case's Cost section; Billing Guard. Hosted: LLM Cost Metrics opens repoops.ai/team/costs, which leads with the billed and measured panel, its receipts and bills, then the open cost cases; a cost case's link opens the case there, and repoops.ai/team/llm-cost redirects to it.
Permissions
Adding an estimate is a local write behind the server's same-origin gate. On the hosted dashboard, only an owner or admin sets the budget alerts.
Connections
A provider cost key on Billing Guard for Provider billed; without one it reads not reported. Cost receipts on cases for Measured usage. A Production events gateway with a collector sending cost events, for cost cases to open on their own. The request-log panel needs the OTEL logs exporter pointed at this machine.
Plan
No plan gate on the local page. The hosted pages follow the hosted dashboard tiers.

Configure it

  1. Pick a repository.

    The repository applies to the whole page. Environment, service and time narrow the case list only.

  2. Read the two headline figures apart.

    Provider billed covers the provider account; Measured usage covers the cases in scope. Open a figure's receipts before trusting it, and read Unknown rate and Unallocated beside it.

  3. Read the empty state, if there is one.

    It names the source condition: missing, failed, stale, idle or measured. Only measured is a zero, and only for what the collectors report.

  4. Open a case on its Cost section.

    Read each part with its basis. An unknown rate is counted, not priced. Add an estimate if a person's time belongs in the picture, and it stays apart from measured charges.

  5. Check the bill on Billing Guard.

    Connect the provider account, set the tolerance band, and read the days the bill and the records disagree.

SettingWhereA sensible choiceWhy it matters
Tolerance bandBilling Guard, Reconciliation2% (the default)How far a day may drift before Billing Guard calls it a discrepancy.
Budget alertsrepoops.ai/team/overview, Budget alerts (owner or admin)blank for no limitA daily sweep notifies Slack and the owners and admins by email once per period. It does not cap spend.
ⓘ
To stop or undo
Nothing on this page runs on its own; it reads cases and sources. Billing Guard reads the provider only for an account you connected.

What you should see

A case with measured work

Configuration. A case whose investigation and build ran on this machine, no invoice attached.

Expect. Investigation and Build read measured amounts. Provider bill reads that no bill is attached. Nothing is added to a provider figure.

Verify. Measured charges lists the receipts; any at an unknown rate are counted apart with the words not summed.

No provider key on this machine

Configuration. Billing Guard has no provider cost key.

Expect. Provider billed reads not reported: No provider cost key is set on this machine, so the provider bill is not reported. Measured usage still reads the case receipts.

Verify. The note under the figures says same-scope reconciliation is not reported and links to Billing Guard.

No source watches the cost class

Configuration. No Production events gateway configured for the repository.

Expect. The queue reads Nothing to open on this lens, with the missing-source sentence.

Verify. The sentence ends This is a missing source, not a clean bill.

Data and cost

What is captured
The page reads the case store, the integrations list and Billing Guard's provider cost report. Cost receipts, estimates and refunds are written on the case. The request-log panel reads the requests the OTEL logs receiver stored under the repository brain.
Who can see it
Local by default. The hosted Costs page reads applied-action spend the team's devices report; it does not read this machine's case Cost sections.
How long it is kept
The page sets no retention of its own. Case files are read over a 24-month window.
What leaves the machine
Reading the page makes no model call. Provider billed comes from Billing Guard, which reads the provider's cost report for a key you set.
What it costs
No model spend to read the page.

When the result differs

SymptomLikely causeNext action
Nothing to open on this lens, with a missing-source sentence.No Production events gateway is configured for this repository.Configure the gateway and point a collector that reports cost at it, or open a cost case by hand.
The same, but it says idle.The gateway is delivering, but no collector has sent it a cost event.Check that the collector reports cost; until it does, the page cannot tell a quiet bill from a collector that does not report cost.
The case store could not be read.The read of the case store failed or timed out.Use Refresh to retry. This is not an empty queue.
Provider bill reads No bill is attached to this case.No invoice was attached to the case.Attach one from Billing Guard once the provider bill is read.
Measured usage reads not reported.No priced measured receipt is on a case in this scope, or the case store could not be read.Widen the scope, or read the sentence under the figure: a failed read says so and is not a zero.
Costly failed attempts reads not reported.No receipt in this scope says how its run ended. Scope runs, builds and validation runs record it on this machine; a receipt that does not say is not judged.Nothing to fix. The figure fills once a scope run, build or validation run in this scope has ended.
Build it says Held and names the monthly LLM budget.This month's measured spend reached the budget set under Settings, Monthly LLM budget.Raise or clear the budget in Settings, or wait for the month to turn. Validation runs and spending actions wait for the same reason.
Replayed and duplicate charge read not reported.The request store carries no delivery count.Nothing on the page fixes it. The cells fill once the request store records how many times each id was delivered.
Disable
Nothing to turn off on this page. Disconnect on Billing Guard removes a provider key from this machine and stops it reading that bill; your local records stay.
Roll back
Not provided. An estimate, once recorded, stays on the case.
Revoke access
Disconnect on Billing Guard removes the key from this machine; a key set in the environment is removed where it is configured. On the hosted dashboard an owner or admin clears the budget fields.
Delete
Not provided in the app. Cost receipts and estimates are part of the case record.

Maintenance evidence

Feature id
llm-cost-metrics (spine leaf llm-cost)
Owner
LLM Cost Metrics pillar (LDG-0688, LDG-0746, F04 LDG-0967). Guide: LDG-0988.
Supported product version
RepoOps main at 154f31d3f (after v0.3.2, with LDG-1002 part 1)
Last verified
2026-09-26, the budget and failed-attempt lines re-read against the LDG-1011 branch (the team budget, the schedules, local validation receipts, the estimate outcome); the rest read against origin/main at 154f31d3f, after LDG-1002 part 1 added the six figures, the receipts and the economics rows: public/lib/cost-summary.js, public/lib/pillar-landing.js, public/lib/scope-bar.js, public/lib/case-sections.js, lib/home-content.mjs, public/billing-guard.html and the hosted costs, llm-cost and overview pages; not opened on a running instance.
Example fixtures
No fixture file; inline cases in lib/cost-page-summary.test.mjs, public/lib/cost-summary.test.mjs, lib/routes/ai-incidents.lens.test.mjs, public/lib/pillar-landing.test.mjs and lib/home-content.test.mjs.
Source references
public/llm-cost.html, public/lib/cost-summary.js, public/lib/pillar-landing.js, public/lib/scope-bar.js, public/lib/case-sections.js, lib/home-content.mjs, public/billing-guard.html, lib/incident-source-contract.mjs, lib/actions/policy.mjs, lib/budget/llm-budget.mjs, lib/routes/prevention-validation.mjs, public/settings.html, website/app/team/(home)/costs/page.tsx, website/app/team/(home)/overview/page.tsx
Documentation review
Written 2026-09-26 by the authoring agent against the code (LDG-0988); independent review not yet recorded.
Video review
Narrated story re-rendered and published 2026-09-26 (render 58911f0dd19b, LDG-1011 part 2) against main at 0b397c973, after the budget hold reached the schedules, the team budget and local validation receipts; the render it replaces (24b6b4f6b4ec) said no budget held anything. Six frames, the eight captions and the transcript were re-checked by the authoring agent, not an independent reviewer; the published mp4's sha256 matches the render; the audio was not listened to by a person. Narration is the provisional Windows voice until LDG-0721.

Last updated