The OpenTelemetry GenAI conventions exist so that every span an agent emits carries the same usage attributes - input tokens, output tokens, cached input tokens - regardless of which provider served the call. Once you have that, the cost of a run is arithmetic. Getting the arithmetic wrong by a factor of ten is the standard way to be surprised by a bill.
Providers quote prices per million tokens. A usage record looks like:
{"model": "big", "input_tokens": 1000, "cached_input_tokens": 800, "output_tokens": 200}
The trap: input_tokens is the total input, and cached_input_tokens is the subset of it that was served from the prompt cache. The cached portion is billed at the (much lower) cached rate, and only the remainder at the full input rate:
cost=106(input−cached)⋅pin+cached⋅pcached+output⋅pout
Double-counting the cached tokens - charging them at both rates - is the single most common bug in agent cost dashboards.
Implement:
def compute_cost(usage, prices):
Return:
Returns the three-key dict. All money values are rounded to 6 dp; total_tokens is an int.
usage = [{"model": "big", "input_tokens": 1000, "cached_input_tokens": 800, "output_tokens": 200}]
prices = {"big": {"input": 3.0, "cached_input": 0.3, "output": 15.0}}
print(compute_cost(usage, prices)["total_cost"])
# 0.00384
200 fresh input tokens at $3/M = $0.0006, 800 cached at $0.30/M = $0.00024, 200 output at $15/M = $0.003. Total $0.00384.
usage = [{'model':'big','input_tokens':1000,'cached_input_tokens':800,'output_tokens':200}]
prices = {'big': {'input':3.0,'cached_input':0.3,'output':15.0}}
print(compute_cost(usage, prices)['total_cost'])0.00384
Only 1000 - 800 = 200 input tokens are billed at the full rate: 200 * 3.0 / 1e6 = 0.0006. The 800 cached tokens cost 800 * 0.3 / 1e6 = 0.00024. Output is 200 * 15.0 / 1e6 = 0.003. Summing gives 0.00384.
0 <= len(usage) <= 5000; every model in usage also appears in pricescached_input_tokens <= input_tokens; a missing cached_input_tokens means 010**6by_model by iterating sorted model names so the dict order is deterministic