Building an Agent Spend View Your Finance Team Will Actually Read
A worksheet for connecting coding-tool subscriptions, model usage, review effort, rework, and build activity to accepted changes, using your own invoices instead of borrowed benchmarks.
It is renewal season, and the invoices for your AI-assisted development stack are spread across four different owners. Assistant seats. Model API usage. CI minutes. A scanning tool that started charging per pull request somewhere along the way. The question from finance is simple and reasonable: what did that buy us?
The honest answer most engineering leaders can give right now is a shrug dressed up as a percentage borrowed from someone else's report. That does not survive a second question.
An agent spend view is a worksheet, not a dashboard. It divides five cost lines (subscriptions, metered model usage, review effort, rework, and build activity) by one defined output unit (accepted changes), reported at a level where someone can actually act on the result. You fill it with your own invoices, your own pull request history, and your own internal rates. This article gives you the worksheet, the definitions that stop arguments, and the places the data actually lives.
The Invoice Nobody Can Explain
The invoices arrive separately, on different cycles, owned by different people. Assistant seats usually sit with a platform or IT budget. Model API usage lands in a cloud or provider console that engineering opened for a pilot and nobody re-owned. CI minutes are buried in the same platform bill as repository hosting. Scanning and observability tools often sit with security.
Nobody sums them, because summing them without a denominator produces a number that only looks bad. Some large figure per month, for what? Compared to what?
This is where borrowed benchmarks fail hardest. A published productivity percentage describes someone else's repositories, review standards, test coverage, and rework rate. If their reviewers approve quickly and yours hold a two-round review on payment paths because a bad change costs real money, the percentage transfers nothing. Worse, quoting it invites finance to hold you to a number you did not generate and cannot reproduce.
The alternative is unglamorous and durable. Define one output unit. Enumerate five cost lines. Pick a reporting level. Write down the assumptions on the same page as the result. You will not get a benchmark. You will get a number you can defend line by line, which is the only kind that survives a finance review.
Pick the Output Unit Before You Total the Costs
Choose the denominator first, or the cost total will quietly choose it for you.
The unit I recommend is the accepted change: a pull request merged to a protected branch, with required checks passing, with a required review recorded, and not reverted or hotfixed within a stated window. Every clause in that sentence is doing work. Merged to a protected branch excludes long-lived experiment branches. Required checks passing and required review recorded mean the change went through your defined path rather than around it. The revert window means you are counting changes that held.
Consider the alternatives and why they break:
- Deploys measure release cadence, not change volume. A team that batches many changes into one deploy looks dramatically cheaper than a team that ships continuously, for no real reason.
- Story points are estimates of effort, not units of output, and they are not comparable across teams by design.
- Lines of code get worse the more capable your tooling gets. A model that emits a long implementation where a short one would do makes your cost per line look excellent.
- Commits reward noise. Agent retries on the same intent inflate the count without adding value.
Then write your exclusion rules down, because they will be challenged. I exclude automated dependency bumps, generated lockfile updates, formatting-only commits, and repeated agent attempts at the same intent where only the final merged attempt counts. Reasonable teams draw these lines differently. Unreasonable teams draw them differently every quarter.
One more discipline: never report cost per accepted change alone. DORA's research program frames delivery throughput and stability as measures that have to be read together, because optimizing one while ignoring the other produces a distorted picture of performance [1]. A cost-per-change number that falls while change failure rate climbs is not an improvement. It is a bill arriving later.
Here is the shape of the calculation, so you can see the method rather than a result. Take your platform's count of merged pull requests for the month. Apply the exclusion rules to remove dependency bumps, lockfile churn, formatting commits, and duplicate agent attempts. What remains is your accepted-change count. Substituting your own two numbers matters more than any illustrative pair I could print. What matters is that the same rules produce both numbers next month.
The Five Cost Lines That Belong in the View
Five lines cover almost everything, and the last two are the ones teams skip.
Subscriptions are per-seat charges for coding assistants, review tooling, and anything else billed by headcount. Pull this from your own billing export, and pull the activity data alongside it. Seats assigned but unused are the single most common finding in a first-pass spend view, and they are also the easiest to act on before a renewal conversation.
Model usage is metered token or request spend from agent runs. Split it into authoring workloads and review workloads if your tooling lets you tag them, because those two categories respond to completely different interventions. Authoring spend follows developer behaviour. Review spend follows pull request volume and diff size.
Review effort is reviewer hours converted at a fully loaded internal rate that you supply. Include re-review rounds, which is where the real cost hides. A change that takes three rounds costs more than three times a single-round change, because context is lost between rounds.
Rework is reverted or hotfixed changes inside your stated window. Build activity is CI minutes, runner costs, and check reruns attributable to agent-opened pull requests. I group these as one line in reporting and two in collection, because they usually move together: changes that come back also burn pipeline time on the way.
| Cost line | Where the number comes from | Who owns it | Update cadence | Common measurement trap |
|---|---|---|---|---|
| Subscriptions | Vendor billing export plus admin activity report | Platform or IT budget owner | Monthly, reconciled at renewal | Counting assigned seats as active seats |
| Model usage | Provider billing console, tagged by workload | Engineering platform lead | Monthly | Mixing authoring and review spend into one figure |
| Review effort | PR review events and timestamps, times internal rate | Engineering manager per team | Monthly | Ignoring second and third review rounds |
| Rework | Reverts and hotfixes within a stated window | Same owner as review effort | Monthly, with a lagging window | Closing the month before the revert window expires |
| Build activity | Actions or Runners usage report, filtered to PR workflows | CI owner | Monthly | Attributing scheduled jobs to pull requests |
The internal rate is yours to set and yours to publish. Whatever finance already uses for fully loaded engineering cost is the right input, because arguing about the rate is not a conversation engineering wins or needs.
Choose a Reporting Level Someone Can Act On
Pick the level by asking who reads the number and what they are allowed to change.
Repository level exposes which codebases absorb disproportionate review and rework cost. This is the most operationally useful level, because the fixes are concrete: adjust ownership routing, tighten merge conditions, add a check, split a service.
Team level supports staffing and tool allocation. It answers whether a squad's tooling spend tracks its output, and it is the level a director can act on in a planning cycle.
Organization level supports renewal negotiation and portfolio decisions. It is the only level finance genuinely needs, and it is nearly useless for diagnosis.
Do not report per developer. The moment an individual's cost per change becomes visible to their manager, the data quality collapses. People will split pull requests, avoid hard repositories, and stop asking for review. You will have converted a spend view into a performance review and lost both.
| Reporting level | Question it answers | Data you need | Who reads it | Best for |
|---|---|---|---|---|
| Repository | Which codebases absorb review and rework cost | PR history, check results, CODEOWNERS routing | Tech leads, platform team | Diagnosis and targeted fixes |
| Team | Does tooling spend track this team's output | Seat assignments, team-scoped PR data | Engineering managers, directors | Staffing and tool allocation |
| Organization | What is the total and what changes if we cut | All five cost lines, rolled up | CTO, finance, procurement | Renewal and budget decisions |
| Per developer | Not recommended | N/A | N/A | Nothing. It degrades the data you need |
Filling the Worksheet: A Two-Repository Walkthrough
Two repositories in the same organization can produce the same cost per accepted change for opposite reasons. That is the argument against a single blended number, and it is easiest to see concretely.
Scenario A: the payments service
High review effort per change. Every pull request touching the settlement paths draws two reviewers, and a substantial share go to a second round. Model usage is modest because the diffs are small and carefully scoped. Rework is low, which is the point of the review depth.
The arithmetic: accepted changes for the month, divided into subscription share plus model usage plus (reviewer hours times your internal rate) plus build minutes. Reviewer hours dominate. The cost per change looks high, and it should, because the review path is doing deliberate work where a wrong change is expensive.
What to change here is routing, not depth. If review requests are landing on whoever is available rather than whoever holds the decision history for those paths, you are paying for expensive review that lacks the context to be efficient. Path-based ownership files exist for exactly this: they route a pull request to the people responsible for a given directory [2]. Tightening CODEOWNERS on the settlement paths reduces rounds without reducing scrutiny.
Scenario B: the internal admin app
Cheap review, high rework. Single approver, fast merges, low model spend. But reverts and hotfixes inside the stated window run high enough that rework becomes the largest line in the view.
Here the cost is real but deferred, which is why teams miss it. The fix is merge conditions rather than more human review time: required checks that actually fail on the class of defect causing the reverts, expressed as organization-level rule sets rather than per-repository settings that drift [3]. Verify enforcement empirically by attempting a merge that should be blocked, because configuration that looks correct and behaviour that is correct are different claims.
Where the Data Actually Lives (and Where It Does Not)
Every line in the worksheet maps to a real system, and the mapping is worth writing down before anyone builds anything.
Pull request events, review records, and check conclusions come from your GitHub or GitLab history. CI minutes come from Actions or Runners usage reports. Model usage comes from the provider billing console. Seat activity comes from your assistant admin tooling, which is where inactive seats surface [4].
Retention is a hard constraint, not a detail. If pull request and check history ages out of your platform or your export pipeline before your reporting window closes, the view cannot be rebuilt later. NIST's secure software development guidance treats archiving the evidence that practices were followed as a practice in its own right, separate from defining the practices [5]. Check your actual retention against your actual reporting window before you promise finance a quarterly view.
For artifact-level questions, emit build provenance as a pipeline by-product. A signed statement describing what was built, from which source, by which builder, removes an entire category of manual reconstruction later [6]. This matters for the spend view because linking rework back to the change that caused it is otherwise archaeology.
Now the part to say plainly: do not try to measure what share of a diff a model wrote. It is not mechanically verifiable, and any number you produce will be an estimate dressed as a measurement. Measure review depth and check outcomes instead, both of which are observable. That is the same discipline that applies to audit evidence for AI-assisted changes, and it is why SlopBuster's context-aware pull request review reports on what the review found rather than guessing at authorship proportions.
A monthly extract that gets two of your five lines into real numbers looks roughly like this:
# Merged PRs for one repo, last month, with review and check state
gh pr list \
--repo your-org/payments-service \
--state merged \
--search "merged:2026-01-01..2026-01-31" \
--limit 500 \
--json number,title,mergedAt,author,reviews,statusCheckRollup \
> merged-prs-2026-01.json
# Count accepted changes after exclusions
jq '[.[]
| select(.title | test("^(chore\\(deps\\)|bump |Update lockfile)"; "i") | not)
| select(.reviews | length > 0)
| select(.statusCheckRollup | all(.conclusion == "SUCCESS"))
] | length' merged-prs-2026-01.jsonRun it once by hand before you automate it. You will discover your exclusion pattern is wrong, and it is cheaper to discover that in a terminal than in a board deck.
Making the Number Survive Its First Finance Review
The first question finance asks is never about the number. It is about the method.
Put the denominator definition, the exclusion list, the internal rate, and the revert window on the same page as the result. If those four things are not visible, the conversation becomes an interrogation about how the number was made, and you will spend the meeting defending arithmetic instead of making a decision.
Separate committed from variable cost. Annual seat commitments are not reducible this quarter no matter what the view says. Model usage, CI minutes, and check reruns are. Finance cares intensely about this distinction, because it determines whether a decision changes cash flow or just changes a slide.
| Renewal input | Before the view | After the view | Decision it enables |
|---|---|---|---|
| Seat count | Headcount-based estimate | Assigned versus active seats, by team | Right-size before signing, not after |
| Model usage | One provider invoice total | Split by authoring and review workload | Cap or tier the workload that grew |
| Review cost | Not measured | Reviewer hours per repository | Fix routing on the expensive paths |
| Rework | Invisible | Reverts and hotfixes per repository | Tighten merge conditions where they pay |
| Build minutes | Bundled platform line | PR workflow minutes, attributable | Cut reruns and redundant required checks |
One cadence, one owner. Monthly is right for most organizations, with a lagging revert window so you are not closing a month before rework has had time to appear. Name the person who rules on exceptions, such as a repository whose review path is expensive on purpose. Without a named owner, every anomaly becomes a debate.
Finally, resist using this view to justify headcount changes in its first two quarters. Measurement noise is highest early, definitions are still settling, and a staffing decision made on a definition you later change is a decision you cannot explain. Use the first two quarters to stabilize the method. Use quarter three onward to make decisions. Tracking which repositories carry disproportionate ownership and rework risk is a separate and complementary exercise, which is where repository and contributor intelligence earns its place next to the spend view.
Frequently Asked Questions
Is cost per accepted change a productivity metric?
No. It is a spend allocation metric. It tells you where money goes per unit of shipped change. It says nothing about whether those changes were the right ones to make, and it should never be read without a stability measure alongside it [1].
What revert window should we use?
Two weeks is a reasonable default for most web and service codebases. Pick one, write it down, and keep it constant. Changing the window changes the number, so changing it mid-year destroys comparability.
Should agent-opened pull requests be counted separately?
Count them separately in collection, together in the denominator. You want to know whether agent-opened changes carry different review and rework profiles, but a change that shipped is a change that shipped regardless of who opened it. Enumerate every identity that can open or merge, including bot and agent accounts, and confirm none of them has a bypass path around required conditions [3].
Do we need the decision context in the repository for this to work?
Not for the arithmetic, but it changes the results. Architecture decision records are a lightweight, version-controlled way to capture the context and consequences of a choice next to the code it governs, rather than in an external wiki [7]. When that context lives only in meeting notes, review rounds multiply because reviewers reconstruct it each time. Repository-resident decision records and typed institutional memory in Genie both attack the same cost line: review effort.
What if our model usage is not tagged by workload?
Start with the single total and split it next quarter. An untagged line you actually report beats a tagged line you keep meaning to build.
How do the five cost lines relate to review quality?
Review effort and rework are the two lines that move in opposite directions, and that is the useful tension in the worksheet. Cutting reviewer hours lowers one line and tends to raise the other after a lag, which is why the view only makes sense read as a whole and paired with a stability measure [1]. The practical lever is usually context rather than time: routing a change to the people who hold the relevant decision history reduces rounds without reducing scrutiny [2]. Our write-up on the hidden costs of code review bottlenecks covers where that queue time accumulates.
What to Do in the Next Thirty Minutes
Four concrete steps, in order.
1. Pull one repository's merged pull request count for last month and apply your exclusion rules. You now have a first accepted-change number and, more importantly, a first draft of the exclusion rules.
2. Export one billing statement and one CI usage report. Two of five cost lines become real instead of estimated, and the gap between the two tells you which data source needs work.
3. Pick the reporting level and name the definition owner before anyone opens a dashboard tool. The dashboard is the last step, not the first.
4. Start tracking reverts and hotfixes within your chosen window, starting this week. Rework is the line most teams omit and the line that most often explains an anomaly. It is also the only line that requires you to wait, so start the clock now.
Then go back to those four invoices you could not reconcile. With the worksheet filled, the answer is not a percentage from someone else's report. It is this: last month we accepted this many changes across these repositories; the cost per accepted change was this, composed of these five lines; two repositories account for most of the variance, one because its review path is expensive on purpose and one because its merge conditions are too loose; here is what we are changing before renewal, and here is what we are not.
That is an answer a finance team will read.
References
[1] DORA, "DORA Research Program." https://dora.dev/research/
[2] GitHub, "About code owners." https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
[3] GitHub, "About rulesets." https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets
[4] GitHub, "GitHub Copilot documentation." https://docs.github.com/en/copilot
[5] NIST, "SP 800-218, Secure Software Development Framework." https://csrc.nist.gov/pubs/sp/800/218/final
[6] SLSA, "Provenance specification, version 1.0." https://slsa.dev/spec/v1.0/provenance
[7] Architecture Decision Records community, "Architecture Decision Records." https://adr.github.io/