Counts are DISJOINT: inputTokens is uncached input only, and cached input
is reported separately, so billed input is the sum of the three. Adapters
whose providers fold cache hits into one prompt total must subtract them back
out. reasoningTokens is detail already inside outputTokens and must never
be added again.
The cache fields are OPTIONAL, and that is a decision, not an oversight.
Absent means "the provider did not report it", which is not the same fact as
zero. TokenUsage in the session vocabulary requires cacheRead/
cacheWrite, so the writer that eventually folds one of these into a
step/end row must decide what an unreported count means and record that
decision — it must not quietly sign a fabricated zero. That conversion is
deliberately NOT provided here, so nobody can reach for it by accident.
Token accounting for one model call.
Counts are DISJOINT:
inputTokensis uncached input only, and cached input is reported separately, so billed input is the sum of the three. Adapters whose providers fold cache hits into one prompt total must subtract them back out.reasoningTokensis detail already insideoutputTokensand must never be added again.The cache fields are OPTIONAL, and that is a decision, not an oversight. Absent means "the provider did not report it", which is not the same fact as zero.
TokenUsagein the session vocabulary requirescacheRead/cacheWrite, so the writer that eventually folds one of these into astep/endrow must decide what an unreported count means and record that decision — it must not quietly sign a fabricated zero. That conversion is deliberately NOT provided here, so nobody can reach for it by accident.