¢ Token Economy
.NET · dependency-free core

Token Economy

Token economics for LLM coding agents.

One tested source of truth for model pricing (with history), run-cost computation, and token-efficiency model selection — so a coding agent knows what a run costs and which model buys the most for its tokens.

Get started View on GitHub $ dotnet add package TokenEconomy

What it does & why

Coding-agent orchestrators need to answer two money questions precisely: what did that run cost? and which model should run this next? Hardcoded, half-null price tables scattered across services answer both badly. Token Economy replaces them with one deterministic, unit-tested library.

01

Pricing catalog with history

Per-model price entries keyed by ValidFrom. A run is costed with the price valid at the run's UTC timestamp. Historic entries are kept, never overwritten.

02

Cost API

ComputeCost(model, usage, atUtc) → a deterministic per-component breakdown and total. An unknown or unpriced model returns an explicit unknown — never a silent $0.

03

Token-efficiency matrix

SuggestModel(…) ranks the models available right now for a task under budget pressure, each with a one-line rationale. Cost class is derived from the catalog, never restated.

From task to evidence

Token Economy separates a routing recommendation from an observed result. That distinction keeps a cheap-looking model from being treated as a good choice without evidence.

01 / ESTIMATE

Describe the work before launch

TaskComplexityEstimator turns observable card and repository signals into a versioned complexity band, confidence, predicted tokens, duration, reissues, and inspectable evidence. It estimates expected work, not business importance.

02 / ROUTE

Choose transparently

SuggestModel combines task fit, derived cost class, and availability into ranked choices with an auditable rationale. An orchestrator decides whether and how to act on that recommendation.

03 / OBSERVE

Measure the outcome

Controlled A/B setups record success, token use, duration, and authoritative cost when available. Operational history can retain the same outcome signals for later calibration.

What informs a complexity estimate

Its evidence is deliberately pre-launch: touched surface and dependency fan-out, novelty, constraint density, specification ambiguity, required reading, and verification cost. Actual changed files, tool calls, and review feedback are outcomes for later calibration, not inputs that would leak the answer into the estimate.

The learning loop is deliberately closed but not automatic: task features → complexity estimate and model choice → observed tokens, duration, reissues, and outcome → reclassification or updated policy. Historical neighbours can inform a new estimate; the optional host-supplied mini-model assessment is capped and the library never calls a provider itself.

The included 30-card fixtures validate the pipeline, while the repository's results/complexity-backtest snapshot reports a real-card observational replay. Its cohort and measurement limitations—and weak current accuracy—make it calibration evidence, not a routing-readiness or causal model-comparison claim. See the complexity design and backtest contract.

Token usage, made visible

Where the tokens actually went: per model, per task class, per retry, and across one measured session. Every bar is computed from checked-in evidence in this repository — measured runs, real card history, and list prices resolved from the dated catalog. Nothing here is illustrative, and an unpriced model stays unpriced.

Loading published token evidence…

Source: website/data/token-usage.json, generated by scripts/generate-website-data.py from the append-only cases under benchmarks/results/, the card backtest snapshot in results/, and the session analysis in docs/analyses/. Dollar figures are list prices from src/TokenEconomy/catalog/model-prices.json resolved at each run's own timestamp; a unit test re-costs the published file through ComputeCost so the site cannot drift from the library. The four token components are mutually exclusive — cache reads are never added to input a second time.

Benchmarks

Published runs are controlled local comparisons: each variant receives the same prompt and a fresh fixture, then a deterministic command evaluates the response. They are not provider-wide capability claims.

How these studies map to established benchmarks

This harness borrows the test-verified repair shape of SWE-bench and the focused function-correctness shape of HumanEval. Its fixtures are local, deliberately small, and versioned for routing calibration; they are not SWE-bench or HumanEval submissions, and their results are not comparable to either leaderboard.

Local study shapeEstablished referenceWhat carries overWhat does not
Repository repair with a deterministic test commandSWE-benchA reproducible starting repository, a stated task, and test-verified evaluation.Task distribution, repository scale, and leaderboard comparability.
Focused response-artifact correctnessHumanEvalA small, deterministic correctness target for comparing variants.HumanEval problems, pass@k protocol, and capability claims.
Document-to-text hard casesNone claimedVersioned inputs and explicit positive/negative extraction oracles.A general document-understanding benchmark or support guarantee.

Loading published benchmark evidence…

The raw run and derived report are append-only JSON. The displayed table is rendered from a deployable projection generated from those files. To add a study, commit a setup in benchmarks/setups/, its minimal fixture, and generated raw + report files in benchmarks/results/; then run python scripts/generate-website-data.py. See the benchmark protocol on GitHub.

Project status

A precise snapshot of what this repository currently contains. Status is intentionally narrower than a product roadmap and is rendered from the versioned site status record.

Loading project status…

Benchmark results measure the specified setup at the recorded time. They do not silently alter SuggestModel, publish raw operational data, or claim provider limits.

Prices have history

Each model carries a list of ModelPrice entries, each effective from a ValidFrom instant (inclusive, UTC). Resolution picks the entry with the greatest ValidFrom that is not after the run's timestamp — so a run last month is costed at last month's rate, even after a price change. A change adds a new entry; it never edits the old one.

The seeded catalog captures a real, dated change: Claude Sonnet 5 runs on an introductory rate now and switches to standard pricing on 2026-09-01 (UTC). The same run, same model is priced differently on either side of that boundary:

Run timestamp (UTC) Price entry in effect Input /MTok Output /MTok Cost of 1M in + 200K out
2026-07-10 Introductory $2.00 $10.00 $4.00
2026-10-01 Standard $3.00 $15.00 $6.00
using TokenEconomy;

var catalog = ModelPriceCatalog.Default;
var usage   = new TokenUsage(Input: 1_000_000, Output: 200_000);

var intro    = new DateTime(2026, 7, 10, 0, 0, 0, DateTimeKind.Utc);
var standard = new DateTime(2026, 10, 1, 0, 0, 0, DateTimeKind.Utc);

catalog.ComputeCost("claude-sonnet-5", usage, intro).Total;    // 4.00 (introductory rate)
catalog.ComputeCost("claude-sonnet-5", usage, standard).Total; // 6.00 (standard rate, from 2026-09-01)

Model ids and aliases resolve case- and dot/dash-insensitively, so claude-opus-4.8, gpt-5-6, and dated snapshots all match their canonical listing.

Cost API

Feed a TokenUsage and a UTC instant to ComputeCost; get back a CostBreakdown with per-component costs and a nullable Total. Cache tokens are priced with Anthropic's documented economics — cache-read at 0.1× input, cache-write at 1.25× input (5-minute TTL).

using TokenEconomy;

var breakdown = ModelPriceCatalog.Default.ComputeCost(
    "claude-opus-4-8",
    new TokenUsage(Input: 250_000, Output: 12_000, CacheRead: 40_000),
    DateTime.UtcNow);

if (breakdown.HasPrice)
    Console.WriteLine($"{breakdown.Total} {breakdown.Currency}");  // ≈ 1.57 USD
else
    Console.WriteLine(breakdown.Status);  // UnknownModel or NoPriceForDate — never a silent $0
Missing prices are explicit, never zero. An unknown id resolves to PriceStatus.UnknownModel; a known-but-unpriced model to PriceStatus.NoPriceForDate. In both cases CostBreakdown.Total is null — a missing price can never masquerade as a free run.

The breakdown

  • InputCost / OutputCost / CacheReadCost / CacheWriteCost — per-component decimals.
  • Total — the sum, or null when no price applied.
  • HasPrice — true only when a concrete price was used.
  • Unconfirmed — true when the applied rate is a not-yet-confirmed placeholder, so callers can surface the caveat instead of trusting it silently.

Need only the rate, not a cost? ResolvePrice(model, atUtc) returns the ModelPrice in effect (or the reason none applied) without any token counts.

Picking a model — SuggestModel

The selection axis: given a task class, the current budget pressure, and the CLIs that have quota right now, rank the models you could actually launch — best first — each with a score, a suggested reasoning effort, and an auditable rationale string.

using TokenEconomy;

// A plain feature, budget getting tight, only the Claude CLI has quota right now.
var ranked = ModelEfficiencyMatrix.Default.SuggestModel(
    TaskClass.Feature,
    BudgetPressure.Tight,
    availableClis: [Cli.Claude],
    atUtc: DateTime.UtcNow);

var best = ranked[0];  // empty list ⇒ nothing available: wait, don't launch
Console.WriteLine($"{best.ModelId} @ {best.SuggestedEffort} — {best.Rationale}");
// claude-sonnet-5 @ Medium — claude-sonnet-5: balanced tier, an ideal match for
// feature work; standard cost — moderate spend under tight pressure. Suggested effort: medium.
Capability fit leads; budget pressure tips the balance toward cheaper models (a downshift) — but never lets an underpowered model outrank a capable one. Restricted (private-project) and deprecated models are never suggested, and a CLI that isn't in your available set drops out with no launch attempt. An empty result means "wait", not "launch something bad".

How it decides

  • Task classHeavyDesign, Feature, MechanicalChore, DocEdit, Research.
  • Capability tierLight / Balanced / Frontier, rated against the task into a Suitability.
  • Cost classEconomy / Standard / Premium, derived by costing a fixed reference workload through the pricing catalog. An unpriced model is Unknown, never a guessed band — and because the derivation runs through price history, cost class tracks changes over time.
  • Rationale — a one-line English string meant to travel verbatim into the orchestrator's decision event and transparency view.

Describe(atUtc) renders the whole matrix as inspectable rows — tier, cost class, effort levels, and suitability for every task class. The matrix is data + pure functions; the policy of when to downshift, throttle, or wait stays in the caller's admission algorithm, by design.

Forecast each task against the five-hour cap

A research plan for estimating every candidate model's share of one effective five-hour quota window — with a prediction range, confidence, calibration age, and current headroom shown separately. It tackles the hard parts: opaque provider limits, rolling windows, parser glitches, and unknown task demand.

Plan only — operator GO required. The concept and proposed slices are documented for review; no estimator, card metric, or admission behavior is implemented.

Install

Dependency-free, targets net10.0, ships XML docs and a symbol package. Apache-2.0.

# package reference
dotnet add package TokenEconomy

# or pin a version
dotnet add package TokenEconomy --version 0.2.0
using TokenEconomy;

// The seeded catalog: known Claude 4.x/5 and OpenAI gpt-5.x models.
var catalog = ModelPriceCatalog.Default;
var matrix  = ModelEfficiencyMatrix.Default;  // cost is derived from the same catalog

Building your own set? Construct a ModelPriceCatalog from your own ModelListings and a ModelEfficiencyMatrix from your own profiles over it.