Tool

Monitor and optimize AI agent token costs in CI/CD

CLI that prices token waste in an AI agent trace, prescribes fixes, and can fail CI when a change makes the agent measurably more expensive.

Works with opentelemetrygithubpypinpm

91
Spark score
out of 100
Updated 7 days ago
Version 0.1.0

Add to Favorites

Why it matters

Wattage helps engineering teams prevent cost regressions in AI agents by analyzing OpenTelemetry traces to detect token waste patterns, price them in real dollars, and fail CI builds when changes make agents measurably more expensive.

Outcomes

What it gets done

01

Detect token waste patterns like uncached prompts, redundant tool calls, and non-converging loops across agent traces

02

Price every LLM call and waste pattern in real dollars using vendored model pricing snapshots

03

Generate token efficiency scores and badges for README documentation and team visibility

04

Block pull requests that exceed cost thresholds or introduce critical efficiency regressions

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/faizannraza-wattage | bash

Overview

Wattage

A CLI tool that ingests an OpenTelemetry GenAI trace of an AI agent, prices every LLM call against a dated pricing snapshot, runs eight detectors for specific waste patterns like re-sent stable context or thrashing loops, and grades the trace 0-100 for token efficiency. Use it to find and price exactly where an agent's tokens are wasted and to gate CI so a pull request fails when it measurably regresses an agent's cost or efficiency score.

What it does

wattage is a CLI, described as a Kill-A-Watt meter for AI agents, that reads a captured agent trace, prices exactly where tokens are being burned and wasted in real dollars, and prescribes a concrete fix for each waste pattern found. It ingests OpenTelemetry GenAI semantic-convention traces through a normalized data model, sessions to tasks to loops to iterations to calls, and runs eight detectors: prefix_churn (stable context re-sent instead of cached), cache_gap (caching attempted but under-redeemed), verbosity, redundant_tool_calls, nonconvergence (loops that thrash, oscillate, or stall without progress), retrieval_thrash, model_mismatch, and reasoning_overspend. Every finding is priced, comes with a fix, and is tagged with a quality_risk tier so a fix that could plausibly change output quality only counts toward the efficiency score once a --quality map backs it with real evidence.

When to use - and when NOT to

Use it to audit an existing agent's trace for cost waste, to grade a trace 0-100 for token efficiency (wattage score / wattage badge), or to gate CI so a pull request fails when a change regresses an agent's cost or score past a set threshold. It never fabricates a number: a call against an unpriced model is left at zero cost and fails wattage ci loudly with a distinct exit code rather than guessing, and an unmeasured quality signal is reported as unmeasured rather than assumed fine. Its nonconvergence detector is benchmarked against a hand-reviewed set of 10 labeled synthetic loops at 1.00 precision and recall, versus 1.00/0.14 for a naive SHA-256 exact-match baseline, since exact-match structurally cannot catch a retry with a fresh timestamp or an oscillation between two strategies.

Inputs and outputs

uvx wattage report trace.json

Input is an OTLP JSON trace export, no config file or API key required, and it runs fully offline. Output is a terminal report, Token Efficiency grade, total cost, a token breakdown table, and per-detector findings, or, with --html, a self-contained shareable flame graph. On a real captured trace, the prefix_churn fix simulation showed a 44.7% cost reduction, $0.000199 to $0.000110, from enabling prompt caching on a stable prefix; the dollar figures are small because it's a 3-turn demo trace, but the mechanism holds at production scale.

Integrations

wattage badge trace.json --out wattage-badge.svg produces a live README badge. The GitHub Action, faizannraza/wattage/action, wires into a pull_request workflow with a fail-on threshold, score_below, cost_delta_pct_above, any_critical, posts a per-detector delta table as a PR comment, and emits both SARIF, visible in GitHub's Security tab, and JUnit XML for other CI systems; the committed .wattage/baseline.json only updates on a separate push-to-default-branch workflow that runs after a merge, so PR runs never write their own baseline. Custom detectors are added through a Python entry-point plugin group without touching the core pipeline.

Who it's for

Teams running LLM agents in production who need to see exactly where tokens are wasted, in priced dollars, and to stop a cost or efficiency regression from merging. The project is Apache-2.0 licensed.

Source README
wattage

CI
PyPI
npm
Python versions
License: Apache 2.0
Docs

A Kill-A-Watt meter for your AI agents. Point it at a trace and it tells
you exactly where your tokens are being burned and wasted, prices each waste
pattern in real dollars, prescribes a fix, and can fail your CI when a change
makes your agent measurably more expensive.

wattage report demo

A real captured agent trace (see provenance) -
Wattage catches a stable prompt prefix being re-sent instead of cached, prices
the waste, and prescribes the fix. Regenerate this GIF with
vhs docs/assets/demo.tape (see the tape file for the exact command).

Install and run

uvx wattage report trace.json

No config file, no API key, fully offline - point it at an OTLP JSON
trace export and it prices every call and runs every detector. Don't have a
trace yet? Getting your first trace covers both
"I already have OTel traces" and "I have zero instrumentation" (a runnable,
5-minute path from nothing to a real, priced report). Or try it right now
against the fixture shipped in this repo:

git clone https://github.com/faizannraza/wattage
cd wattage && uv sync
uv run wattage report examples/sample_trace.json
╭──── ⚡ wattage — examples/sample_trace.json ────╮
│ Token Efficiency: A (100)   Total cost: $0.0602 │
│ quality: unmeasured                             │
╰─────────────────────────────────────────────────╯
      Token breakdown
┏━━━━━━━━━━━━━━━━┳━━━━━━━━┓
┃ Category       ┃ Tokens ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━┩
│ input          │  18450 │
│ output         │    320 │
│ cache_read     │      0 │
│ cache_creation │      0 │
│ reasoning      │      0 │
└────────────────┴────────┘
No findings — this trace looks efficient.
pricing: 2026-07-18-verified

Or get a self-contained, shareable HTML flame graph instead of the terminal
view:

uv run wattage report examples/sample_trace.json --html report.html

The evidence, not a marketing claim

Wattage's standout feature is the convergence engine - the
nonconvergence detector, which catches an agent thrashing through a loop
without making real progress, including patterns a naive exact-match
duplicate detector structurally cannot see (a retry with a fresh timestamp
each time, an oscillation between two strategies, a "productive-looking"
stall where every call is technically unique but nothing is actually
learned).

Rather than assert that, we built a hand-reviewed set of 10 labeled
synthetic loops and benchmarked Wattage's classifier against a real
SHA-256 exact-match baseline implementation:

Classifier Precision Recall F1
Wattage 1.00 1.00 1.00
SHA-256 exact-match 1.00 0.14 0.25

Reproduce it yourself - no cherry-picking, no hidden setup:

uv run python -m benchmarks.harness

And on a genuine captured agent trace (not synthetic - see
benchmarks/traces/README.md for provenance),
Wattage's prefix_churn fix simulation shows a 44.7% cost reduction
($0.000199 → $0.000110) from enabling prompt caching on the stable prefix -
small dollar figures because it's a 3-turn demo trace, but the mechanism is
identical at production scale. Run it against your own traces for numbers
that matter:

uv run python -c "from benchmarks.frontier import build_frontier; print(build_frontier())"

Full methodology: The Convergence Engine.

The badge

uv run wattage badge trace.json --out wattage-badge.svg

Wire --badge-out into your CI job (see below) so it regenerates on every
merge to your default branch, and the badge in your README stays live.

How it works

Three surfaces, one normalized data model underneath
(sessions → tasks → loops → iterations → calls), built from
OpenTelemetry GenAI semantic-convention
traces:

  • wattage report - ingests a trace, prices every call against a
    vendored, dated pricing snapshot, and runs eight detectors:

    Detector Catches
    prefix_churn Stable context re-sent instead of cached
    cache_gap Caching attempted but under-redeemed by later reads
    verbosity Output far beyond what the step needed
    redundant_tool_calls The same tool call repeated (exact or fuzzy)
    nonconvergence Loops that thrash, oscillate, or stall without progress
    retrieval_thrash Repeated retrieval that never yields relevant results
    model_mismatch A pricier model doing work a cheaper one could handle
    reasoning_overspend Heavy reasoning-token spend on a simple step

    Every finding is priced in real dollars, includes a concrete fix, and is
    tagged with a quality_risk tier (none / low / review) - a fix that
    could plausibly change output quality (a model downgrade, less reasoning)
    only counts toward your score once a --quality map backs it with real
    evidence. Full detail: Detectors.

  • wattage score / wattage badge - a single 0-100 Token Efficiency
    grade for a README badge or a CI gate.

  • wattage ci - the cost-regression gate (below).

Wattage never fabricates a number: an unpriced model leaves that call's cost
at zero (and fails wattage ci loudly, exit code 4) rather than guessing;
an unmeasured quality signal is reported as unmeasured, not assumed fine.

CI integration

# .github/workflows/wattage.yml
name: Wattage
on:
  pull_request:
    paths: ["agents/**", "prompts/**", "src/**"]
concurrency:
  group: wattage-${{ github.ref }}
  cancel-in-progress: true
jobs:
  token-efficiency:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Generate trace fixture
        run: python scripts/run_agent_fixture.py > trace.json
      - name: Wattage cost-regression gate
        uses: faizannraza/wattage/action@v0.1.0
        with:
          source: trace.json
          baseline: .wattage/baseline.json
          fail-on: "score_below:80,cost_delta_pct_above:5,any_critical:true"
          pr-comment: "true"

Fails the build (exit code 1) when your agent regresses past the threshold
you set, posts a per-detector delta table as a PR comment, and emits SARIF
(shows up in GitHub's Security tab) and JUnit XML for any other CI system.
The baseline is a small committed JSON file - noise-floor protection is
structural, not statistical: it only ever updates on a run that actually
passed the gate.

This is only half the setup. A PR job runs on a throwaway checkout, so
it can't be the thing that updates .wattage/baseline.json on disk - that
update needs a second workflow, triggered on push to your default branch,
that commits the refreshed baseline (and badge) back after each merge.
Skipping it means every PR compares against the same stale baseline
forever. Full reference, with both workflows: CI Integration.

FAQ

Common questions

Discussion

Questions & comments · 0

Sign In Sign in to leave a comment.