Skip to documentation
Documentation navigation

Documentation navigation

Documentation / guides

Usage translation

Normalize provider usage fields and cache subsets into Usage.

developer

The normalized alias is intentionally small:

type Usage struct {
	InputTokens         content.TokenCount
	OutputTokens        content.TokenCount
	CacheReadTokens     content.TokenCount
	CacheCreationTokens content.TokenCount
	ReasoningTokens     content.TokenCount
}

Fields

Provider fieldNormalized fieldRule
OpenAI prompt_tokensinput plus cache subsetssubtract cached_tokens and cache_write_tokens
Responses input_tokensinput plus cache read and cache writesubtract input_tokens_details.cached_tokens and cache_write_tokens
Anthropic input_tokensinputcache fields are separate
Gemini promptTokenCountinputsubtract cachedContentTokenCount, then add toolUsePromptTokenCount
Bedrock inputTokensinputcache fields are separate

Output and reasoning are normalized similarly. Gemini adds candidate and thought counts for OutputTokens; its totalTokenCount is validated as a well-formed count but is deliberately not reconciled against those components. Missing usage remains nil, not a fabricated zero measurement.

Invariants

usagenorm rejects negative, null-invalid, fractional, or out-of-range counts. Cache subsets cannot exceed the provider’s gross input count, and addition uses checked arithmetic. Reasoning greater than output is not an invariant: it is reported as received and observable through content.Usage.ReasoningWithinOutput.

u := content.Usage{InputTokens: 10, CacheReadTokens: 2, OutputTokens: 4}
contextTokens, err := u.ContextTokens() // 12
if err != nil {
	return err
}
_ = contextTokens

Source and proof

Run go test ./usage ./codec/....

← back to documentation