Before this change the broker never knew what a run actually cost. It
guessed: it multiplied token counts by a hand-typed price table of three
models. Every other model in the Mira/Vega roster
(qwen, minimax, seed,
gemini-flash-lite, deepseek-v4-pro) fell through to a
deliberately-high $5 / $25-per-1M fallback. For a cheap model
that is roughly an 18x over-estimate. Two things break from
that single lie:
aborted_cost.
The brain already knows the truth: OpenRouter returns
provider_details['cost'] per call. Story A1 (brain) started
stamping that real number onto the model.usage event as
cost_usd. This story makes the broker read it.
brain (OpenRouter real cost)
-> model.usage event { input_tokens, output_tokens, model_id, cost_usd }
-> broker accumulates totals.cost_usd
|-> cost cap check (abort if over the per-route cap)
|-> per-firm credit debit (record_run_debit)
Both the cap and the debit read the same accumulator,
totals.cost_usd. So there is exactly one place to fix:
what we add to that accumulator per model.usage event.
| Surface | Change |
|---|---|
ModelUsagePayload (agent_contracts/events.py) |
Adds cost_usd: float | None. Mandatory: the wire base is
extra="forbid", so once the brain emits the field, an
unaware broker would reject the whole event and fail the run.
Optional-with-default keeps old streams parsing. |
_usage_cost_usd() (clerk_worker/runner.py) |
New helper. Returns payload.cost_usd when present. When
null, falls back to the static estimate and fires the
billing_cost_fallback counter + a loud
logger.warning. The model.usage handler now adds
_usage_cost_usd(event.payload) to totals.cost_usd. |
pricing.py |
The hand-priced _MODEL_PRICING table is deleted.
token_cost_usd is now the flat conservative-high fallback
only, renamed _FALLBACK_PRICING and documented as
"not the price source". |
pramaan.billing.cost_fallback (observability/metrics.py) |
New registry-backed counter + emit_billing_cost_fallback.
Any non-zero rate means the brain stopped reporting cost - alarm on it. |
The fallback path is designed to be loud, not silent. If it ever
runs in production it means the brain regressed and billing quietly went back
to guessing. So it does three things at once - bill conservative-high (never
free), emit an alarmable counter tagged by model_id, and log a
warning - so the regression surfaces before the next invoice does.
One shared OpenRouter key carries one global provider rate limit, so a heavy firm's burst can throttle others at the model layer. Accepted for the pilot; backstopped by the per-run cost cap and the per-firm circuit breaker. Revisit at >=10 firms or the first observed cross-firm throttle. No per-firm key/rate-limit is built here.
uv run ruff check src/shared/agent_contracts/pricing.py src/shared/agent_contracts/events.py src/shared/observability/metrics.py src/clerk_worker/runner.py uv run pytest tests/unit/agent_contracts tests/unit/clerk_worker tests/unit/shared/observability -q
Key assertions: test_real_event_cost_is_primary_not_token_estimate
(a $0.50 real cost on a 1-token call breaches a $0.10 cap - only possible if
the real number is read) and
test_missing_event_cost_falls_back_and_increments_counter
(no cost_usd -> static estimate + counter fires once, tagged by
model).
In one sentence: the broker now bills the provider's real cost and only guesses when forced to - loudly.