Know what each client and case costs in model calls
Every model call is attributed to the organization and the case it served, so a firm can see what a case cost, close each month into a total and link that total to the invoice that bills it.
- What it is
- Mechanism — something you declare.
- What it does
- One attribution per call. A call that served one case produces one row; an embedding batch that served several rows of one organization is split between them by input length. A call made outside any piece of work still produces a row, marked as unattributed, so every call is accounted for.
- What you decide
- Name the case a turn works on, register prices for the models you use, and link monthly totals from your billing flow when you invoice the cost.
- Where it stops
- Splitting one embedding batch between several organizations has not yet been observed against a real embeddings provider.

Each call to a language or embedding model is recorded against the organization it served and, when the work names one, the case: the record, matter or ticket being worked on. A billing manager can then ask what a case, a client, an agent or a model cost over a period, and each month closes into one total per client that an invoice can point to.
The problem it solves
A firm that sells finished work instead of seats needs to know its margin per piece of work. The vendor’s bill says what the whole application spent, not which client or which case caused it. A total that silently drops the calls it could not attribute looks complete and is too low.
What it does
One attribution per call. A call that served one case produces one row; an embedding batch that served several rows of one organization is split between them by input length. A call made outside any piece of work still produces a row, marked as unattributed, so every call is accounted for.
Exact cost, rounded once. When a registered price applies, the row stores the call’s exact cost without rounding. A reported total is rounded once, from the exact sum, rather than adding up already-rounded amounts.
An honest summary. The summary groups by case, organization, agent or model, per currency, and states how many calls in the window could not be attributed or priced. It is readable only by the application’s super-administrator or billing manager: it is the firm’s internal margin data, and an organization administrator never sees it.
Monthly totals that an invoice can cite. After a month ends and a grace period passes, a scheduled close writes one total per organization, month and currency. Calls that no price covered are totalled under a separate “no currency” slot rather than disappearing. Running the close again changes nothing. The billing flow links a total to the invoice that bills it, once.
Deletion keeps what the law needs. The detail rows are operational records and go with the organization. When an organization is deleted, its open month is closed first. A monthly total linked to an invoice is kept for the statutory bookkeeping period; one no invoice cites is deleted.
No personal data. The rows hold identifiers, counts and amounts: no prompt, no output, no user.
What you decide
Name the case a turn works on, register prices for the models you use, and link monthly totals from your billing flow when you invoice the cost.
Wonder Todos treats a todo as its case. Selected from todos.resources-config.ts; the rest of the resource configuration is omitted.
/**
* A todo is Wonder Todos' CASE (#1598): the unit of work its assistant and its autonomous agents spend model calls
* on. Every model call made while working on a todo — an operation on it, a turn opened on it, a job enqueued from
* it — is attributed to the todo and to its organization, so the application can summarize its cost per todo.
*/
workUnit: true,
A case is a row of a resource declared workUnit: true, and an agent turn names the todo it works on as its case.
It registers one price in its backend configuration. Selected from saas-config.backend.ts; the explanatory comment above the section is omitted.
modelCostAccounting: {
providerUsagePricingAuthorities: [{
schemaVersion: 1,
pricingAuthorityRef: 'pricing:wonder-todos/anthropic/claude-sonnet-5',
pricingAuthorityVersion: 1,
providerRef: 'anthropic',
model: LLM_Model.CLAUDE_SONNET_5,
currency: 'USD',
unitsDenominator: 1_000_000,
roundingMode: ProviderUsagePricingRoundingMode.CEILING_AGGREGATE_TO_MINOR_UNIT,
rates: [
{ category: ProviderUsagePricingCategory.INPUT_TOKEN, amountMinorNumerator: 300 },
{ category: ProviderUsagePricingCategory.CACHED_INPUT_TOKEN, amountMinorNumerator: 30 },
{ category: ProviderUsagePricingCategory.CACHE_WRITE_INPUT_TOKEN, amountMinorNumerator: 375 },
{ category: ProviderUsagePricingCategory.OUTPUT_TOKEN, amountMinorNumerator: 1_500 },
],
usageTierRules: [],
effectiveFrom: '2026-01-01T00:00:00.000Z',
sourceRef: 'wonder-todos:test-price',
sourceVersion: '2026-09-27',
}],
periodCloseGraceDays: 3,
},
A price applies to one provider and model, in one currency, and each rate is a number of minor units per unitsDenominator billable units: here, cents per million tokens, by token category. These are Wonder Todos’ own test numbers, not the provider’s list price. periodCloseGraceDays is how many days after a month ends its totals are written.
Limits
Splitting one embedding batch between several organizations has not yet been observed against a real embeddings provider.
A cost is computed only for a model whose price is registered. Calls to any other model are counted, not priced.