- Ingest is fail-open. A missing attribute degrades a feature. It never rejects the span. “Required” below means required for the span to be usable, not required for it to be accepted.
- One spelling per field. Only the canonical name in these tables is read. There are no compatibility aliases and no deprecated-spelling fallbacks, so
sessionId,enduser.id, andtessary.call_site_idare all ignored. Third-party dialects are a separate, documented case: see Accepted dialects.
Span structure
These are protobuf fields on the OTLP (OpenTelemetry Protocol) span, not attributes. Every OpenTelemetry SDK sets them for you.span.kind, trace_state, span flags, dropped counts, instrumentation-scope attributes, and span links are all ignored.
Call site
This is the only
tessary.* attribute with a reader. The call-site tag covers what a call site is and how to choose an id.
Kind
gen_ai.operation.name is the single source of a span’s kind.
The enum is open, so an unrecognized value degrades to an unknown kind rather than failing. Values map to a closed 14-value step typology:
llm, reasoning, tool, mcp, retrieval, embedding, reranker, agent, workflow, plan, memory, handoff, guardrail, step.
A span carrying gen_ai.request.model but no recognized operation name still resolves as a model call. That backstop is the reason the model attribute is required rather than recommended.
Model and provider
Content
Message content is stored whole and never truncated.Usage
The producer’s raw usage object is kept as an audit copy and is never read for arithmetic.
Cost
Report a cost and Tessary stores it verbatim and never reprices it. Report none and the token buckets above are priced on arrival. Report neither and the call is unpriced, which is not the same as zero.Errors
Tools
Without both, a tool call is an unnamed span.
A handoff between agents needs no attribute. It is already wire-encoded as an
execute_tool span for the transfer, followed by an invoke_agent span for the receiving agent under the same parent. Tessary derives the relationship from the span graph.
Session and user
Retrieval
Extraction runs on every span and does nothing when the prefix is absent, so there is no kind gate to satisfy.
Code and repository provenance
These are standard OpenTelemetry semantic conventions, set by the producer. They are stored for provenance and are never used to resolve a call site.Accepted dialects
If an LLM auto-instrumentation is already emitting one of these, leave it alone. Both are normalized to the canonical vocabulary at ingest, so a native span and a dialect span carrying the same content produce the same stored shape. Translating a dialect by hand adds work and risk for no gain.
When a span carries both the structured
gen_ai.input.messages array and the flattened gen_ai.prompt.<N>.* family, the structured array wins and the flattened copy is ignored. Never treat gen_ai.prompt.* as a canonical message key.
Do not emit
tessary.call_site.id is the only tessary.* name with a reader. Every other tessary.* spelling, and every ad-hoc alias of a canonical field such as sessionId or enduser.id, is carried verbatim and read by nothing. Put the content on the standard field from the tables above instead.
Ingestion contract lists each unread name against the field that replaces it.
deployment.environment.name is accepted and survives verbatim in the attribute bag, but it scopes nothing. A project is the only scope below an organization, so use separate projects for separate environments.
Transport
A missing token, or one that fails verification, is refused with
401. A token that is not project-scoped, or is query-scoped, is refused with 403. Write and admin keys both ingest, because admin is the superset family: see API keys for the three scopes and the errors each one returns. Ingestion contract carries the batch, body, and payload limits, and the 503 the receiver answers under buffer pressure.
The HTTP receiver is always on. A gRPC receiver exists and is opt-in; see Ingest and OTLP for the two variables that control it, and note that the default Docker Compose configuration does not publish its port to the host.
Related pages
Ingestion contract
The exhaustive lookup behind this page: every field, every dialect, and the limits.
Configure an exporter
Get spans to the endpoint above, without replacing the exporter you already have.
The call-site tag
The one attribute nothing resolves without.
