Skip to content

feat(cost): itemize reasoning cost per span and by model#34

Merged
JoniMartin27 merged 1 commit into
mainfrom
feat/reasoning-cost-breakdown
Jun 13, 2026
Merged

feat(cost): itemize reasoning cost per span and by model#34
JoniMartin27 merged 1 commit into
mainfrom
feat/reasoning-cost-breakdown

Conversation

@JoniMartin27

Copy link
Copy Markdown
Owner

@

What

Lookspan already bills reasoning tokens at their own rate, but the cost was blended into the per-span total. This makes the reasoning cost a first-class, queryable figure — per span and per model.

  • computeCostBreakdownUsd(model, usage) returns { total, reasoning }. computeCostUsd is now a thin wrapper, so existing behavior/signature is unchanged.
  • enrichSpanCost stores a per-span reasoning_cost_usd at ingest (additive migration v7; SQLite + Postgres parity verified in-process via pg-mem).
  • CostsRepository.summary adds reasoning (total) and reasoningByModel (the routing dimension). GET /api/costs/summary surfaces both.
  • Dashboard Costs view shows reasoning as a share of total cost and charts Reasoning cost by model.

The reasoning figure is computed even when a model has no explicit reasoningPer1M — it is then the share of the output bill those tokens account for, which is the very signal that tells you whether a dedicated reasoning rate is worth setting. It is always a sub-component of total, never an extra charge.

Why

In reply to the reasoning-token billing post, @alphaxagent.bsky.social noted:

Separate reasoning token billing makes the "use a smarter model on harder requests" routing strategy much more legible — you can now see exactly what the reasoning premium costs per request type, not just in aggregate.

This delivers exactly that: the reasoning premium is now visible per request type (per model), not just in aggregate.

Tests

  • computeCostBreakdownUsd: explicit reasoning rate, output-rate fallback (total unchanged), zero-reasoning, unknown model.
  • enrichSpanCost: itemizes reasoningCostUsd on the span.
  • CostsRepository.summary + Postgres parity: reasoning total and reasoningByModel round-trip and sum.
  • API: /api/costs/summary exposes the new fields.

npm run ci green locally: typecheck, lint (biome), 237 tests, build.

🤖 Generated with Claude Code
@

feat(cost): itemize reasoning cost per span and by model

Reasoning tokens were already billed at their own rate, but the cost was
blended into the per-span total. This surfaces it as a first-class figure:

- computeCostBreakdownUsd returns {total, reasoning}; computeCostUsd is now a
  thin wrapper over it, so existing behavior is unchanged.
- enrichSpanCost stores a per-span reasoning_cost_usd (additive migration v7,
  SQLite + Postgres parity verified in-process).
- CostsRepository.summary adds `reasoning` (total) and `reasoningByModel` — the
  routing dimension. The /api/costs/summary route surfaces both.
- Dashboard shows reasoning as a share of total and charts cost by model.

The reasoning figure is computed even with no explicit reasoning rate (the share
of the output bill those tokens account for), so it stays a sub-component of the
total, never an extra charge.

This makes the "use a smarter model on harder requests" routing premium legible
per request type instead of only in aggregate — as suggested by @alphaxagent.bsky.social.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
@JoniMartin27 JoniMartin27 merged commit f566290 into main Jun 13, 2026
2 checks passed
@JoniMartin27 JoniMartin27 deleted the feat/reasoning-cost-breakdown branch June 13, 2026 23:43
JoniMartin27 added a commit that referenced this pull request Jun 13, 2026
Reasoning tokens were already billed at their own rate, but the cost was
blended into the per-span total. This surfaces it as a first-class figure:

- computeCostBreakdownUsd returns {total, reasoning}; computeCostUsd is now a
  thin wrapper over it, so existing behavior is unchanged.
- enrichSpanCost stores a per-span reasoning_cost_usd (additive migration v7,
  SQLite + Postgres parity verified in-process).
- CostsRepository.summary adds `reasoning` (total) and `reasoningByModel` — the
  routing dimension. The /api/costs/summary route surfaces both.
- Dashboard shows reasoning as a share of total and charts cost by model.

The reasoning figure is computed even with no explicit reasoning rate (the share
of the output bill those tokens account for), so it stays a sub-component of the
total, never an extra charge.

This makes the "use a smarter model on harder requests" routing premium legible
per request type instead of only in aggregate — as suggested by @alphaxagent.bsky.social.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant