Repository navigation
Conversation
List only the gen_ai attributes Sentry and Relay read, with a description of each. Drop requirement levels, deprecated attributes, and attributes Relay derives during ingestion. Add decision, memory, and handoff spans, the span hierarchy, and common rules for conversation IDs, errors, and data collection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
| | `gen_ai.agent.name` | string | The agent's name. Powers the agent filter and grouping in Agents insights, the agent flow in Conversations, and span titles. | `"Weather Agent"` | | ||
| | `gen_ai.input.messages` | string | The messages the agent received. Sentry uses them for the conversation preview and transcript when the child model spans don't carry messages. **[0]** | `'[{"role": "user", "parts": [{"type": "text", "content": "..."}]}]'` | | ||
| | `gen_ai.output.messages` | string | The agent's final response. Used the same way as the input messages. **[0]** | `'[{"role": "assistant", "parts": [{"type": "text", "content": "..."}]}]'` | | ||
| | `gen_ai.tool.definitions` | string | The tools available to the agent, as a JSON array of name and description objects. Shown as **Available Tools** in the span details. Omit it when the agent has no tools. | `'[{"name": "get_weather", "description": "..."}]'` | |
There was a problem hiding this comment.
Not doing a full review now.
This immediately stands out because available tools are provided on a per-call basis.
A similar caveat to what OTel has for setting gen_ai.request.model on Invoke Agent spans applies
This attribute SHOULD be populated if and only if the instrumented library allows to set only a single model per agent. . It SHOULD NOT be populated for agents that support multiple models or dynamic selection.
All libraries we instrument in Python allow dynamic tool configuration during an agent execution.
As a result, we don't set gen_ai.tool.definitions on Invoke Agent spans in Python.
I know that this doesn't work nicely with the product today, so we should discuss how to resolve this conflict.
Co-authored-by: Andrei <168741329+andreiborza@users.noreply.github.com>
SDKs no longer drop earlier messages from gen_ai.input.messages. Replace the trimming rule with guidance to send every message the model received. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
alexander-alderman-webb
left a comment
There was a problem hiding this comment.
Just a brief read
| ## Notes | ||
|
|
||
| Reasoning tokens are a subset of output tokens; `gen_ai.usage.output_tokens` includes `gen_ai.usage.reasoning.output_tokens`. | ||
| **[0]** Messages use the format `{role, parts}`, where `role` is `"user"`, `"assistant"`, `"tool"`, or `"system"`, and `parts` is an array of typed objects: |
There was a problem hiding this comment.
No system messages go in the gen_ai.system_instructions attribute, so there should be no system roles in gen_ai.input.messages.
| | `gen_ai.tool.call.arguments` | string | The arguments the tool was called with, as a JSON string. Shown in the span's **Input** tab and as the timeline preview. | `'{"location": "Paris"}'` | | ||
| | `gen_ai.tool.call.result` | string | What the tool returned. Shown in the span's **Output** tab, and its size is shown in the timeline. | `'{"temperature": 18}'` | | ||
|
|
||
| ## Handoff Span |
There was a problem hiding this comment.
We're removing handoff spans from the SDKs, they're not in OTel either.
There was a problem hiding this comment.
Please deprecate it in conventions and let's remove it here.
| - `gen_ai.usage.total_tokens` | ||
| - `gen_ai.response.tokens_per_second` | ||
| - `gen_ai.context.window_size` and `gen_ai.context.utilization` | ||
| - `gen_ai.cost.*`, calculated from the model and token counts. Relay keeps an existing `gen_ai.cost.total_tokens` so users can set costs for self-hosted or unpriced models, but SDKs don't calculate costs themselves. |
There was a problem hiding this comment.
These can be set by SDKs (requirement from the Seer team).
|
|
||
| ### Request Data | ||
| - `gen_ai.operation.type` | ||
| - `gen_ai.usage.total_tokens` |
There was a problem hiding this comment.
gen_ai.usage.total_tokens does not always equal
gen_ai.usage.input_tokens + gen_ai.usage.output_tokens.
according to the values the SDKs send. So I would keep sending them from the SDK even if the Relay transform is wrong.
| | Attribute | Type | Requirement Level | Description | Example | | ||
| | :--------------------------------- | :----- | :---------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------- | | ||
| | `gen_ai.input.messages` | string | optional | List of dictionaries describing the messages (prompts) given to the agent. **[0]**, **[1]**, **[4]**, **[5]**, **[7]** | `'[{"role": "user", "parts": [{"type": "text", "content": "..."}]}]'` | | ||
| | `gen_ai.system_instructions` | string | optional | The system instructions passed to the model. | `"You are a helpful assistant."` | |
There was a problem hiding this comment.
Why do invoke agent spans no longer carry system instructions?
Surely the same justification as for gen_ai.input.messages applies:
Sentry uses them for the conversation preview and transcript when the child model spans don't carry messages.
| - On failure, set the span status to error. Sentry counts errors from the span status alone. | ||
| - When the application has a conversation, chat, or session ID, set `gen_ai.conversation.id` to it on every `gen_ai.*` span. Conversations are keyed on this attribute, so spans without it don't appear in any conversation. Omit it when there is no such ID; never derive one from a trace or request ID. | ||
| - Send structured values (messages, tool definitions, records) as JSON strings. Span attributes only accept primitives, so set `'[{"foo": "bar"}]'`, not `[{"foo": "bar"}]`. | ||
| - Gate prompt, response, and tool content with the `genAI` option of the [data collection](/sdk/foundations/client/data-collection/) configuration. When collection is off, omit those attributes. Metadata such as model names, token counts, and tool names is always sent. |
There was a problem hiding this comment.
Confusing what data collection off means. It's always on in new JS and Python SDKs, and if you omit explicit config, then all GenAI attributes are set.
|
|
||
| - Span `op`: `"gen_ai.decide"` | ||
| - Span `name`: `"decide {gen_ai.request.model}"` (e.g. `"decide typesafe/jev-1.13"`) | ||
| - `gen_ai.operation.name`: `"decide"`. Decisions share the `ai_client` operation type with model calls, so this attribute is what tells them apart. |
There was a problem hiding this comment.
Confusing, the SDKs never set ai_client.
There was a problem hiding this comment.
Let's add that this is inferred by Relay with a link to the codebase.
| | Attribute | Type | Description | Example | | ||
| | :----------------------------------------- | :----- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------- | | ||
| | `gen_ai.request.model` | string | The model the SDK asked for, as the raw provider string. Drives model breakdowns, cost calculation, and model icons. Without a model, Relay doesn't classify the span as a model call. | `"gpt-4o"` | | ||
| | `gen_ai.response.model` | string | The concrete model that responded, which Models views group by. Omit it when the provider doesn't report one; Relay copies `gen_ai.request.model` instead. | `"gpt-4o-2024-08-06"` | |
There was a problem hiding this comment.
Not relevant what Relay does here, and I also don't think Relay should pretend that the response model is the request model.
| | `gen_ai.response.model` | string | The concrete model that responded, which Models views group by. Omit it when the provider doesn't report one; Relay copies `gen_ai.request.model` instead. | `"gpt-4o-2024-08-06"` | | |
| | `gen_ai.response.model` | string | The concrete model that responded, which Models views group by. Omit it when the provider doesn't report one. | `"gpt-4o-2024-08-06"` | |
There was a problem hiding this comment.
Let's find out if they are both strictly needed?
| Describes AI agent invocation. | ||
| Agent invocations represent operations that can include multiple model calls, or some auxiliary work that goes beyond transforming the model input and output. | ||
| - Set `gen_ai.operation.name` on every span. Sentry uses it to recognize AI spans and to tell decision, memory, and embeddings spans apart from ordinary model calls. Relay derives `gen_ai.operation.type` from it, and every Agents insights view filters on that type. | ||
| - Set `gen_ai.operation.name`, `gen_ai.request.model`, `gen_ai.agent.name`, and `gen_ai.tool.name` when the span starts, so sampling decisions can use them. |
There was a problem hiding this comment.
gen_ai.tool.name only appears on child Execute Tool spans, how is this relevant for sampling decisions?
| The AI Agents module is agnostic to the library used. SDKs instrument supported AI frameworks and provider clients automatically. Users instrument anything else manually with the same span conventions. | ||
|
|
||
| ## Spans Conventions | ||
| This page lists every attribute SDKs send on AI spans. Send all of them. The descriptions call out the few cases where an attribute can be omitted. Don't send attributes that aren't listed here: no part of the product reads them, or Relay derives them during ingestion. |
There was a problem hiding this comment.
Agent name doesn't always exist, and with all our populate integrations we care about gen_ai.function.id.
No description provided.