Skip to content
SpendByTeam

Journal Engineering management

AI coding spend by team: how to see who's using what, and why it matters

Your AI coding bill is one number. Here's how to break it down by team, project and developer from OpenTelemetry metrics — and what to do with the numbers once you have them.

7 min read

Twelve months ago, AI coding agents were something a few enthusiasts expensed. Today they are a budget line big enough that someone in finance has started asking questions. The awkward part is that the invoice can’t answer them. It shows a total, maybe a per-user list, and nothing about what the money was spent on.

If you run an engineering org, the question you’ll be asked isn’t “how much did we spend on AI?” — you already know that. It’s “which team, which product, and was it worth it?”

This post walks through how to answer that with data you already have, and the traps to avoid along the way.

Why per-user numbers aren’t enough

Most provider consoles give you spend per seat or per API key. That’s a start, but it maps badly onto how engineering organizations actually budget:

  • Budgets live at team and product level, not at person level. Nobody has a “Dana” cost centre.
  • People move between projects. A senior engineer might spend Monday on the checkout service and Thursday helping the mobile team. Per-user totals smear that across both.
  • Per-person leaderboards backfire. The fastest way to make developers stop using a tool that’s working is to publish a ranking of who “costs the most”. The developer at the top of that list is often your most productive one.

What you want is the same numbers, re-cut along the axes you already manage: team, project, repository, and — if you’re an agency — client.

Where the data comes from

Modern coding agents emit OpenTelemetry metrics. Claude Code, for example, can export counters such as:

Metric What it measures
claude_code.cost.usage Estimated cost of each request, in USD
claude_code.token.usage Input, output and cache tokens
claude_code.session.count Sessions started
claude_code.lines_of_code.count Lines added and removed
claude_code.pull_request.count Pull requests created

Each data point carries labels: a session ID, the user’s email, the model — and, in recent versions, the repository URL the session was working in. That last label is the key that unlocks per-project reporting, because repositories map cleanly to projects, and projects map to teams and clients.

Two settings matter for privacy. Metrics are just numbers with labels; the content-bearing signals are logs and traces, and they can be switched off independently. A team-spend setup should set OTEL_LOGS_EXPORTER=none and OTEL_TRACES_EXPORTER=none, and never enable the flags that log prompts or tool inputs. You get the accounting without any of the content.

The attribution model

Turning raw data points into a team report is a small chain of lookups:

  1. Data point → repository. Normalise the repo URL so [email protected]:acme/api.git and https://github.com/acme/api are the same thing.
  2. Repository → project. Usually one-to-one; sometimes a project spans a backend, a frontend and an infra repo.
  3. Project → team (and project → client for agencies).
  4. Developer → team, as a fallback for work that happens outside a repository.

Anything that can’t be resolved goes into an explicit “Unattributed” bucket. Resist the temptation to hide it. A visible unattributed number is what gets people to install the hook or map the missing repo; a hidden one silently corrupts every other figure.

What a useful team report looks like

Once the attribution is in place, a monthly team view should answer five questions on one screen:

  1. How much this month, and how does it compare to last month?
  2. What’s the forecast for month end? A linear projection from the month-to-date run rate is crude but catches runaway spend by the 10th, not the 30th.
  3. Which projects drove the change? The top five projects usually explain 80% of any month-over-month movement.
  4. Which teams are near their budget?
  5. How much is unattributed?

Then add one efficiency figure — we like cost per merged pull request — as a sanity check rather than a target. A sudden jump in cost per PR on one service is worth a conversation; a high but stable number usually just means the work is hard.

Mistakes we see teams make

Using cost as a performance metric. Spend tells you where effort went, not whether it was good. Pair it with delivery data (PRs, tickets) and treat outliers as questions, not verdicts.

Forgetting seat-based plans. If you pay a flat monthly price per seat, the per-request cost in the metrics is an API-equivalent value, not cash out of your account. It’s still the right number for comparing teams and projects — it tells you who gets the most out of the seats — but label it honestly in reports to finance.

Reporting by person by default. Decide the visibility rules before rolling out. Many teams settle on: team leads see their own team, finance sees teams and projects but no names, and individual numbers are visible only to the developer themselves. An anonymous mode — “Dev #4” instead of a name — removes most of the anxiety.

Rolling out machine by machine. If your agent supports managed settings, push the configuration centrally. It’s faster, it guarantees logs and traces stay off, and it prevents anyone from redirecting the telemetry elsewhere.

A 30-minute plan

  1. Pick three volunteers and install the exporter on their machines.
  2. Let it run for a week. Map the repositories you see to projects and teams.
  3. Look at the unattributed share. If it’s above 5%, fix the mapping or install the context hook.
  4. Agree visibility rules with your leads.
  5. Roll out org-wide with managed settings and set a soft budget per team at roughly last month’s spend plus 20%.

That’s it. Next month, when someone asks where the AI budget went, you’ll have an answer that fits on one slide — and doesn’t involve anyone’s prompts.

SpendByTeam does all of the above out of the box: install guide, what we collect.