v0.23.0 — the wire format for §7, and the three things it will not carry - #24
Merged
Conversation
…ill not carry Section 7 said what to instrument and named no format; a grep for opentelemetry over the pack returned one table cell. references/otel-genai.md is the format, and it earns its own file on the refusals rather than the field list. - The conventions moved repositories, their Schema URL reads TODO, and every gen_ai.* attribute is Development. Adopt and pin; treat a branch on any of those names as code with an expiry date. - gen_ai.evaluation.result has no attribute for who produced the score — the field section 7 requires by name. OpenInference has it as annotation. annotator_kind with our three values; carry it as a documented extension rather than drop the requirement. - There is no cost attribute, and usage is eleven numbers. A cost from input + output is wrong in both directions: it bills cache reads at full price and misses reasoning tokens and cache writes. - The content-upload hook runs independently of the opt-in flags AND of the sampling decision, so it is the last scrubbing point and fires on spans nobody reads; a masking hook cannot change the span name. Checked against a shipping implementation: OpenLLMetry captures content when its env var is unset, the inverse of the spec's default. - "OpenTelemetry-based" is not one vocabulary, and "replay" is three guarantees. B-134, OT-1..8. Gate: npm test rc=0. Body 4631/4750. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
agent-evals§7 said what to instrument in four bullets and named no format. A grep foropentelemetryover the whole pack returned one table cell.references/otel-genai.mdis that format — and it earns its own file on the refusals, not the field list.Read the status before encoding any of it
The conventions moved out of the main
semantic-conventionsrepository into their own, whose README lists Schema URL:TODO. Every document isStatus: Development; on the inference span the onlyStableattributes are those borrowed from core semconv. Everygen_ai.*attribute is Development.Adopt it anyway — a moving standard beats a private vocabulary nobody else's tooling reads — but pin the version and treat any branch on a
gen_ai.*name as code with an expiry date.Three things it will not carry
1. Who produced the score.
gen_ai.evaluation.resulthas a name, a value, a low-cardinality label and an explanation — and no attribute for the scorer. §7 requires exactly that (human|llm_judge|code_check), because a score with no source cannot be calibrated or audited. OpenInference has the field asannotation.annotator_kindwith our three values. Carry it as a documented extension rather than drop the requirement: a judge score and a human label indistinguishable on the wire get averaged downstream, which is what §5's calibration exists to prevent.2. Money. There is no cost attribute at all, and usage is eleven numbers —
input_tokens,output_tokens,reasoning.output_tokens,cache_read.input_tokens,cache_write.input_tokens, plus per-modality splits. A cost frominput + outputalone is wrong in both directions: it bills cache reads at full price and misses reasoning tokens and cache writes.gen_ai.client.token.usagecarries a hard MUST NOT report when counts are unobtainable — absence over a fabricated zero, matchingaudit.md.3. A safe default you can rely on. The spec's default is to record nothing. Checked against a shipping implementation rather than assumed: OpenLLMetry's
is_content_tracing_enabled()returns(os.getenv("TRACELOOP_TRACE_CONTENT") or "true")— unset means true, so prompts are captured unless you turn them off (traceloop-sdk/traceloop/sdk/config/__init__.py, read 2026-08-31). An agent's trace carries prompts, prompts carry secrets, and the most-used implementation ships the inverse of the spec.Two seams that decide a design, not a field
Two words that mean three things each
"OpenTelemetry-based" answers a transport question and no semantic one — Phoenix emits OpenInference, OpenLLMetry emits
gen_ai.*+traceloop.*, neither a subset of the other, and a trace from both is two disconnected halves under one trace id."Replay" is durable execution (recorded results, nothing re-runs), a trace playground (the call re-runs live), or this skill's fixture replay.
audit.mdasks whether a run can be replayed without saying which; the reference names the three.Evidence
npm testrc=00 GAP, 14 PASS, body 4631/4750Board B-134. Ledger OT-1 … OT-8.
🤖 Generated with Claude Code