You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
old semconv attribute names (prompt_tokens vs input_tokens) — cross-SDK aggregation gap #1447
The current OTel GenAI semantic conventions use gen_ai.usage.input_tokens / gen_ai.usage.output_tokens. OpenLLMetry, pydantic-ai, and other instrumentation we audited have already migrated to the new names.
The file header (~L8-24) contains TODO comments acknowledging mapping issues.
The consequence
In an OTLP collector receiving spans from multiple SDKs:
sum(gen_ai.usage.input_tokens) misses all AgentOps spans (they emit prompt_tokens)
sum(gen_ai.usage.prompt_tokens) misses all OpenLLMetry spans (they emit input_tokens)
Cross-SDK token aggregation requires knowing which attribute name each SDK uses — per-SDK knowledge that generic consumers shouldn't need
The question
Is there a plan to migrate to the current gen_ai.usage.input_tokens / output_tokens names, or to emit both during a transition? The old names still work within the AgentOps ecosystem, but any downstream tool consuming generic OTel GenAI attributes will silently undercount when AgentOps spans are mixed in.
Happy to send a two-SDK repro (one AgentOps span + one OpenLLMetry span in the same collector, asserting the aggregation gap).
Context: AgentMeasure conformance check; this is the AgentOps follow-up after the Anthropic cache-token finding in #1445.
I'd like to take this. Plan: dual-emit current OTel GenAI usage names (gen_ai.usage.input_tokens / output_tokens) alongside the existing prompt_tokens / completion_tokens in TokenUsage.to_attributes(), with regression coverage, so cross-SDK collectors can sum either family during the transition. No call-site rewrite in this PR.
Thanks for picking this up — dual-emit is the right transitional shape, and putting the regression tests around TokenUsage.to_attributes() is exactly where this class of drift belongs.
Two things worth pinning down while the implementation settles:
Canonical name + removal horizon. If gen_ai.usage.input_tokens/output_tokens become primary, stating in the code/docs that prompt_tokens/completion_tokens are compatibility aliases (even with a soft removal horizon) helps consumers keying dashboards on the old names — they break silently, not loudly, the day the aliases drop.
Double-count risk while both are live. Any consumer that sums every gen_ai.usage.* token attribute will count both copies. Either document "prefer the new names, old ones are fallback", or gate the legacy names behind a flag — one sentence in the docs will save someone a confusing afternoon.
The regression shape that bit every SDK in our audit: same logical call, two attribute names, one expected total. Happy to review the PR when it's up.
Activity
ZxlDragonDoctor commentedon Sep 12, 2026
I'd like to take this. Plan: dual-emit current OTel GenAI usage names (
gen_ai.usage.input_tokens/output_tokens) alongside the existingprompt_tokens/completion_tokensinTokenUsage.to_attributes(), with regression coverage, so cross-SDK collectors can sum either family during the transition. No call-site rewrite in this PR.roy-tong commentedon Sep 14, 2026
Thanks for picking this up — dual-emit is the right transitional shape, and putting the regression tests around
TokenUsage.to_attributes()is exactly where this class of drift belongs.Two things worth pinning down while the implementation settles:
Canonical name + removal horizon. If
gen_ai.usage.input_tokens/output_tokensbecome primary, stating in the code/docs thatprompt_tokens/completion_tokensare compatibility aliases (even with a soft removal horizon) helps consumers keying dashboards on the old names — they break silently, not loudly, the day the aliases drop.Double-count risk while both are live. Any consumer that sums every
gen_ai.usage.*token attribute will count both copies. Either document "prefer the new names, old ones are fallback", or gate the legacy names behind a flag — one sentence in the docs will save someone a confusing afternoon.The regression shape that bit every SDK in our audit: same logical call, two attribute names, one expected total. Happy to review the PR when it's up.
Repro fixtures: AgentMeasure conformance pack — plain JSONL + expected totals, no runtime install. Found during an open ecosystem audit of usage-accounting tools.