Specification · v0.2 (draft) · CC BY 4.0
Turn Accounting
Version: 0.2 (draft) Date: 3 August 2026 Editor: Yacine — Code75 Licence: specification text under CC BY 4.0; conformance suite under Apache-2.0 Status: draft for comment. Nothing here is stable until 1.0.
Editor's disclosure: the editor is the author of tack, one of the implementations listed in §13. This document is licensed and governed so that it can be adopted against tack. If any rule in this specification can only be satisfied by tack, that rule is a defect — report it.
On this draft. This specification was drafted and then revised against an audit of a production system before publication, rather than published on reasoning alone. Three rules earned their place by catching real defects in that audit: unknown is not zero found ambiguous zero-cost rows; the explicit-currency rule found an implicit currency on the cost side against a different one on the purchase side; the refusal-recording rule found that refused turns were not being written at all. Six gaps in the specification itself were found and closed, and one rule was found over-specified and relaxed. A rule that has never met an implementation is a hypothesis.
v0.2 was revised against a second audit of a different kind: a from-scratch implementation of this unit, reviewed at design time. That review caught a sequencing defect before it was built — a paid routing operation placed ahead of the admission gates, so that a refused turn would have already spent provider money — and the pre-admission rules in §4.3 and §6.7 exist because of it. Design-time review is where these rules are cheapest to apply; the defect they catch is the same either way.
0. Scope
In scope. How to define, bound, record and count a turn as a unit of cost, so that a cost-per-turn figure means the same thing across two independent systems.
Out of scope. Tenant isolation, access control, data residency, model quality, latency objectives, and pricing guidance. This specification says how to count. It does not say what to charge.
A narrow specification gets adopted. A broad one gets read.
1. Motivation
Providers price inference in tokens. Nobody operates a product in tokens.
A single user-facing exchange in an agentic system is not one model call. It is an admission check, one or more retrieval legs, a loop of model calls interleaved with tool executions, one or more guardrail evaluations, occasional retries, and an emission. The tokens are a component of that cost. They are not the cost — and on many workloads they are not even the largest component, once the tools the agent actually calls are counted.
The consequence is that the industry has no comparable unit. Two vendors can both publish a cost per interaction and mean entirely different things — one counting a single model call, the other counting the full loop; one excluding refusals, the other including them; one counting only inference, the other counting the paid APIs the agent invoked; one measuring a component, the other estimating it; one reporting a mean, the other a median. Neither is lying. The figures are simply not comparable, which makes them useless for procurement, for margin modelling, and for public benchmarking.
Cost-per-completed-task, cost-per-resolution and cost-per-trace all circulate as concepts. What is missing is not the idea. It is the definition: what counts as one, what does not, how the money is represented, how confident the numbers are, and what must be published alongside them for them to mean anything.
This document supplies that definition.
2. Terminology
The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be interpreted as in RFC 2119.
turn — the unit defined in §3.
submission — the point at which a caller hands work to the system. May be followed by queueing.
admission — the point at which the system accepts a submitted unit of work for execution, after gate checks. Admission, not submission, opens a turn.
emission — the point at which the system delivers its response to the caller, or terminates without one.
component — a cost-bearing operation inside a turn: an inference call, a guard evaluation, a retrieval leg, a tool execution, an infrastructure operation.
gate — a pre-execution check that may prevent a turn from being admitted: balance, policy, class availability, envelope.
payer — the account to which a turn's cost is attributable.
On the choice of word. Several terms are in circulation for approximately this unit: run, invocation, task, interaction, trace, request, exchange, episode. This specification uses turn and treats the others as synonyms where they denote the same boundary. An implementation MAY use any label in its own interface and still claim conformance, provided the boundary it uses is the one defined in §3. Conformance is about the boundary, not the vocabulary.
3. The turn
A turn is one bounded unit of work, from admission to emission, including every component required to produce that emission.
3.1 Boundary
- A turn MUST begin at admission and end at emission.
- A turn MUST include all components executed between those two points, regardless of how many model calls, tool executions, guard evaluations or retrieval legs occur.
- A turn MUST NOT be split per model call. A loop of six tool-augmented model calls producing one response is one turn.
- A turn is not tied to a human message. Work initiated by a schedule, an event, or another system is a turn.
- A turn MUST have exactly one outcome (§5.3).
3.2 The counting rule
One emission, one turn.
Everything the system had to do to reach that emission belongs to it. This is the entire specification in one line; §4 is the application of it to cases where the answer is not obvious.
3.3 The decomposition rule
- A turn MUST have a single total cost.
- That total MUST decompose into components, and the components MUST sum to the total without residual (§6.2).
- Any figure presented to a payer MUST be derived from the same record as the figure presented to an operator. Two independently computed numbers for one turn is a conformance failure even when they happen to agree.
This rule exists because a developer asks where did the cost go and a buyer asks how much and is it stable. They are entitled to different views. They are not entitled to different numbers.
3.4 Attribution and orphans
Every cost-bearing operation performed in service of a turn MUST carry that turn's identifier.
- A cost-bearing record that has neither a parent turn identifier nor an emission of its own is an orphan. An orphan MUST NOT be counted as a turn.
- Implementations MUST be able to report an orphan rate: cost-bearing records not attributable to any turn, as a proportion of total cost and of total records.
This rule exists because orphaned components bias the unit twice in the same direction: the parent turn's cost is understated, and the turn count is inflated by records that were never turns. Cost per turn is then wrong in both the numerator and the denominator, and no other test in this specification detects it. Guard evaluations, embedding calls and retries that mint their own identifiers instead of inheriting the parent's are the common cause.
4. Edge cases (normative)
The rulings below follow from §3.2. They are enumerated because implementations diverge here, and divergence here is what makes figures incomparable.
4.1 Loop and retry
| Case | Ruling | Rationale |
|---|---|---|
| Loop of N model calls with tool execution between them, one response | One turn, iterations = N | One emission |
| Several tool calls issued in parallel within one model round-trip | One iteration, tool_calls counts each call | iterations counts model round-trips; tool_calls counts calls. The two are not interchangeable |
| Model retries a tool after a tool error | Same turn | No new emission |
| Provider-level retry after a failed attempt (timeout, 5xx, malformed response) | Same turn; provider_attempts incremented; tokens burned on the failed attempt MUST be counted where the provider reports or charges for them | No new emission, but money was spent |
| Best-of-N, speculative or parallel sampling where one completion is kept | One turn; all N completions counted in cost | The discarded completions were paid for |
4.2 Supporting components
| Case | Ruling | Rationale |
|---|---|---|
| Guardrail / judge evaluation before emission | Same turn, own cost component, MUST carry the parent turn identifier (§3.4) | Required to reach the emission |
| Retrieval and embedding calls | Same turn, own cost component, MUST carry the parent turn identifier (§3.4) | Required to reach the emission |
| Tool execution with an external monetary cost (paid API, SMS, payment fee) | Same turn, tool_execution component (§5.2) | End-to-end means end-to-end |
| Tool result served from a memoised or cached store | Cost attributed to the turn that caused the original external call; the reusing turn records the call in tool_calls at zero cost | Symmetric with the cache rule below |
| Context compaction or summarisation triggered during the turn | Same turn, own cost component | Caused by this turn |
| Context compaction run as scheduled maintenance | Separate turn, class maintenance | Its own admission, no caller emission |
| Cache write | Attributed to the turn that caused the write | Otherwise later turns are silently subsidised by an earlier one |
| Cache read | Attributed to the turn that read it, at the read rate | Direct attribution |
4.3 Outcomes other than success
| Case | Ruling | Rationale |
|---|---|---|
| Refused at admission (insufficient funds, unavailable class, policy, envelope) | One turn, outcome = refused, MUST be recorded, MUST NOT be billed. cost_total = 0 where admission is zero-cost — the normal case; see the pre-admission row | Refusal is an outcome, not an absence |
| Cost-bearing operation performed between submission and admission (routing, selection embedding, paid pre-admission evaluation) | Belongs to the turn. If the turn is then refused, those components MUST be recorded with their cost, and cost_total MUST equal their sum | Money spent in service of a turn is that turn's cost; hiding it under a zero corrupts the refusal distribution the same way an unrecorded refusal corrupts the success one |
| Guard or policy verdict stops the turn after admission, before or during emission | One turn, outcome = refused; cost incurred MUST be counted; billability MUST be declared | The system declined; the spend is real |
| Gate evaluated in shadow mode: refusal logged but execution proceeds | Not a refusal. The turn's real outcome is recorded, and gate_mode = shadow is declared (§6.7) | A gate that does not stop spending has not refused anything |
| Submitted work expiring in queue before admission | One turn, outcome = refused, reason refused_expired, cost_total = 0 | The caller is entitled to know it did not run |
| Failure after admission, before emission | One turn, outcome = failed; cost incurred MUST be counted; billability MUST be declared | Money was spent |
| Streaming response interrupted by the caller | One turn, outcome = interrupted; cost incurred up to interruption counted | Emission began |
| Turn re-executed after a system-side defect (replay, incident recovery) | New turn, billable = false, reason replay_system_defect | The payer did not ask twice |
4.4 Composition and boundaries
| Case | Ruling | Rationale |
|---|---|---|
| Human-in-the-loop pause, then resumption | Two turns | The pause is an emission |
| Sub-agent or delegated agent invoked within a turn | Same turn by default; components attributed to the parent. If recorded separately, child records MUST carry parent_turn_id and MUST NOT be double-counted in totals | One emission |
| Sub-agent invocation crossing a payer boundary | Separate turn per payer | Cost must be attributable to exactly one payer |
| One call processing a batch of N items | One turn | The unit is the invocation boundary, not the payload |
| N items dispatched as N calls | N turns | N emissions |
| Same logical conversation continued across channels | Separate turns | Emission boundary, not conversation boundary |
| Turn spanning a provider or internal price change | Rates fixed at admission and MUST NOT be re-derived later (§6.1, §6.3) | A committed record does not change retroactively |
An implementation encountering a case not listed here MUST resolve it by §3.2 and SHOULD report it for inclusion in a later version.
5. The canonical turn record
5.1 Required fields
| Field | Type | Notes |
|---|---|---|
record_type | enum | turn or correction (§6.4) |
turn_id | opaque string | Unique |
parent_turn_id | opaque string, nullable | Per §3.4 and §4.4 |
corrects_turn_id | opaque string, nullable | Required when record_type = correction |
idempotency_key | opaque string, nullable | §6.5 |
payer_id | opaque string | MUST be opaque — this specification requires no identity data |
class | string | Implementation-defined; MUST be published (§10) |
class_basis | enum | model_derived, shape_derived, or customer_selected. §5.7 |
gate_mode | enum | enforcing, shadow, or absent. §6.7 |
submitted_at / started_at / ended_at | timestamp | Submission, admission, emission |
outcome | enum | §5.3 |
billable | boolean | |
billable_reason | enum | Required when billable = false. §5.4 |
cost_total | decimal | §6.2 |
cost_currency | ISO 4217 | §6.1 |
cost_components | map | Each entry carries a value and a provenance. MUST sum to cost_total (§3.3). §5.2 |
cost_completeness | enum | complete or partial. Derived from component provenance. §5.2 |
fx | object, nullable | Required when any component was incurred in another currency. §6.1 |
counters | map | §5.5 |
models_used | array | Vendor, model identifier, and route, per inference component |
price_charged | decimal, nullable | Null at Level 1 |
price_currency | ISO 4217, nullable | |
record_version | string | This specification version |
Recommended fields. conversation_id and turn_index (the turn's ordinal position within its conversation) SHOULD be recorded. Without them, cost growth as a function of conversation age — the single largest source of cost drift in long-lived threads — cannot be measured.
5.2 Cost components and provenance
The following component keys are defined. An implementation MUST populate every component it has knowledge of.
inference_input_uncached · inference_input_cached_read · inference_cache_write · inference_output · inference_reasoning · guard · retrieval · tool_execution · infrastructure
tool_execution is required, and it is the component most often omitted. An agent that sends messages, calls a paid enrichment API, or triggers a payment incurs real cost outside inference. On many production workloads it exceeds the model cost. An end-to-end unit that excludes it is not end-to-end.
Each component MUST carry a provenance:
| Provenance | Meaning |
|---|---|
known | Derived from a figure the provider reported or charged |
estimated | Derived by the implementation's own approximation. estimation_method is REQUIRED |
unknown | The implementation cannot determine it |
- An
estimatedvalue MUST NOT be presented as measured, in any interface or export. - An
unknowncomponent MUST NOT be recorded as zero. Recording an unknown cost as zero corrupts every figure built on it. A partial record is honest; a silently zeroed one is not. cost_completenessiscompleteonly when every populated component isknown.
Provenance exists because implementations legitimately estimate components a provider does not break out — for example a reasoning-token share inferred from returned text where the provider bills it inside output tokens. Estimation is acceptable. Estimation indistinguishable from measurement is not.
infrastructure (queue, storage, egress, compute overhead) is OPTIONAL — see §15.
5.3 Outcomes
emitted · refused · failed · interrupted
Every turn MUST carry exactly one. The three non-emitted outcomes are distinguished by who stopped the turn: refused — the system declined, before or after admission; failed — the system attempted and broke; interrupted — the caller stopped it. A stop that fits none of these is a gap in this specification and SHOULD be reported.
Refusals and failures MUST be recorded with the same fidelity as successes. A system that only records successful turns cannot support a cost-per-turn figure, because its denominator is unknown — see §6.8.
5.4 Billable reasons (closed enum)
refused_insufficient_funds · refused_policy · refused_class_unavailable · refused_envelope_exceeded · refused_expired · failed_system · failed_provider · interrupted_by_caller · replay_system_defect · promotional · correction · other
other MUST be accompanied by a free-text billable_note, and SHOULD be reported for inclusion in a later version. Free text alone is not conformant: a reason that cannot be aggregated across implementations defeats the purpose of the field.
5.5 Required counters
iterations · tool_calls · provider_attempts · input_tokens · cached_input_tokens · cache_write_tokens · output_tokens · reasoning_tokens · retrieval_legs
iterationscounts model round-trips.tool_callscounts individual tool invocations, including those issued in parallel within one round-trip. The two MUST NOT be conflated, anditerationsMUST NOT be derived arithmetically fromtool_calls.provider_attemptscounts calls issued to a provider including failed attempts that were retried. Without it, a turn that succeeded on its third attempt is indistinguishable from one that succeeded immediately, and the cost of the first two is invisible.reasoning_tokensMUST be recorded separately fromoutput_tokenswhere the provider distinguishes them. Where the provider does not, the counter MAY be omitted, or populated with provenanceestimatedand a declared method. Reasoning budget is the largest source of cost variance within a fixed class and is invisible if silently folded into output.- A retrieval leg is one ranked candidate list produced against one index or modality. Legs are counted the same whether they execute as separate requests or as sub-queries fused server-side inside a single request: a hybrid query with a lexical and a semantic sub-query is
retrieval_legs = 2, regardless of transport.
5.6 Model attribution
models_used MUST reflect what actually served the turn, including any substitution or failover. A system that presents a class abstraction to its customers MAY hide the model in its pricing, but MUST NOT hide it in the record. A silent model substitution defeats the purpose of an auditable unit.
5.7 Class basis
class_basis declares how a turn's class was determined:
model_derived— class follows from which model served the turn.shape_derived— class follows from measurable properties of the work (context size, iteration ceiling, tool budget).customer_selected— the payer chose the class.
This specification does not prefer one basis over another. It requires the basis to be declared, because a model_derived class makes cross-vendor cost comparison circular: the class is defined by the thing being compared. A reader cannot interpret a per-class figure without knowing which basis produced it.
6. Accounting primitives
A unit of account requires more than a definition of the unit. This section defines how the money is represented, corrected, retained, gated and covered.
6.1 Currency and conversion
- Every monetary field MUST carry an explicit ISO 4217 currency. There is no default currency.
cost_currencyandprice_currencyMAY differ. Both MUST be present when both values are present.- Where any component was incurred in a currency other than
cost_currency, the record MUST include anfxobject with:rate,from_currency,to_currency,rate_source, andrate_at. - The rate MUST be the rate in effect at admission, and MUST NOT be re-derived at invoicing time or at any later point. A committed record does not move because a rate moved.
- A fixed internal margin multiplier, a credit conversion rate, or any other business ratio MUST NOT be recorded in the
fxobject. It is not an exchange rate.
6.2 Precision and rounding
- Monetary values MUST be represented as decimal. Binary floating point MUST NOT be used for any monetary field.
- Stored precision MUST be sufficient that components sum to the total without residual at stored precision. An implementation whose precision is too coarse to satisfy §3.3 is non-conformant; one that satisfies it at four decimal places is conformant.
- Components MUST NOT be rounded individually before summation. The total is computed at full precision and rounded once, if at all.
- Where rounding is applied, the mode MUST be round-half-to-even.
- A rounded value presented in an interface or invoice MUST NOT be re-decomposed. §3.3 is tested against stored precision, not presented precision.
6.3 Immutability
- A written turn record MUST NOT be mutated or deleted.
- This applies to every field, including
billable. A turn later judged non-billable is corrected under §6.4, not edited.
6.4 Corrections
- An error in a written record MUST be corrected by appending a record with
record_type = correctionandcorrects_turn_idset to the original. - A correction record carries the delta, not the restated total.
- A payer's balance for a period is the sum of their billable turn records and all correction records referencing them.
- Correction records MUST carry
billable_reason = correctionwhere they reverse a charge. - Where a provider reports usage or cost asynchronously after emission, the delta MUST be applied as a correction record. The original record MUST NOT be revised, upward or downward. Late-arriving truth is still a correction, not an edit.
This is the same discipline as a reversing journal entry, and it is what makes a ledger auditable rather than merely current.
6.5 Idempotency
- A submission MAY carry an
idempotency_key. - Where a key is supplied, an implementation MUST NOT create more than one turn for that key within a declared idempotency window, and MUST return the original record on replay.
- The idempotency window MUST be published.
Without this, a retried client submission produces two turns and charges twice. Idempotency is a billing property, not only a transport convenience.
6.6 Retention
- The minimum retention period for turn records MUST be published.
- At Level 2 and above, retention MUST be at least as long as the period during which a payer may dispute an invoice.
- Records MUST remain retrievable in their original form for the whole retention period. Aggregation is not retention.
6.7 Gate mode
Where the implementation operates a gate (§2), it MUST declare the gate's mode:
| Mode | Meaning |
|---|---|
enforcing | A gate decision to refuse prevents execution and prevents spending |
shadow | A gate decision to refuse is recorded, but execution proceeds and money is spent |
absent | No gate |
- In
shadowmode, a logged refusal MUST NOT be recorded asoutcome = refused(§4.3). The turn's real outcome is what happened. - Level 3 REQUIRES
enforcing. A gate that does not stop spending is not a commitment, and a system running in shadow mode cannot claim to be unable to spend money it has not collected. - Gate checks SHOULD be zero-cost operations. An implementation whose admission decision itself requires a paid evaluation MUST attribute that spend to the turn per §4.3, including on the refusal path. Sequencing paid work ahead of free gates is the defect this rule exists to catch: it makes every refusal quietly more expensive than its record claims.
Shadow mode is a legitimate rollout state. Declaring it is what makes it legitimate.
6.8 Record coverage
No test in this specification can detect a record that was never written. Absence is invisible from the inside.
- An implementation MUST maintain a count of terminal outcomes that is independent of the turn record store — for example, a counter incremented at each exit path in the execution pipeline.
- Record coverage is the ratio of turn records written to terminal outcomes counted.
- Coverage MUST be published alongside any cost-per-turn figure (§10).
- Level 2 REQUIRES coverage of 100%.
Systems that only write a record on the success path exhibit high apparent data quality and a silently truncated distribution: every percentile is computed over survivors. This is the most common and least visible failure of turn accounting, and coverage is the only measurement that reveals it.
7. Conformance levels
Three levels. Each is a superset of the one before. Levels are self-declared and MUST be substantiated by §8.
Level 1 — Measured
- Every turn produces a record per §5.
cost_totaldecomposes per §3.3, without residual at stored precision (§6.2).- Every component carries a provenance; estimated components declare a method (§5.2).
- Currency is explicit (§6.1); records are immutable and corrected by compensation (§6.3, §6.4).
- Cost-bearing components carry the parent turn identifier; the orphan rate is reportable (§3.4).
- Cost MAY be computed after the fact.
- No claim is made about billing.
Typical: observability platforms, gateways with per-customer cost reporting, internal instrumentation.
Level 2 — Counted
Level 1, plus:
- The turn is the unit the payer is charged in.
- The charged amount is derived from the turn record, not computed independently from it.
- Refusals are recorded at zero cost and are not charged.
- Record coverage is 100% (§6.8).
- Class definitions,
class_basis, and envelope limits are published (§10). - Idempotency window and retention period are published (§6.5, §6.6).
Typical: products billing per interaction, resolution, or task.
Level 3 — Committed
Level 2, plus:
gate_mode = enforcing(§6.7).- Funds are reserved before execution and the reservation is checked at admission.
- The usage record and the balance movement are committed in a single atomic transaction.
- Every reservation resolves to exactly one of: commitment, or release. No reservation outlives its turn.
- The reconciliation invariants in §8 T21–T23 hold continuously and are testable.
Level 3 is the difference between a system that reports what it spent and a system that cannot spend what it has not collected.
8. Conformance suite
An implementation claiming a level MUST pass all tests at that level and below.
| ID | Level | Assertion |
|---|---|---|
| T1 | 1 | For every record, cost_components sums to cost_total without residual at stored precision |
| T2 | 1 | No monetary field is stored in binary floating point; all carry an explicit currency |
| T3 | 1 | Every populated component carries a provenance; every estimated component carries an estimation_method |
| T4 | 1 | No component with provenance unknown is stored as a zero value; cost_completeness is partial whenever any component is not known |
| T5 | 1 | Every record carries exactly one outcome and a billable flag; billable_reason is drawn from the closed enum |
| T6 | 1 | A turn executing N > 1 iterations produces exactly one record with iterations = N, and iterations is not a function of tool_calls |
| T7 | 1 | A turn issuing M parallel tool calls in one round-trip records iterations = 1, tool_calls = M |
| T8 | 1 | A turn that succeeded after R failed provider attempts records provider_attempts = R + 1 |
| T9 | 1 | Every cost-bearing record carries a parent turn identifier or its own emission; the orphan rate is computable |
| T10 | 1 | A sub-agent record, if separate, carries parent_turn_id and is not double-counted in any total |
| T11 | 1 | models_used reflects the model actually served, including under failover |
| T12 | 1 | Where currencies differ, fx.rate_at equals the admission timestamp and the rate is unchanged by later re-reads |
| T13 | 1 | A correction appends a record referencing the original; the original is byte-identical before and after |
| T14 | 1 | class_basis is populated on every record |
| T15 | 2 | A refused turn is recorded with billable = false; its cost_total equals the sum of its recorded components — zero where admission is zero-cost — and no cost-bearing component postdates the refusal decision |
| T16 | 2 | Record coverage equals 100%: the independent terminal-outcome counter matches the count of turn records for the same window |
| T17 | 2 | For any period, the amount charged to a payer equals the sum of that payer's billable turn records plus corrections referencing them |
| T18 | 2 | A turn exceeding its published class envelope produces the published behaviour, and the record states which |
| T19 | 2 | A replayed submission carrying a previously seen idempotency_key produces no second turn and returns the original record |
| T20 | 3 | gate_mode = enforcing: a refused turn results in no downstream provider spend |
| T21 | 3 | For every reservation, exactly one of {commitment, release} exists |
| T22 | 3 | No reservation exists older than its declared time-to-live |
| T23 | 3 | A turn failing after reservation and before emission results in a release, not an orphaned reservation |
| T24 | 3 | The usage record and the balance movement share a transaction identifier |
T16 is the test most implementations will fail without noticing, because it is the only one that measures what is absent. T21–T23 are the tests most implementations will fail first, and the ones a payer cares about most: they are the difference between an accounting error and a lost balance.
9. Reference: what "one turn" is not
Stated explicitly, because these are the substitutions that make published figures incomparable:
- Not one model call. Loops are one turn.
- Not one conversation. Conversations contain many turns.
- Not one successful outcome. Refusals, failures and interruptions are turns.
- Not one token bundle. Payload size does not determine turn count.
- Not inference alone. Tools the agent called are part of the turn.
- Not a supporting call. A guard, an embedding or a retry is a component, not a turn (§3.4).
10. Publishing a cost-per-turn figure
Any party publishing a cost-per-turn figure and citing this specification MUST publish, alongside it:
- The class definitions, the
class_basis, and the envelope limits that bound each class — at minimum: maximum context tokens, maximum iterations, maximum output tokens, and the behaviour on breach. - Record coverage (§6.8) and the orphan rate (§3.4).
- The outcome mix: whether refused, failed and interrupted turns are included in the denominator.
- The provenance mix: the share of total cost that is
known,estimatedandunknown(§5.2). A figure drawn largely from estimated components is not comparable to one drawn from measured ones. - The gate mode (§6.7).
- The currency and, where conversion applies, the rate source.
- The distribution, not only the mean, with the sample size. At minimum p50, p90 and p95.
- The measurement window and the workload description.
10.1 Statistical adequacy
A percentile MUST NOT be published unless at least ten observations exceed it, and the sample size MUST accompany every percentile.
In practice this means n ≥ 200 for a p95 and n ≥ 1000 for a p99. Below those, the figure is an artefact of the two or three most expensive turns in the sample and will move by an order of magnitude with the next one.
A mean cost per turn over a right-skewed distribution is not a false statement, but it is not a useful one, and it systematically understates the cost of the most engaged payers. Where sample size does not support a percentile, report the sample size and the maximum observed rather than a percentile that cannot be supported.
11. Non-goals
This specification deliberately does not address: tenant isolation, permission and clearance models, data residency, model quality or evaluation, latency objectives, or what a turn should cost. Several of those are necessary to operate a product responsibly. None of them are necessary to make a cost figure comparable, and including them would make this document a product description rather than a unit definition.
12. Governance
- The specification text is CC BY 4.0. Anyone may implement it, extend it, or fork it, including in direct competition with any implementation listed in §13.
- The conformance suite is Apache-2.0 and is the only basis for a conformance claim. Self-declaration without a passing suite is not a claim.
- Any rule that only the editor's implementation can satisfy is a defect. Report it and it will be changed or removed.
- Rules SHOULD be revised against implementation audits rather than reasoning alone. This version is the product of one such audit; a rule that has never met an implementation is a hypothesis.
- Version 1.0 will not be declared while there is only one implementation.
13. Implementations
Entries are self-declared. No entry has been verified against the conformance suite at v0.1, because the suite is published with this draft and has not yet been run.
| Implementation | Declared level | Notes |
|---|---|---|
| tack | Level 3 (target) | Editor's implementation. Level 3 claim is a target, not a verified result: T21–T23 are not yet satisfied at the time of writing |
Additions welcome, including from implementations that only reach Level 1. Level 1 is a real and honest claim, and a specification with one implementation is a document, not a standard.
14. Changelog
v0.2 (draft) — 3 August 2026 — revised against a design-time audit of a second, from-scratch implementation (see On this draft). Added: the pre-admission cost rule and the post-admission guard-stop ruling (§4.3); the who-stopped-it outcome taxonomy (§5.3); the transport-independent retrieval-leg definition (§5.5); the async-provider-report-is-a-correction rule (§6.4); the zero-cost-gates expectation (§6.7). Amended: T15 to match the refined refusal-cost semantics. Resolved former open question 8 (async revision → always a §6.4 correction); added open questions 10–12.
v0.1 — 30 July 2026 — initial version. Drafted, then revised against a production implementation audit before publication (see On this draft). Prior working drafts are not published.
15. Open questions for v0.2
- Whether
maintenanceturns should be a distinct outcome rather than a class. - Whether
infrastructureshould be promoted from OPTIONAL to REQUIRED. If it is, the allocation method (per turn, per span, per GB-month) and the reference volume MUST be declared, since infrastructure is largely a fixed cost and its per-turn share is a function of throughput rather than of the turn. - How to represent a turn served by more than one vendor mid-loop.
- Whether the
inference_reasoningcomponent and thereasoning_tokenscounter are redundant now that provenance exists. - A canonical serialisation, and whether to align field names with an existing tracing standard.
- Whether Level 3 should require a published remedy for reservations stranded by prolonged provider unavailability.
- Whether the idempotency window should have a specified minimum.
- Whether record coverage should be required — rather than merely published — at Level 1.
- Whether a minimum sample size should gate conformance claims themselves, not only published figures.
- Whether Level 3 should require zero-cost admission outright. A paid gate is arguably incompatible with "cannot spend what it has not collected", but ruling it out may exclude legitimate paid pre-admission policy evaluation.
- Whether the
billable_reasonenum should distinguish pre-admission refusals from post-admission guard stops, now that both map tooutcome = refused. - Whether a race between a passing zero-cost pre-check and a failing authoritative reserve — where a pre-admission component was paid for in the window between them — needs its own declared accounting treatment, or is adequately covered by the §4.3 pre-admission row.