Skip to content

feat: segment agent spend by backend (Bedrock vs direct) on the Usage page#14

Merged
iaj6 merged 3 commits into
mainfrom
feat/bedrock-legibility-slice-1
Jun 10, 2026
Merged

feat: segment agent spend by backend (Bedrock vs direct) on the Usage page#14
iaj6 merged 3 commits into
mainfrom
feat/bedrock-legibility-slice-1

Conversation

@iaj6

@iaj6 iaj6 commented Jun 9, 2026

Copy link
Copy Markdown
Owner

What & why

AgentOps already computes backend-agnostic cost from Claude Code transcripts (the differentiator that governs Bedrock/Vertex traffic the Anthropic Admin API can't see) — but the hook detected the backend and computed per-model cost, then threw both away before persisting metrics. So the dashboard couldn't tell a Bedrock run from a direct one, and the Bedrock value was invisible.

This slice makes that value legible: it persists the per-run backend and byModel, then segments Usage-page spend by backend with an explicit honesty badge.

Changes

  • Capture (b79b6a3) — optional backend + byModel on the Metrics type; the already-in-scope values are carried into the session-end metrics literal. Local mode persists for free via finalizeRun → updateRun into the runs.metrics JSON column (no migration, no new column). Exports BEDROCK_PRICING_IS_PARITY_ESTIMATE + verified date.
  • Segment + honesty UI (9152a92) — /api/usage/local buckets spend into bedrock / anthropic / unknown (buckets reconcile to totalCost) and surfaces the parity-estimate flag. The Usage page renders a "By backend" breakdown; untagged/legacy runs show as "Not yet classified" and are never folded into Direct; Bedrock dollars carry a "Bedrock est." badge + footnote.
  • SDK write path (3833679) — doReportMetrics forwards backend/byModel; the metrics route validates (backend ∈ {anthropic,bedrock}; byModel a map of finite, non-negative costs) and persists them, so SDK-mode runs are tagged too.

Honesty guardrail

BEDROCK_PRICING is still a parity copy of the Anthropic-direct rates, so the $-magnitude is an estimate while the backend attribution is exact. The UI says exactly that: token volumes + "this ran on Bedrock" are exact; dollar amounts are estimated at Anthropic-direct US rates (verified 2026-05-13) pending AWS verification. When real Bedrock rates land, flip the flag and the caveat disappears with zero UI rework.

Verification

  • Build green, web lint clean
  • 1268 tests pass (+5: CLI Bedrock-tagging end-to-end, 3 SDK-route validation/persistence, 1 usage-bucketing incl. the buckets-reconcile-to-total invariant)
  • Adversarial review (3 lenses → verify): 0 confirmed findings

Deferred to follow-ups (out of scope here)

run_metrics.backend column (nothing queries it yet) · per-user Bedrock attribution table · stacked Cost-Per-Day chart · real per-region Bedrock rates · historical backfill from on-disk transcripts.

🤖 Generated with Claude Code

iaj6 and others added 3 commits June 9, 2026 16:49
The hook already detects the backend (CLAUDE_CODE_USE_BEDROCK) and computes
per-model cost from the transcript, then discarded both before persisting
metrics — so the dashboard could not tell a Bedrock run from a direct one.

Add optional `backend` and `byModel` to the Metrics type and carry the
already-in-scope values into the session-end metrics literal. Local mode
persists them for free via finalizeRun -> updateRun into the runs.metrics
JSON column (no migration, no new column). Also export
BEDROCK_PRICING_IS_PARITY_ESTIMATE + a verified date so the UI can flag
Bedrock dollars as estimated — BEDROCK_PRICING is still a parity copy of the
Anthropic-direct rates, so the $-magnitude is an estimate while the backend
attribution is exact.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
… badge

/api/usage/local now buckets captured spend into bedrock / anthropic / unknown
(the buckets reconcile to totalCost) and surfaces the parity-estimate flag +
verified date. The Usage page renders a "By backend" breakdown under the local
cost card. Untagged/legacy runs show as "Not yet classified" and are never
folded into Direct (which would manufacture a confident "you have no Bedrock
spend"). Bedrock dollars carry a "Bedrock est." badge + footnote because the
rates are an Anthropic-parity estimate, not AWS billing.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
In SDK mode the metrics POST body dropped backend/byModel, and the route
rebuilt the metrics object field-by-field, so SDK-mode runs always read as
unclassified — a confusing half-feature next to local mode. Forward both
fields from doReportMetrics and validate + persist them in the route
(backend in {anthropic, bedrock}; byModel an object mapping model ids to
finite, non-negative costs). They live only in the runs.metrics JSON blob —
no run_metrics column, since nothing queries run_metrics for backend yet.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@iaj6 iaj6 merged commit 7e9ca33 into main Jun 10, 2026
3 checks passed
@iaj6 iaj6 deleted the feat/bedrock-legibility-slice-1 branch June 10, 2026 22:28
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