From e41ab594f89db8c73c29e29b0bcd3906164e9fff Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 20 Oct 2026 09:58:13 +0200 Subject: [PATCH 1/9] feat(attributes): Add experimental `gen_ai.extract` operation Co-Authored-By: Claude Opus 5.5 --- .../sentry-conventions/src/attributes.ts | 12 +++++++---- javascript/sentry-conventions/src/op.ts | 5 +++++ javascript/sentry-conventions/src/search.ts | 4 ++-- .../gen_ai/gen_ai__input__messages.json | 7 ++++++- .../gen_ai/gen_ai__operation__name.json | 8 ++++++++ .../gen_ai/gen_ai__output__messages.json | 7 ++++++- model/description/gen_ai.json | 2 ++ model/name/gen_ai.json | 2 ++ model/op/gen_ai.json | 4 ++++ python/src/sentry_conventions/attributes.py | 20 +++++++++++++++---- rust/src/op.rs | 3 +++ 11 files changed, 62 insertions(+), 12 deletions(-) diff --git a/javascript/sentry-conventions/src/attributes.ts b/javascript/sentry-conventions/src/attributes.ts index 9db855bd..747a6a29 100644 --- a/javascript/sentry-conventions/src/attributes.ts +++ b/javascript/sentry-conventions/src/attributes.ts @@ -7963,7 +7963,7 @@ export type GEN_AI_FUNCTION_ID_TYPE = string; // Path: model/attributes/gen_ai/gen_ai__input__messages.json /** - * The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. `gen_ai.input.messages` + * The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them. `gen_ai.input.messages` * * Attribute Value Type: `string` {@link GEN_AI_INPUT_MESSAGES_TYPE} * @@ -8114,6 +8114,7 @@ export type GEN_AI_MEMORY_STORE_ID_TYPE = string; * - `embeddings` * - `evaluate` * - `execute_tool` + * - `extract` * - `generate_content` * - `invoke_agent` * - `search_memory` @@ -8162,7 +8163,7 @@ export type GEN_AI_OPERATION_TYPE_TYPE = string; // Path: model/attributes/gen_ai/gen_ai__output__messages.json /** - * The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. `gen_ai.output.messages` + * The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", answers: {...}}` with the answers keyed by field name, as the provider returned them. `gen_ai.output.messages` * * Attribute Value Type: `string` {@link GEN_AI_OUTPUT_MESSAGES_TYPE} * @@ -27873,7 +27874,7 @@ export const ATTRIBUTE_METADATA: Record = { }, 'gen_ai.input.messages': { brief: - 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them.', + 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', type: 'string', keys: [ 'gen_ai.input.messages', @@ -27892,6 +27893,7 @@ export const ATTRIBUTE_METADATA: Record = { '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', aliases: ['ai.texts', 'ai.prompt.messages', 'gen_ai.prompt', 'ai.prompt'], changelog: [ + { version: 'next', description: 'Describe the extraction message shape for gen_ai.extract' }, { version: '0.26.0', prs: [650], description: 'Describe the evaluation message shape for gen_ai.evaluate' }, { version: '0.21.0', prs: [583], description: 'Added ai.prompt as an alias' }, { version: '0.5.0', prs: [264] }, @@ -27982,6 +27984,7 @@ export const ATTRIBUTE_METADATA: Record = { visibility: 'public', example: 'chat', changelog: [ + { version: 'next', description: "Added 'extract' to the well-known values" }, { version: '0.27.0', prs: [653, 680], @@ -28011,7 +28014,7 @@ export const ATTRIBUTE_METADATA: Record = { }, 'gen_ai.output.messages': { brief: - 'The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them.', + 'The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", answers: {...}}` with the answers keyed by field name, as the provider returned them.', type: 'string', keys: ['gen_ai.output.messages', 'ai.response.text', 'ai.response.toolCalls', 'ai.responses', 'ai.tool_calls'], applyScrubbing: { @@ -28023,6 +28026,7 @@ export const ATTRIBUTE_METADATA: Record = { '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', aliases: ['ai.response.toolCalls', 'ai.response.text'], changelog: [ + { version: 'next', description: 'Describe the extraction message shape for gen_ai.extract' }, { version: '0.26.0', prs: [650], description: 'Describe the evaluation message shape for gen_ai.evaluate' }, { version: '0.4.0', prs: [221] }, ], diff --git a/javascript/sentry-conventions/src/op.ts b/javascript/sentry-conventions/src/op.ts index b23bab62..949ad1d6 100644 --- a/javascript/sentry-conventions/src/op.ts +++ b/javascript/sentry-conventions/src/op.ts @@ -349,6 +349,11 @@ export const GEN_AI_RERANK = 'gen_ai.rerank'; */ export const GEN_AI_DECIDE = 'gen_ai.decide'; +/** + * Extraction of a set of typed fields (e.g., text, date, number, list, or estimate) from a shared state by a generative AI model + */ +export const GEN_AI_EXTRACT = 'gen_ai.extract'; + /** * Evaluation of typed questions (e.g., boolean, choice, or score) about a shared state by a generative AI model * diff --git a/javascript/sentry-conventions/src/search.ts b/javascript/sentry-conventions/src/search.ts index 0cb2e060..82d68327 100644 --- a/javascript/sentry-conventions/src/search.ts +++ b/javascript/sentry-conventions/src/search.ts @@ -8495,7 +8495,7 @@ export const ATTRIBUTE_SEARCH_METADATA: Record canonicalName: 'gen_ai.input.messages', type: 'string', brief: - 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them.', + 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', deprecationChain: [ 'gen_ai.input.messages', 'ai.input_messages', @@ -8558,7 +8558,7 @@ export const ATTRIBUTE_SEARCH_METADATA: Record canonicalName: 'gen_ai.output.messages', type: 'string', brief: - 'The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them.', + 'The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", answers: {...}}` with the answers keyed by field name, as the provider returned them.', deprecationChain: [ 'gen_ai.output.messages', 'ai.response.text', diff --git a/model/attributes/gen_ai/gen_ai__input__messages.json b/model/attributes/gen_ai/gen_ai__input__messages.json index b67370ef..7f87b901 100644 --- a/model/attributes/gen_ai/gen_ai__input__messages.json +++ b/model/attributes/gen_ai/gen_ai__input__messages.json @@ -1,6 +1,6 @@ { "key": "gen_ai.input.messages", - "brief": "The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `\"user\"`, `\"assistant\"`, `\"tool\"`, or `\"system\"`. For messages of the role `\"tool\"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: \"text\", text:\"...\"}`. For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them.", + "brief": "The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `\"user\"`, `\"assistant\"`, `\"tool\"`, or `\"system\"`. For messages of the role `\"tool\"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: \"text\", text:\"...\"}`. For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: \"extraction\", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.", "type": "string", "apply_scrubbing": { "key": "manual" @@ -10,6 +10,11 @@ "alias": ["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], "visibility": "public", "changelog": [ + { + "version": "next", + "prs": [], + "description": "Describe the extraction message shape for gen_ai.extract" + }, { "version": "0.26.0", "prs": [650], diff --git a/model/attributes/gen_ai/gen_ai__operation__name.json b/model/attributes/gen_ai/gen_ai__operation__name.json index 93909997..abd94d8c 100644 --- a/model/attributes/gen_ai/gen_ai__operation__name.json +++ b/model/attributes/gen_ai/gen_ai__operation__name.json @@ -38,6 +38,9 @@ { "value": "execute_tool" }, + { + "value": "extract" + }, { "value": "generate_content" }, @@ -59,6 +62,11 @@ ], "visibility": "public", "changelog": [ + { + "version": "next", + "prs": [], + "description": "Added 'extract' to the well-known values" + }, { "version": "0.27.0", "prs": [653, 680], diff --git a/model/attributes/gen_ai/gen_ai__output__messages.json b/model/attributes/gen_ai/gen_ai__output__messages.json index 010d97d9..a54ec70b 100644 --- a/model/attributes/gen_ai/gen_ai__output__messages.json +++ b/model/attributes/gen_ai/gen_ai__output__messages.json @@ -1,6 +1,6 @@ { "key": "gen_ai.output.messages", - "brief": "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", answers: {...}}` with the answers keyed by question name, as the provider returned them.", + "brief": "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: \"extraction\", answers: {...}}` with the answers keyed by field name, as the provider returned them.", "type": "string", "apply_scrubbing": { "key": "manual" @@ -10,6 +10,11 @@ "alias": ["ai.response.toolCalls", "ai.response.text"], "visibility": "public", "changelog": [ + { + "version": "next", + "prs": [], + "description": "Describe the extraction message shape for gen_ai.extract" + }, { "version": "0.26.0", "prs": [650], diff --git a/model/description/gen_ai.json b/model/description/gen_ai.json index 276d0c1d..3c61c509 100644 --- a/model/description/gen_ai.json +++ b/model/description/gen_ai.json @@ -25,6 +25,7 @@ "gen_ai.chat", "gen_ai.decide", "gen_ai.embeddings", + "gen_ai.extract", "gen_ai.generate_content", "gen_ai.rerank", "gen_ai.responses", @@ -38,6 +39,7 @@ "generate_content gemini-2.0-flash-001", "embeddings text-embedding-3-small", "decide jev-latest", + "extract clairic", "chat" ] }, diff --git a/model/name/gen_ai.json b/model/name/gen_ai.json index e998fa88..149bdf09 100644 --- a/model/name/gen_ai.json +++ b/model/name/gen_ai.json @@ -32,6 +32,7 @@ "gen_ai.chat", "gen_ai.decide", "gen_ai.embeddings", + "gen_ai.extract", "gen_ai.execute_tool", "gen_ai.generate_content", "gen_ai.rerank", @@ -50,6 +51,7 @@ "chat claude-opus-4", "execute_tool get_weather", "decide jev-latest", + "extract clairic", "chat" ] }, diff --git a/model/op/gen_ai.json b/model/op/gen_ai.json index 16c81f32..9804bcc3 100644 --- a/model/op/gen_ai.json +++ b/model/op/gen_ai.json @@ -34,6 +34,10 @@ "name": "gen_ai.decide", "description": "Decision on a set of typed questions (e.g., boolean, choice, or score) about a shared state by a generative AI model" }, + { + "name": "gen_ai.extract", + "description": "Extraction of a set of typed fields (e.g., text, date, number, list, or estimate) from a shared state by a generative AI model" + }, { "name": "gen_ai.evaluate", "description": "Evaluation of typed questions (e.g., boolean, choice, or score) about a shared state by a generative AI model", diff --git a/python/src/sentry_conventions/attributes.py b/python/src/sentry_conventions/attributes.py index a2471c28..e0cfbf0d 100644 --- a/python/src/sentry_conventions/attributes.py +++ b/python/src/sentry_conventions/attributes.py @@ -4917,7 +4917,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): # Path: model/attributes/gen_ai/gen_ai__input__messages.json GEN_AI_INPUT_MESSAGES: Literal["gen_ai.input.messages"] = "gen_ai.input.messages" - """The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. + """The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them. Type: str Apply Scrubbing: manual @@ -5010,6 +5010,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): - `embeddings` - `evaluate` - `execute_tool` + - `extract` - `generate_content` - `invoke_agent` - `search_memory` @@ -5039,7 +5040,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): # Path: model/attributes/gen_ai/gen_ai__output__messages.json GEN_AI_OUTPUT_MESSAGES: Literal["gen_ai.output.messages"] = "gen_ai.output.messages" - """The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. + """The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", answers: {...}}` with the answers keyed by field name, as the provider returned them. Type: str Apply Scrubbing: manual @@ -18643,7 +18644,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ], ), "gen_ai.input.messages": AttributeMetadata( - brief='The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them.', + brief='The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', type=AttributeType.STRING, keys=( "gen_ai.input.messages", @@ -18659,6 +18660,10 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): example='[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', aliases=["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], changelog=[ + ChangelogEntry( + version="next", + description="Describe the extraction message shape for gen_ai.extract", + ), ChangelogEntry( version="0.26.0", prs=[650], @@ -18767,6 +18772,9 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): visibility=Visibility.PUBLIC, example="chat", changelog=[ + ChangelogEntry( + version="next", description="Added 'extract' to the well-known values" + ), ChangelogEntry( version="0.27.0", prs=[653, 680], @@ -18793,7 +18801,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ], ), "gen_ai.output.messages": AttributeMetadata( - brief='The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them.', + brief='The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", answers: {...}}` with the answers keyed by field name, as the provider returned them.', type=AttributeType.STRING, keys=( "gen_ai.output.messages", @@ -18808,6 +18816,10 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): example='[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', aliases=["ai.response.toolCalls", "ai.response.text"], changelog=[ + ChangelogEntry( + version="next", + description="Describe the extraction message shape for gen_ai.extract", + ), ChangelogEntry( version="0.26.0", prs=[650], diff --git a/rust/src/op.rs b/rust/src/op.rs index 83aa0f8a..de98ddec 100644 --- a/rust/src/op.rs +++ b/rust/src/op.rs @@ -227,6 +227,9 @@ pub const GEN_AI_RERANK: &str = "gen_ai.rerank"; /// Decision on a set of typed questions (e.g., boolean, choice, or score) about a shared state by a generative AI model pub const GEN_AI_DECIDE: &str = "gen_ai.decide"; +/// Extraction of a set of typed fields (e.g., text, date, number, list, or estimate) from a shared state by a generative AI model +pub const GEN_AI_EXTRACT: &str = "gen_ai.extract"; + /// Evaluation of typed questions (e.g., boolean, choice, or score) about a shared state by a generative AI model #[deprecated(note = "Use `GEN_AI_DECIDE` (gen_ai.decide) instead")] pub const GEN_AI_EVALUATE: &str = "gen_ai.evaluate"; From e69e2332d8dc7cb9a16387f0edcb6339d56747e2 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 20 Oct 2026 09:58:32 +0200 Subject: [PATCH 2/9] Add PR number to changelog --- javascript/sentry-conventions/src/attributes.ts | 6 +++--- model/attributes/gen_ai/gen_ai__input__messages.json | 2 +- model/attributes/gen_ai/gen_ai__operation__name.json | 2 +- model/attributes/gen_ai/gen_ai__output__messages.json | 2 +- python/src/sentry_conventions/attributes.py | 6 +++++- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/javascript/sentry-conventions/src/attributes.ts b/javascript/sentry-conventions/src/attributes.ts index 747a6a29..53598530 100644 --- a/javascript/sentry-conventions/src/attributes.ts +++ b/javascript/sentry-conventions/src/attributes.ts @@ -27893,7 +27893,7 @@ export const ATTRIBUTE_METADATA: Record = { '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', aliases: ['ai.texts', 'ai.prompt.messages', 'gen_ai.prompt', 'ai.prompt'], changelog: [ - { version: 'next', description: 'Describe the extraction message shape for gen_ai.extract' }, + { version: 'next', prs: [728], description: 'Describe the extraction message shape for gen_ai.extract' }, { version: '0.26.0', prs: [650], description: 'Describe the evaluation message shape for gen_ai.evaluate' }, { version: '0.21.0', prs: [583], description: 'Added ai.prompt as an alias' }, { version: '0.5.0', prs: [264] }, @@ -27984,7 +27984,7 @@ export const ATTRIBUTE_METADATA: Record = { visibility: 'public', example: 'chat', changelog: [ - { version: 'next', description: "Added 'extract' to the well-known values" }, + { version: 'next', prs: [728], description: "Added 'extract' to the well-known values" }, { version: '0.27.0', prs: [653, 680], @@ -28026,7 +28026,7 @@ export const ATTRIBUTE_METADATA: Record = { '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', aliases: ['ai.response.toolCalls', 'ai.response.text'], changelog: [ - { version: 'next', description: 'Describe the extraction message shape for gen_ai.extract' }, + { version: 'next', prs: [728], description: 'Describe the extraction message shape for gen_ai.extract' }, { version: '0.26.0', prs: [650], description: 'Describe the evaluation message shape for gen_ai.evaluate' }, { version: '0.4.0', prs: [221] }, ], diff --git a/model/attributes/gen_ai/gen_ai__input__messages.json b/model/attributes/gen_ai/gen_ai__input__messages.json index 7f87b901..2052f758 100644 --- a/model/attributes/gen_ai/gen_ai__input__messages.json +++ b/model/attributes/gen_ai/gen_ai__input__messages.json @@ -12,7 +12,7 @@ "changelog": [ { "version": "next", - "prs": [], + "prs": [728], "description": "Describe the extraction message shape for gen_ai.extract" }, { diff --git a/model/attributes/gen_ai/gen_ai__operation__name.json b/model/attributes/gen_ai/gen_ai__operation__name.json index abd94d8c..21ba30a3 100644 --- a/model/attributes/gen_ai/gen_ai__operation__name.json +++ b/model/attributes/gen_ai/gen_ai__operation__name.json @@ -64,7 +64,7 @@ "changelog": [ { "version": "next", - "prs": [], + "prs": [728], "description": "Added 'extract' to the well-known values" }, { diff --git a/model/attributes/gen_ai/gen_ai__output__messages.json b/model/attributes/gen_ai/gen_ai__output__messages.json index a54ec70b..f9d188af 100644 --- a/model/attributes/gen_ai/gen_ai__output__messages.json +++ b/model/attributes/gen_ai/gen_ai__output__messages.json @@ -12,7 +12,7 @@ "changelog": [ { "version": "next", - "prs": [], + "prs": [728], "description": "Describe the extraction message shape for gen_ai.extract" }, { diff --git a/python/src/sentry_conventions/attributes.py b/python/src/sentry_conventions/attributes.py index e0cfbf0d..7c0e841a 100644 --- a/python/src/sentry_conventions/attributes.py +++ b/python/src/sentry_conventions/attributes.py @@ -18662,6 +18662,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): changelog=[ ChangelogEntry( version="next", + prs=[728], description="Describe the extraction message shape for gen_ai.extract", ), ChangelogEntry( @@ -18773,7 +18774,9 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): example="chat", changelog=[ ChangelogEntry( - version="next", description="Added 'extract' to the well-known values" + version="next", + prs=[728], + description="Added 'extract' to the well-known values", ), ChangelogEntry( version="0.27.0", @@ -18818,6 +18821,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): changelog=[ ChangelogEntry( version="next", + prs=[728], description="Describe the extraction message shape for gen_ai.extract", ), ChangelogEntry( From 7bd292872d6431d7db1b2e2787c1465781f5fa9f Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 20 Oct 2026 10:02:27 +0200 Subject: [PATCH 3/9] Remove type field from extract message shape --- javascript/sentry-conventions/src/attributes.ts | 8 ++++---- javascript/sentry-conventions/src/search.ts | 4 ++-- model/attributes/gen_ai/gen_ai__input__messages.json | 2 +- model/attributes/gen_ai/gen_ai__output__messages.json | 2 +- python/src/sentry_conventions/attributes.py | 8 ++++---- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/javascript/sentry-conventions/src/attributes.ts b/javascript/sentry-conventions/src/attributes.ts index 53598530..6a74ca8d 100644 --- a/javascript/sentry-conventions/src/attributes.ts +++ b/javascript/sentry-conventions/src/attributes.ts @@ -7963,7 +7963,7 @@ export type GEN_AI_FUNCTION_ID_TYPE = string; // Path: model/attributes/gen_ai/gen_ai__input__messages.json /** - * The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them. `gen_ai.input.messages` + * The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them. `gen_ai.input.messages` * * Attribute Value Type: `string` {@link GEN_AI_INPUT_MESSAGES_TYPE} * @@ -8163,7 +8163,7 @@ export type GEN_AI_OPERATION_TYPE_TYPE = string; // Path: model/attributes/gen_ai/gen_ai__output__messages.json /** - * The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", answers: {...}}` with the answers keyed by field name, as the provider returned them. `gen_ai.output.messages` + * The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them. `gen_ai.output.messages` * * Attribute Value Type: `string` {@link GEN_AI_OUTPUT_MESSAGES_TYPE} * @@ -27874,7 +27874,7 @@ export const ATTRIBUTE_METADATA: Record = { }, 'gen_ai.input.messages': { brief: - 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', + 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', type: 'string', keys: [ 'gen_ai.input.messages', @@ -28014,7 +28014,7 @@ export const ATTRIBUTE_METADATA: Record = { }, 'gen_ai.output.messages': { brief: - 'The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", answers: {...}}` with the answers keyed by field name, as the provider returned them.', + 'The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them.', type: 'string', keys: ['gen_ai.output.messages', 'ai.response.text', 'ai.response.toolCalls', 'ai.responses', 'ai.tool_calls'], applyScrubbing: { diff --git a/javascript/sentry-conventions/src/search.ts b/javascript/sentry-conventions/src/search.ts index 82d68327..41fe1ec6 100644 --- a/javascript/sentry-conventions/src/search.ts +++ b/javascript/sentry-conventions/src/search.ts @@ -8495,7 +8495,7 @@ export const ATTRIBUTE_SEARCH_METADATA: Record canonicalName: 'gen_ai.input.messages', type: 'string', brief: - 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', + 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', deprecationChain: [ 'gen_ai.input.messages', 'ai.input_messages', @@ -8558,7 +8558,7 @@ export const ATTRIBUTE_SEARCH_METADATA: Record canonicalName: 'gen_ai.output.messages', type: 'string', brief: - 'The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", answers: {...}}` with the answers keyed by field name, as the provider returned them.', + 'The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them.', deprecationChain: [ 'gen_ai.output.messages', 'ai.response.text', diff --git a/model/attributes/gen_ai/gen_ai__input__messages.json b/model/attributes/gen_ai/gen_ai__input__messages.json index 2052f758..5af21920 100644 --- a/model/attributes/gen_ai/gen_ai__input__messages.json +++ b/model/attributes/gen_ai/gen_ai__input__messages.json @@ -1,6 +1,6 @@ { "key": "gen_ai.input.messages", - "brief": "The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `\"user\"`, `\"assistant\"`, `\"tool\"`, or `\"system\"`. For messages of the role `\"tool\"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: \"text\", text:\"...\"}`. For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: \"extraction\", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.", + "brief": "The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `\"user\"`, `\"assistant\"`, `\"tool\"`, or `\"system\"`. For messages of the role `\"tool\"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: \"text\", text:\"...\"}`. For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.", "type": "string", "apply_scrubbing": { "key": "manual" diff --git a/model/attributes/gen_ai/gen_ai__output__messages.json b/model/attributes/gen_ai/gen_ai__output__messages.json index f9d188af..77708b6f 100644 --- a/model/attributes/gen_ai/gen_ai__output__messages.json +++ b/model/attributes/gen_ai/gen_ai__output__messages.json @@ -1,6 +1,6 @@ { "key": "gen_ai.output.messages", - "brief": "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: \"extraction\", answers: {...}}` with the answers keyed by field name, as the provider returned them.", + "brief": "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them.", "type": "string", "apply_scrubbing": { "key": "manual" diff --git a/python/src/sentry_conventions/attributes.py b/python/src/sentry_conventions/attributes.py index 7c0e841a..5e3c38d2 100644 --- a/python/src/sentry_conventions/attributes.py +++ b/python/src/sentry_conventions/attributes.py @@ -4917,7 +4917,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): # Path: model/attributes/gen_ai/gen_ai__input__messages.json GEN_AI_INPUT_MESSAGES: Literal["gen_ai.input.messages"] = "gen_ai.input.messages" - """The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them. + """The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them. Type: str Apply Scrubbing: manual @@ -5040,7 +5040,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): # Path: model/attributes/gen_ai/gen_ai__output__messages.json GEN_AI_OUTPUT_MESSAGES: Literal["gen_ai.output.messages"] = "gen_ai.output.messages" - """The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", answers: {...}}` with the answers keyed by field name, as the provider returned them. + """The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them. Type: str Apply Scrubbing: manual @@ -18644,7 +18644,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ], ), "gen_ai.input.messages": AttributeMetadata( - brief='The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', + brief='The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', type=AttributeType.STRING, keys=( "gen_ai.input.messages", @@ -18804,7 +18804,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ], ), "gen_ai.output.messages": AttributeMetadata( - brief='The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{type: "extraction", answers: {...}}` with the answers keyed by field name, as the provider returned them.', + brief='The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them.', type=AttributeType.STRING, keys=( "gen_ai.output.messages", From 2df50568bea98504c9852b13c3902d69f83eecff Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 20 Oct 2026 10:54:13 +0200 Subject: [PATCH 4/9] Move operation message shapes to additional context --- .../sentry-conventions/src/attributes.ts | 40 ++++++++++++++++--- javascript/sentry-conventions/src/search.ts | 4 +- .../gen_ai/gen_ai__input__messages.json | 13 ++++-- .../gen_ai/gen_ai__output__messages.json | 13 ++++-- python/src/sentry_conventions/attributes.py | 30 +++++++++++--- 5 files changed, 80 insertions(+), 20 deletions(-) diff --git a/javascript/sentry-conventions/src/attributes.ts b/javascript/sentry-conventions/src/attributes.ts index 6a74ca8d..1a8e41de 100644 --- a/javascript/sentry-conventions/src/attributes.ts +++ b/javascript/sentry-conventions/src/attributes.ts @@ -7963,7 +7963,7 @@ export type GEN_AI_FUNCTION_ID_TYPE = string; // Path: model/attributes/gen_ai/gen_ai__input__messages.json /** - * The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them. `gen_ai.input.messages` + * The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. Some operations use a different shape. See the additional context. `gen_ai.input.messages` * * Attribute Value Type: `string` {@link GEN_AI_INPUT_MESSAGES_TYPE} * @@ -7975,6 +7975,7 @@ export type GEN_AI_FUNCTION_ID_TYPE = string; * Aliases: {@link AI_TEXTS} `ai.texts`, {@link AI_PROMPT_MESSAGES} `ai.prompt.messages`, {@link GEN_AI_PROMPT} `gen_ai.prompt`, {@link AI_PROMPT} `ai.prompt` * * @example "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]" + * @example "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00\", \"fields\": {\"invoice_number\": {\"type\": \"text\", \"instructions\": \"The invoice number\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"The date the payment is due\"}, \"total\": {\"type\": \"number\", \"unit\": \"USD\", \"decimals\": 2}}}]" */ export const GEN_AI_INPUT_MESSAGES = 'gen_ai.input.messages'; @@ -8163,7 +8164,7 @@ export type GEN_AI_OPERATION_TYPE_TYPE = string; // Path: model/attributes/gen_ai/gen_ai__output__messages.json /** - * The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them. `gen_ai.output.messages` + * The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context. `gen_ai.output.messages` * * Attribute Value Type: `string` {@link GEN_AI_OUTPUT_MESSAGES_TYPE} * @@ -8175,6 +8176,7 @@ export type GEN_AI_OPERATION_TYPE_TYPE = string; * Aliases: {@link AI_RESPONSE_TOOLCALLS} `ai.response.toolCalls`, {@link AI_RESPONSE_TEXT} `ai.response.text` * * @example "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]" + * @example "[{\"answers\": {\"invoice_number\": {\"value\": \"INV-2291\", \"span\": [8, 16], \"confidence\": 0.99}, \"due_date\": {\"value\": \"2026-10-02\", \"confidence\": 0.97}, \"total\": {\"value\": 1080, \"confidence\": 0.98}}}]" */ export const GEN_AI_OUTPUT_MESSAGES = 'gen_ai.output.messages'; @@ -27874,7 +27876,7 @@ export const ATTRIBUTE_METADATA: Record = { }, 'gen_ai.input.messages': { brief: - 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', + 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. Some operations use a different shape. See the additional context.', type: 'string', keys: [ 'gen_ai.input.messages', @@ -27891,14 +27893,27 @@ export const ATTRIBUTE_METADATA: Record = { visibility: 'public', example: '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', + examples: [ + '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', + '[{"state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00", "fields": {"invoice_number": {"type": "text", "instructions": "The invoice number"}, "due_date": {"type": "date", "instructions": "The date the payment is due"}, "total": {"type": "number", "unit": "USD", "decimals": 2}}}]', + ], aliases: ['ai.texts', 'ai.prompt.messages', 'gen_ai.prompt', 'ai.prompt'], changelog: [ - { version: 'next', prs: [728], description: 'Describe the extraction message shape for gen_ai.extract' }, + { + version: 'next', + prs: [728], + description: + 'Describe the extraction message shape for gen_ai.extract and move operation-specific shapes to additional context', + }, { version: '0.26.0', prs: [650], description: 'Describe the evaluation message shape for gen_ai.evaluate' }, { version: '0.21.0', prs: [583], description: 'Added ai.prompt as an alias' }, { version: '0.5.0', prs: [264] }, { version: '0.4.0', prs: [221] }, ], + additionalContext: [ + 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them.', + 'For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs.', + ], }, 'gen_ai.memory.query.text': { brief: @@ -28014,7 +28029,7 @@ export const ATTRIBUTE_METADATA: Record = { }, 'gen_ai.output.messages': { brief: - 'The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them.', + "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context.", type: 'string', keys: ['gen_ai.output.messages', 'ai.response.text', 'ai.response.toolCalls', 'ai.responses', 'ai.tool_calls'], applyScrubbing: { @@ -28024,12 +28039,25 @@ export const ATTRIBUTE_METADATA: Record = { visibility: 'public', example: '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', + examples: [ + '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', + '[{"answers": {"invoice_number": {"value": "INV-2291", "span": [8, 16], "confidence": 0.99}, "due_date": {"value": "2026-10-02", "confidence": 0.97}, "total": {"value": 1080, "confidence": 0.98}}}]', + ], aliases: ['ai.response.toolCalls', 'ai.response.text'], changelog: [ - { version: 'next', prs: [728], description: 'Describe the extraction message shape for gen_ai.extract' }, + { + version: 'next', + prs: [728], + description: + 'Describe the extraction message shape for gen_ai.extract and move operation-specific shapes to additional context', + }, { version: '0.26.0', prs: [650], description: 'Describe the evaluation message shape for gen_ai.evaluate' }, { version: '0.4.0', prs: [221] }, ], + additionalContext: [ + 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them.', + 'For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`.', + ], }, 'gen_ai.pipeline.name': { brief: 'Name of the AI pipeline or chain being executed.', diff --git a/javascript/sentry-conventions/src/search.ts b/javascript/sentry-conventions/src/search.ts index 41fe1ec6..514664fe 100644 --- a/javascript/sentry-conventions/src/search.ts +++ b/javascript/sentry-conventions/src/search.ts @@ -8495,7 +8495,7 @@ export const ATTRIBUTE_SEARCH_METADATA: Record canonicalName: 'gen_ai.input.messages', type: 'string', brief: - 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', + 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. Some operations use a different shape. See the additional context.', deprecationChain: [ 'gen_ai.input.messages', 'ai.input_messages', @@ -8558,7 +8558,7 @@ export const ATTRIBUTE_SEARCH_METADATA: Record canonicalName: 'gen_ai.output.messages', type: 'string', brief: - 'The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them.', + "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context.", deprecationChain: [ 'gen_ai.output.messages', 'ai.response.text', diff --git a/model/attributes/gen_ai/gen_ai__input__messages.json b/model/attributes/gen_ai/gen_ai__input__messages.json index 5af21920..e5404be8 100644 --- a/model/attributes/gen_ai/gen_ai__input__messages.json +++ b/model/attributes/gen_ai/gen_ai__input__messages.json @@ -1,19 +1,26 @@ { "key": "gen_ai.input.messages", - "brief": "The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `\"user\"`, `\"assistant\"`, `\"tool\"`, or `\"system\"`. For messages of the role `\"tool\"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: \"text\", text:\"...\"}`. For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.", + "brief": "The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `\"user\"`, `\"assistant\"`, `\"tool\"`, or `\"system\"`. For messages of the role `\"tool\"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: \"text\", text:\"...\"}`. Some operations use a different shape. See the additional context.", "type": "string", "apply_scrubbing": { "key": "manual" }, "is_in_otel": true, - "example": "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]", + "examples": [ + "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]", + "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00\", \"fields\": {\"invoice_number\": {\"type\": \"text\", \"instructions\": \"The invoice number\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"The date the payment is due\"}, \"total\": {\"type\": \"number\", \"unit\": \"USD\", \"decimals\": 2}}}]" + ], "alias": ["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], "visibility": "public", + "additional_context": [ + "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them.", + "For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs." + ], "changelog": [ { "version": "next", "prs": [728], - "description": "Describe the extraction message shape for gen_ai.extract" + "description": "Describe the extraction message shape for gen_ai.extract and move operation-specific shapes to additional context" }, { "version": "0.26.0", diff --git a/model/attributes/gen_ai/gen_ai__output__messages.json b/model/attributes/gen_ai/gen_ai__output__messages.json index 77708b6f..700e4db6 100644 --- a/model/attributes/gen_ai/gen_ai__output__messages.json +++ b/model/attributes/gen_ai/gen_ai__output__messages.json @@ -1,19 +1,26 @@ { "key": "gen_ai.output.messages", - "brief": "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them.", + "brief": "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context.", "type": "string", "apply_scrubbing": { "key": "manual" }, "is_in_otel": true, - "example": "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]", + "examples": [ + "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]", + "[{\"answers\": {\"invoice_number\": {\"value\": \"INV-2291\", \"span\": [8, 16], \"confidence\": 0.99}, \"due_date\": {\"value\": \"2026-10-02\", \"confidence\": 0.97}, \"total\": {\"value\": 1080, \"confidence\": 0.98}}}]" + ], "alias": ["ai.response.toolCalls", "ai.response.text"], "visibility": "public", + "additional_context": [ + "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them.", + "For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`." + ], "changelog": [ { "version": "next", "prs": [728], - "description": "Describe the extraction message shape for gen_ai.extract" + "description": "Describe the extraction message shape for gen_ai.extract and move operation-specific shapes to additional context" }, { "version": "0.26.0", diff --git a/python/src/sentry_conventions/attributes.py b/python/src/sentry_conventions/attributes.py index 5e3c38d2..cafd72b9 100644 --- a/python/src/sentry_conventions/attributes.py +++ b/python/src/sentry_conventions/attributes.py @@ -4917,7 +4917,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): # Path: model/attributes/gen_ai/gen_ai__input__messages.json GEN_AI_INPUT_MESSAGES: Literal["gen_ai.input.messages"] = "gen_ai.input.messages" - """The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them. + """The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. Some operations use a different shape. See the additional context. Type: str Apply Scrubbing: manual @@ -4925,6 +4925,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): Visibility: public Aliases: ai.texts, ai.prompt.messages, gen_ai.prompt, ai.prompt Example: "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]" + Example: "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00\", \"fields\": {\"invoice_number\": {\"type\": \"text\", \"instructions\": \"The invoice number\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"The date the payment is due\"}, \"total\": {\"type\": \"number\", \"unit\": \"USD\", \"decimals\": 2}}}]" """ # Path: model/attributes/gen_ai/gen_ai__memory__query__text.json @@ -5040,7 +5041,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): # Path: model/attributes/gen_ai/gen_ai__output__messages.json GEN_AI_OUTPUT_MESSAGES: Literal["gen_ai.output.messages"] = "gen_ai.output.messages" - """The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them. + """The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context. Type: str Apply Scrubbing: manual @@ -5048,6 +5049,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): Visibility: public Aliases: ai.response.toolCalls, ai.response.text Example: "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]" + Example: "[{\"answers\": {\"invoice_number\": {\"value\": \"INV-2291\", \"span\": [8, 16], \"confidence\": 0.99}, \"due_date\": {\"value\": \"2026-10-02\", \"confidence\": 0.97}, \"total\": {\"value\": 1080, \"confidence\": 0.98}}}]" """ # Path: model/attributes/gen_ai/gen_ai__pipeline__name.json @@ -18644,7 +18646,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ], ), "gen_ai.input.messages": AttributeMetadata( - brief='The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}` with the evaluated state and the questions keyed by name, as the caller passed them. For `gen_ai.extract` operations, the array holds one object `{state: ..., fields: {...}}` with the input state and the field definitions keyed by name, as the caller passed them.', + brief='The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. Some operations use a different shape. See the additional context.', type=AttributeType.STRING, keys=( "gen_ai.input.messages", @@ -18658,12 +18660,16 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): is_in_otel=True, visibility=Visibility.PUBLIC, example='[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', + examples=[ + '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', + '[{"state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00", "fields": {"invoice_number": {"type": "text", "instructions": "The invoice number"}, "due_date": {"type": "date", "instructions": "The date the payment is due"}, "total": {"type": "number", "unit": "USD", "decimals": 2}}}]', + ], aliases=["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], changelog=[ ChangelogEntry( version="next", prs=[728], - description="Describe the extraction message shape for gen_ai.extract", + description="Describe the extraction message shape for gen_ai.extract and move operation-specific shapes to additional context", ), ChangelogEntry( version="0.26.0", @@ -18676,6 +18682,10 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ChangelogEntry(version="0.5.0", prs=[264]), ChangelogEntry(version="0.4.0", prs=[221]), ], + additional_context=[ + 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them.', + "For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs.", + ], ), "gen_ai.memory.query.text": AttributeMetadata( brief="The search query used to retrieve memories. Only applicable to 'search_memory'. Opt-in: instrumentations SHOULD NOT capture this by default and SHOULD gate it behind explicit user opt-in, as it may contain sensitive information.", @@ -18804,7 +18814,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ], ), "gen_ai.output.messages": AttributeMetadata( - brief='The model\'s response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}` with the answers keyed by question name, as the provider returned them. For `gen_ai.extract` operations, the array holds one object `{answers: {...}}` with the answers keyed by field name, as the provider returned them.', + brief="The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context.", type=AttributeType.STRING, keys=( "gen_ai.output.messages", @@ -18817,12 +18827,16 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): is_in_otel=True, visibility=Visibility.PUBLIC, example='[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', + examples=[ + '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', + '[{"answers": {"invoice_number": {"value": "INV-2291", "span": [8, 16], "confidence": 0.99}, "due_date": {"value": "2026-10-02", "confidence": 0.97}, "total": {"value": 1080, "confidence": 0.98}}}]', + ], aliases=["ai.response.toolCalls", "ai.response.text"], changelog=[ ChangelogEntry( version="next", prs=[728], - description="Describe the extraction message shape for gen_ai.extract", + description="Describe the extraction message shape for gen_ai.extract and move operation-specific shapes to additional context", ), ChangelogEntry( version="0.26.0", @@ -18831,6 +18845,10 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ), ChangelogEntry(version="0.4.0", prs=[221]), ], + additional_context=[ + 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them.', + "For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`.", + ], ), "gen_ai.pipeline.name": AttributeMetadata( brief="Name of the AI pipeline or chain being executed.", From 48dfc63b581469ab0322d92697ecb862a188f30c Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 20 Oct 2026 11:07:40 +0200 Subject: [PATCH 5/9] Add decide example and label examples by order --- .../sentry-conventions/src/attributes.ts | 20 +++++++++++-------- javascript/sentry-conventions/src/search.ts | 4 ++-- .../gen_ai/gen_ai__input__messages.json | 7 ++++--- .../gen_ai/gen_ai__output__messages.json | 7 ++++--- python/src/sentry_conventions/attributes.py | 20 +++++++++++-------- 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/javascript/sentry-conventions/src/attributes.ts b/javascript/sentry-conventions/src/attributes.ts index 1a8e41de..bf0c3a31 100644 --- a/javascript/sentry-conventions/src/attributes.ts +++ b/javascript/sentry-conventions/src/attributes.ts @@ -7963,7 +7963,7 @@ export type GEN_AI_FUNCTION_ID_TYPE = string; // Path: model/attributes/gen_ai/gen_ai__input__messages.json /** - * The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. Some operations use a different shape. See the additional context. `gen_ai.input.messages` + * The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. The first example shows this shape. Some operations use a different shape. See the additional context. `gen_ai.input.messages` * * Attribute Value Type: `string` {@link GEN_AI_INPUT_MESSAGES_TYPE} * @@ -7975,6 +7975,7 @@ export type GEN_AI_FUNCTION_ID_TYPE = string; * Aliases: {@link AI_TEXTS} `ai.texts`, {@link AI_PROMPT_MESSAGES} `ai.prompt.messages`, {@link GEN_AI_PROMPT} `gen_ai.prompt`, {@link AI_PROMPT} `ai.prompt` * * @example "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]" + * @example "[[{\"type\": \"evaluation\", \"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]]" * @example "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00\", \"fields\": {\"invoice_number\": {\"type\": \"text\", \"instructions\": \"The invoice number\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"The date the payment is due\"}, \"total\": {\"type\": \"number\", \"unit\": \"USD\", \"decimals\": 2}}}]" */ export const GEN_AI_INPUT_MESSAGES = 'gen_ai.input.messages'; @@ -8164,7 +8165,7 @@ export type GEN_AI_OPERATION_TYPE_TYPE = string; // Path: model/attributes/gen_ai/gen_ai__output__messages.json /** - * The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context. `gen_ai.output.messages` + * The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. The first example shows this shape. Some operations use a different shape. See the additional context. `gen_ai.output.messages` * * Attribute Value Type: `string` {@link GEN_AI_OUTPUT_MESSAGES_TYPE} * @@ -8176,6 +8177,7 @@ export type GEN_AI_OPERATION_TYPE_TYPE = string; * Aliases: {@link AI_RESPONSE_TOOLCALLS} `ai.response.toolCalls`, {@link AI_RESPONSE_TEXT} `ai.response.text` * * @example "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]" + * @example "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]" * @example "[{\"answers\": {\"invoice_number\": {\"value\": \"INV-2291\", \"span\": [8, 16], \"confidence\": 0.99}, \"due_date\": {\"value\": \"2026-10-02\", \"confidence\": 0.97}, \"total\": {\"value\": 1080, \"confidence\": 0.98}}}]" */ export const GEN_AI_OUTPUT_MESSAGES = 'gen_ai.output.messages'; @@ -27876,7 +27878,7 @@ export const ATTRIBUTE_METADATA: Record = { }, 'gen_ai.input.messages': { brief: - 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. Some operations use a different shape. See the additional context.', + 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. The first example shows this shape. Some operations use a different shape. See the additional context.', type: 'string', keys: [ 'gen_ai.input.messages', @@ -27895,6 +27897,7 @@ export const ATTRIBUTE_METADATA: Record = { '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', examples: [ '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', + '[[{"type": "evaluation", "state": "I cannot log in, and I also want a refund for last month.", "questions": {"authIssue": {"type": "noul", "instructions": "Is there a login problem?"}, "department": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "Charges and refunds", "technical": "Bugs and outages"}}}}]]', '[{"state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00", "fields": {"invoice_number": {"type": "text", "instructions": "The invoice number"}, "due_date": {"type": "date", "instructions": "The date the payment is due"}, "total": {"type": "number", "unit": "USD", "decimals": 2}}}]', ], aliases: ['ai.texts', 'ai.prompt.messages', 'gen_ai.prompt', 'ai.prompt'], @@ -27911,8 +27914,8 @@ export const ATTRIBUTE_METADATA: Record = { { version: '0.4.0', prs: [221] }, ], additionalContext: [ - 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them.', - 'For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs.', + 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. The second example shows this shape.', + 'For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs. The third example shows this shape.', ], }, 'gen_ai.memory.query.text': { @@ -28029,7 +28032,7 @@ export const ATTRIBUTE_METADATA: Record = { }, 'gen_ai.output.messages': { brief: - "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context.", + "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. The first example shows this shape. Some operations use a different shape. See the additional context.", type: 'string', keys: ['gen_ai.output.messages', 'ai.response.text', 'ai.response.toolCalls', 'ai.responses', 'ai.tool_calls'], applyScrubbing: { @@ -28041,6 +28044,7 @@ export const ATTRIBUTE_METADATA: Record = { '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', examples: [ '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', + '[[{"type": "evaluation", "answers": {"authIssue": {"type": "noul", "noul": 0.98}, "department": {"type": "choice", "choice": "billing", "confidence": 0.28, "probabilities": {"billing": 0.64, "technical": 0.36}}}}]]', '[{"answers": {"invoice_number": {"value": "INV-2291", "span": [8, 16], "confidence": 0.99}, "due_date": {"value": "2026-10-02", "confidence": 0.97}, "total": {"value": 1080, "confidence": 0.98}}}]', ], aliases: ['ai.response.toolCalls', 'ai.response.text'], @@ -28055,8 +28059,8 @@ export const ATTRIBUTE_METADATA: Record = { { version: '0.4.0', prs: [221] }, ], additionalContext: [ - 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them.', - 'For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`.', + 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.', + 'For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`. The third example shows this shape.', ], }, 'gen_ai.pipeline.name': { diff --git a/javascript/sentry-conventions/src/search.ts b/javascript/sentry-conventions/src/search.ts index 514664fe..36fbf84c 100644 --- a/javascript/sentry-conventions/src/search.ts +++ b/javascript/sentry-conventions/src/search.ts @@ -8495,7 +8495,7 @@ export const ATTRIBUTE_SEARCH_METADATA: Record canonicalName: 'gen_ai.input.messages', type: 'string', brief: - 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. Some operations use a different shape. See the additional context.', + 'The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. The first example shows this shape. Some operations use a different shape. See the additional context.', deprecationChain: [ 'gen_ai.input.messages', 'ai.input_messages', @@ -8558,7 +8558,7 @@ export const ATTRIBUTE_SEARCH_METADATA: Record canonicalName: 'gen_ai.output.messages', type: 'string', brief: - "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context.", + "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. The first example shows this shape. Some operations use a different shape. See the additional context.", deprecationChain: [ 'gen_ai.output.messages', 'ai.response.text', diff --git a/model/attributes/gen_ai/gen_ai__input__messages.json b/model/attributes/gen_ai/gen_ai__input__messages.json index e5404be8..d609791e 100644 --- a/model/attributes/gen_ai/gen_ai__input__messages.json +++ b/model/attributes/gen_ai/gen_ai__input__messages.json @@ -1,6 +1,6 @@ { "key": "gen_ai.input.messages", - "brief": "The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `\"user\"`, `\"assistant\"`, `\"tool\"`, or `\"system\"`. For messages of the role `\"tool\"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: \"text\", text:\"...\"}`. Some operations use a different shape. See the additional context.", + "brief": "The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `\"user\"`, `\"assistant\"`, `\"tool\"`, or `\"system\"`. For messages of the role `\"tool\"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: \"text\", text:\"...\"}`. The first example shows this shape. Some operations use a different shape. See the additional context.", "type": "string", "apply_scrubbing": { "key": "manual" @@ -8,13 +8,14 @@ "is_in_otel": true, "examples": [ "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]", + "[[{\"type\": \"evaluation\", \"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]]", "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00\", \"fields\": {\"invoice_number\": {\"type\": \"text\", \"instructions\": \"The invoice number\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"The date the payment is due\"}, \"total\": {\"type\": \"number\", \"unit\": \"USD\", \"decimals\": 2}}}]" ], "alias": ["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], "visibility": "public", "additional_context": [ - "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them.", - "For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs." + "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. The second example shows this shape.", + "For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs. The third example shows this shape." ], "changelog": [ { diff --git a/model/attributes/gen_ai/gen_ai__output__messages.json b/model/attributes/gen_ai/gen_ai__output__messages.json index 700e4db6..66bc7a7e 100644 --- a/model/attributes/gen_ai/gen_ai__output__messages.json +++ b/model/attributes/gen_ai/gen_ai__output__messages.json @@ -1,6 +1,6 @@ { "key": "gen_ai.output.messages", - "brief": "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context.", + "brief": "The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. The first example shows this shape. Some operations use a different shape. See the additional context.", "type": "string", "apply_scrubbing": { "key": "manual" @@ -8,13 +8,14 @@ "is_in_otel": true, "examples": [ "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]", + "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]", "[{\"answers\": {\"invoice_number\": {\"value\": \"INV-2291\", \"span\": [8, 16], \"confidence\": 0.99}, \"due_date\": {\"value\": \"2026-10-02\", \"confidence\": 0.97}, \"total\": {\"value\": 1080, \"confidence\": 0.98}}}]" ], "alias": ["ai.response.toolCalls", "ai.response.text"], "visibility": "public", "additional_context": [ - "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them.", - "For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`." + "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.", + "For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`. The third example shows this shape." ], "changelog": [ { diff --git a/python/src/sentry_conventions/attributes.py b/python/src/sentry_conventions/attributes.py index cafd72b9..7b76dd12 100644 --- a/python/src/sentry_conventions/attributes.py +++ b/python/src/sentry_conventions/attributes.py @@ -4917,7 +4917,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): # Path: model/attributes/gen_ai/gen_ai__input__messages.json GEN_AI_INPUT_MESSAGES: Literal["gen_ai.input.messages"] = "gen_ai.input.messages" - """The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. Some operations use a different shape. See the additional context. + """The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. The first example shows this shape. Some operations use a different shape. See the additional context. Type: str Apply Scrubbing: manual @@ -4925,6 +4925,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): Visibility: public Aliases: ai.texts, ai.prompt.messages, gen_ai.prompt, ai.prompt Example: "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]" + Example: "[[{\"type\": \"evaluation\", \"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]]" Example: "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00\", \"fields\": {\"invoice_number\": {\"type\": \"text\", \"instructions\": \"The invoice number\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"The date the payment is due\"}, \"total\": {\"type\": \"number\", \"unit\": \"USD\", \"decimals\": 2}}}]" """ @@ -5041,7 +5042,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): # Path: model/attributes/gen_ai/gen_ai__output__messages.json GEN_AI_OUTPUT_MESSAGES: Literal["gen_ai.output.messages"] = "gen_ai.output.messages" - """The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context. + """The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. The first example shows this shape. Some operations use a different shape. See the additional context. Type: str Apply Scrubbing: manual @@ -5049,6 +5050,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): Visibility: public Aliases: ai.response.toolCalls, ai.response.text Example: "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]" + Example: "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]" Example: "[{\"answers\": {\"invoice_number\": {\"value\": \"INV-2291\", \"span\": [8, 16], \"confidence\": 0.99}, \"due_date\": {\"value\": \"2026-10-02\", \"confidence\": 0.97}, \"total\": {\"value\": 1080, \"confidence\": 0.98}}}]" """ @@ -18646,7 +18648,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ], ), "gen_ai.input.messages": AttributeMetadata( - brief='The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. Some operations use a different shape. See the additional context.', + brief='The messages passed to the model. It has to be a stringified version of an array of objects. The `role` attribute of each object must be `"user"`, `"assistant"`, `"tool"`, or `"system"`. For messages of the role `"tool"`, the `content` can be a string or an arbitrary object with information about the tool call. For other messages the `content` can be either a string or a list of objects in the format `{type: "text", text:"..."}`. The first example shows this shape. Some operations use a different shape. See the additional context.', type=AttributeType.STRING, keys=( "gen_ai.input.messages", @@ -18662,6 +18664,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): example='[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', examples=[ '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', + '[[{"type": "evaluation", "state": "I cannot log in, and I also want a refund for last month.", "questions": {"authIssue": {"type": "noul", "instructions": "Is there a login problem?"}, "department": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "Charges and refunds", "technical": "Bugs and outages"}}}}]]', '[{"state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00", "fields": {"invoice_number": {"type": "text", "instructions": "The invoice number"}, "due_date": {"type": "date", "instructions": "The date the payment is due"}, "total": {"type": "number", "unit": "USD", "decimals": 2}}}]', ], aliases=["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], @@ -18683,8 +18686,8 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ChangelogEntry(version="0.4.0", prs=[221]), ], additional_context=[ - 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them.', - "For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs.", + 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. The second example shows this shape.', + "For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs. The third example shows this shape.", ], ), "gen_ai.memory.query.text": AttributeMetadata( @@ -18814,7 +18817,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ], ), "gen_ai.output.messages": AttributeMetadata( - brief="The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. Some operations use a different shape. See the additional context.", + brief="The model's response messages. It has to be a stringified version of an array of message objects, which can include text responses and tool calls. The first example shows this shape. Some operations use a different shape. See the additional context.", type=AttributeType.STRING, keys=( "gen_ai.output.messages", @@ -18829,6 +18832,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): example='[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', examples=[ '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', + '[[{"type": "evaluation", "answers": {"authIssue": {"type": "noul", "noul": 0.98}, "department": {"type": "choice", "choice": "billing", "confidence": 0.28, "probabilities": {"billing": 0.64, "technical": 0.36}}}}]]', '[{"answers": {"invoice_number": {"value": "INV-2291", "span": [8, 16], "confidence": 0.99}, "due_date": {"value": "2026-10-02", "confidence": 0.97}, "total": {"value": 1080, "confidence": 0.98}}}]', ], aliases=["ai.response.toolCalls", "ai.response.text"], @@ -18846,8 +18850,8 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ChangelogEntry(version="0.4.0", prs=[221]), ], additional_context=[ - 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them.', - "For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`.", + 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.', + "For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`. The third example shows this shape.", ], ), "gen_ai.pipeline.name": AttributeMetadata( From 1462c3442344df569cd82903e62253f179cd4974 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 20 Oct 2026 11:45:20 +0200 Subject: [PATCH 6/9] Match extract output example to Clairic answers --- javascript/sentry-conventions/src/attributes.ts | 4 ++-- model/attributes/gen_ai/gen_ai__output__messages.json | 2 +- python/src/sentry_conventions/attributes.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/javascript/sentry-conventions/src/attributes.ts b/javascript/sentry-conventions/src/attributes.ts index bf0c3a31..85afd65a 100644 --- a/javascript/sentry-conventions/src/attributes.ts +++ b/javascript/sentry-conventions/src/attributes.ts @@ -8178,7 +8178,7 @@ export type GEN_AI_OPERATION_TYPE_TYPE = string; * * @example "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]" * @example "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]" - * @example "[{\"answers\": {\"invoice_number\": {\"value\": \"INV-2291\", \"span\": [8, 16], \"confidence\": 0.99}, \"due_date\": {\"value\": \"2026-10-02\", \"confidence\": 0.97}, \"total\": {\"value\": 1080, \"confidence\": 0.98}}}]" + * @example "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 0.01, \"guess\": \"2026-10-02\", \"confidence\": 0.97, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 0.01, \"guess\": 1080, \"confidence\": 0.98, \"value\": 1080}}}]" */ export const GEN_AI_OUTPUT_MESSAGES = 'gen_ai.output.messages'; @@ -28045,7 +28045,7 @@ export const ATTRIBUTE_METADATA: Record = { examples: [ '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', '[[{"type": "evaluation", "answers": {"authIssue": {"type": "noul", "noul": 0.98}, "department": {"type": "choice", "choice": "billing", "confidence": 0.28, "probabilities": {"billing": 0.64, "technical": 0.36}}}}]]', - '[{"answers": {"invoice_number": {"value": "INV-2291", "span": [8, 16], "confidence": 0.99}, "due_date": {"value": "2026-10-02", "confidence": 0.97}, "total": {"value": 1080, "confidence": 0.98}}}]', + '[{"answers": {"invoice_number": {"type": "text", "p_null": 3.8e-10, "span": [8, 16], "guess": "INV-2291", "confidence": 1, "value": "INV-2291"}, "due_date": {"type": "date", "p_null": 0.01, "guess": "2026-10-02", "confidence": 0.97, "value": "2026-10-02"}, "total": {"type": "number", "p_null": 0.01, "guess": 1080, "confidence": 0.98, "value": 1080}}}]', ], aliases: ['ai.response.toolCalls', 'ai.response.text'], changelog: [ diff --git a/model/attributes/gen_ai/gen_ai__output__messages.json b/model/attributes/gen_ai/gen_ai__output__messages.json index 66bc7a7e..f6246e3c 100644 --- a/model/attributes/gen_ai/gen_ai__output__messages.json +++ b/model/attributes/gen_ai/gen_ai__output__messages.json @@ -9,7 +9,7 @@ "examples": [ "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]", "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]", - "[{\"answers\": {\"invoice_number\": {\"value\": \"INV-2291\", \"span\": [8, 16], \"confidence\": 0.99}, \"due_date\": {\"value\": \"2026-10-02\", \"confidence\": 0.97}, \"total\": {\"value\": 1080, \"confidence\": 0.98}}}]" + "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 0.01, \"guess\": \"2026-10-02\", \"confidence\": 0.97, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 0.01, \"guess\": 1080, \"confidence\": 0.98, \"value\": 1080}}}]" ], "alias": ["ai.response.toolCalls", "ai.response.text"], "visibility": "public", diff --git a/python/src/sentry_conventions/attributes.py b/python/src/sentry_conventions/attributes.py index 7b76dd12..f503ff42 100644 --- a/python/src/sentry_conventions/attributes.py +++ b/python/src/sentry_conventions/attributes.py @@ -5051,7 +5051,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): Aliases: ai.response.toolCalls, ai.response.text Example: "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]" Example: "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]" - Example: "[{\"answers\": {\"invoice_number\": {\"value\": \"INV-2291\", \"span\": [8, 16], \"confidence\": 0.99}, \"due_date\": {\"value\": \"2026-10-02\", \"confidence\": 0.97}, \"total\": {\"value\": 1080, \"confidence\": 0.98}}}]" + Example: "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 0.01, \"guess\": \"2026-10-02\", \"confidence\": 0.97, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 0.01, \"guess\": 1080, \"confidence\": 0.98, \"value\": 1080}}}]" """ # Path: model/attributes/gen_ai/gen_ai__pipeline__name.json @@ -18833,7 +18833,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): examples=[ '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', '[[{"type": "evaluation", "answers": {"authIssue": {"type": "noul", "noul": 0.98}, "department": {"type": "choice", "choice": "billing", "confidence": 0.28, "probabilities": {"billing": 0.64, "technical": 0.36}}}}]]', - '[{"answers": {"invoice_number": {"value": "INV-2291", "span": [8, 16], "confidence": 0.99}, "due_date": {"value": "2026-10-02", "confidence": 0.97}, "total": {"value": 1080, "confidence": 0.98}}}]', + '[{"answers": {"invoice_number": {"type": "text", "p_null": 3.8e-10, "span": [8, 16], "guess": "INV-2291", "confidence": 1, "value": "INV-2291"}, "due_date": {"type": "date", "p_null": 0.01, "guess": "2026-10-02", "confidence": 0.97, "value": "2026-10-02"}, "total": {"type": "number", "p_null": 0.01, "guess": 1080, "confidence": 0.98, "value": 1080}}}]', ], aliases=["ai.response.toolCalls", "ai.response.text"], changelog=[ From 1309f7c25d162648a7a596f34e73f302f272f9f7 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 20 Oct 2026 14:30:34 +0200 Subject: [PATCH 7/9] Align extract message shapes with Clairic schemas --- javascript/sentry-conventions/src/attributes.ts | 12 ++++++------ model/attributes/gen_ai/gen_ai__input__messages.json | 4 ++-- .../attributes/gen_ai/gen_ai__output__messages.json | 4 ++-- python/src/sentry_conventions/attributes.py | 12 ++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/javascript/sentry-conventions/src/attributes.ts b/javascript/sentry-conventions/src/attributes.ts index 85afd65a..302cd779 100644 --- a/javascript/sentry-conventions/src/attributes.ts +++ b/javascript/sentry-conventions/src/attributes.ts @@ -7976,7 +7976,7 @@ export type GEN_AI_FUNCTION_ID_TYPE = string; * * @example "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]" * @example "[[{\"type\": \"evaluation\", \"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]]" - * @example "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00\", \"fields\": {\"invoice_number\": {\"type\": \"text\", \"instructions\": \"The invoice number\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"The date the payment is due\"}, \"total\": {\"type\": \"number\", \"unit\": \"USD\", \"decimals\": 2}}}]" + * @example "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.\", \"fields\": {\"invoice_number\": {\"type\": \"text\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"Issue date plus the net payment days\"}, \"total\": {\"type\": \"number\", \"decimals\": 2, \"unit\": \"USD\", \"instructions\": \"Amount due including shipping\"}, \"contacts\": {\"type\": \"list\", \"items\": \"text\"}, \"po_number\": {\"type\": \"text\", \"instructions\": \"Purchase order number\"}, \"days_to_pay\": {\"type\": \"estimate\", \"min\": 0, \"max\": 120, \"step\": 1, \"instructions\": \"Days after issue until this invoice is paid\"}}}]" */ export const GEN_AI_INPUT_MESSAGES = 'gen_ai.input.messages'; @@ -8178,7 +8178,7 @@ export type GEN_AI_OPERATION_TYPE_TYPE = string; * * @example "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]" * @example "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]" - * @example "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 0.01, \"guess\": \"2026-10-02\", \"confidence\": 0.97, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 0.01, \"guess\": 1080, \"confidence\": 0.98, \"value\": 1080}}}]" + * @example "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 1.9e-08, \"guess\": \"2026-10-02\", \"confidence\": 0.9999, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 2.3e-08, \"guess\": 1080, \"confidence\": 0.9999, \"value\": 1080}, \"contacts\": {\"type\": \"list\", \"value\": [\"Dana Ruiz\", \"Priya Shah\"], \"spans\": [[120, 129], [131, 141]], \"confidence\": 0.9999}, \"po_number\": {\"type\": \"text\", \"p_null\": 1, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 0.9995, \"value\": null}, \"days_to_pay\": {\"type\": \"estimate\", \"value\": 30, \"mean\": 29.535, \"median\": 30, \"p10\": 21, \"p90\": 38, \"p_below\": 5.9e-06, \"p_above\": 1.2e-05}}, \"truncated\": false}]" */ export const GEN_AI_OUTPUT_MESSAGES = 'gen_ai.output.messages'; @@ -27898,7 +27898,7 @@ export const ATTRIBUTE_METADATA: Record = { examples: [ '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', '[[{"type": "evaluation", "state": "I cannot log in, and I also want a refund for last month.", "questions": {"authIssue": {"type": "noul", "instructions": "Is there a login problem?"}, "department": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "Charges and refunds", "technical": "Bugs and outages"}}}}]]', - '[{"state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00", "fields": {"invoice_number": {"type": "text", "instructions": "The invoice number"}, "due_date": {"type": "date", "instructions": "The date the payment is due"}, "total": {"type": "number", "unit": "USD", "decimals": 2}}}]', + '[{"state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.", "fields": {"invoice_number": {"type": "text"}, "due_date": {"type": "date", "instructions": "Issue date plus the net payment days"}, "total": {"type": "number", "decimals": 2, "unit": "USD", "instructions": "Amount due including shipping"}, "contacts": {"type": "list", "items": "text"}, "po_number": {"type": "text", "instructions": "Purchase order number"}, "days_to_pay": {"type": "estimate", "min": 0, "max": 120, "step": 1, "instructions": "Days after issue until this invoice is paid"}}}]', ], aliases: ['ai.texts', 'ai.prompt.messages', 'gen_ai.prompt', 'ai.prompt'], changelog: [ @@ -27915,7 +27915,7 @@ export const ATTRIBUTE_METADATA: Record = { ], additionalContext: [ 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. The second example shows this shape.', - 'For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs. The third example shows this shape.', + 'For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with its MIME type, for example `"image/png"`. For a data URL, use the MIME type from the URL. For a base64 image object, use its `content_type`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape.', ], }, 'gen_ai.memory.query.text': { @@ -28045,7 +28045,7 @@ export const ATTRIBUTE_METADATA: Record = { examples: [ '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', '[[{"type": "evaluation", "answers": {"authIssue": {"type": "noul", "noul": 0.98}, "department": {"type": "choice", "choice": "billing", "confidence": 0.28, "probabilities": {"billing": 0.64, "technical": 0.36}}}}]]', - '[{"answers": {"invoice_number": {"type": "text", "p_null": 3.8e-10, "span": [8, 16], "guess": "INV-2291", "confidence": 1, "value": "INV-2291"}, "due_date": {"type": "date", "p_null": 0.01, "guess": "2026-10-02", "confidence": 0.97, "value": "2026-10-02"}, "total": {"type": "number", "p_null": 0.01, "guess": 1080, "confidence": 0.98, "value": 1080}}}]', + '[{"answers": {"invoice_number": {"type": "text", "p_null": 3.8e-10, "span": [8, 16], "guess": "INV-2291", "confidence": 1, "value": "INV-2291"}, "due_date": {"type": "date", "p_null": 1.9e-08, "guess": "2026-10-02", "confidence": 0.9999, "value": "2026-10-02"}, "total": {"type": "number", "p_null": 2.3e-08, "guess": 1080, "confidence": 0.9999, "value": 1080}, "contacts": {"type": "list", "value": ["Dana Ruiz", "Priya Shah"], "spans": [[120, 129], [131, 141]], "confidence": 0.9999}, "po_number": {"type": "text", "p_null": 1, "span": [8, 16], "guess": "INV-2291", "confidence": 0.9995, "value": null}, "days_to_pay": {"type": "estimate", "value": 30, "mean": 29.535, "median": 30, "p10": 21, "p90": 38, "p_below": 5.9e-06, "p_above": 1.2e-05}}, "truncated": false}]', ], aliases: ['ai.response.toolCalls', 'ai.response.text'], changelog: [ @@ -28060,7 +28060,7 @@ export const ATTRIBUTE_METADATA: Record = { ], additionalContext: [ 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.', - 'For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`. The third example shows this shape.', + 'For `gen_ai.extract` operations, the array holds one object `{answers: {: }, truncated: boolean, state_text?: string}`. This object is the response body as the provider returned it, without `model` and `usage`. Do not change the values. `answers` holds one answer for each field in the input, keyed by field name. A field that the model cannot determine has a `value` of `null`. `span` and `spans` are `[start, end]` character offsets into `state` (or into `state_text`, if the provider returns it), and `end` is exclusive. Set the model in `gen_ai.response.model` and the token counts in `gen_ai.usage.input_tokens` and `gen_ai.usage.output_tokens`. The third example shows this shape.', ], }, 'gen_ai.pipeline.name': { diff --git a/model/attributes/gen_ai/gen_ai__input__messages.json b/model/attributes/gen_ai/gen_ai__input__messages.json index d609791e..277354f8 100644 --- a/model/attributes/gen_ai/gen_ai__input__messages.json +++ b/model/attributes/gen_ai/gen_ai__input__messages.json @@ -9,13 +9,13 @@ "examples": [ "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]", "[[{\"type\": \"evaluation\", \"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]]", - "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00\", \"fields\": {\"invoice_number\": {\"type\": \"text\", \"instructions\": \"The invoice number\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"The date the payment is due\"}, \"total\": {\"type\": \"number\", \"unit\": \"USD\", \"decimals\": 2}}}]" + "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.\", \"fields\": {\"invoice_number\": {\"type\": \"text\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"Issue date plus the net payment days\"}, \"total\": {\"type\": \"number\", \"decimals\": 2, \"unit\": \"USD\", \"instructions\": \"Amount due including shipping\"}, \"contacts\": {\"type\": \"list\", \"items\": \"text\"}, \"po_number\": {\"type\": \"text\", \"instructions\": \"Purchase order number\"}, \"days_to_pay\": {\"type\": \"estimate\", \"min\": 0, \"max\": 120, \"step\": 1, \"instructions\": \"Days after issue until this invoice is paid\"}}}]" ], "alias": ["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], "visibility": "public", "additional_context": [ "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. The second example shows this shape.", - "For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs. The third example shows this shape." + "For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with its MIME type, for example `\"image/png\"`. For a data URL, use the MIME type from the URL. For a base64 image object, use its `content_type`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape." ], "changelog": [ { diff --git a/model/attributes/gen_ai/gen_ai__output__messages.json b/model/attributes/gen_ai/gen_ai__output__messages.json index f6246e3c..88b1345f 100644 --- a/model/attributes/gen_ai/gen_ai__output__messages.json +++ b/model/attributes/gen_ai/gen_ai__output__messages.json @@ -9,13 +9,13 @@ "examples": [ "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]", "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]", - "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 0.01, \"guess\": \"2026-10-02\", \"confidence\": 0.97, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 0.01, \"guess\": 1080, \"confidence\": 0.98, \"value\": 1080}}}]" + "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 1.9e-08, \"guess\": \"2026-10-02\", \"confidence\": 0.9999, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 2.3e-08, \"guess\": 1080, \"confidence\": 0.9999, \"value\": 1080}, \"contacts\": {\"type\": \"list\", \"value\": [\"Dana Ruiz\", \"Priya Shah\"], \"spans\": [[120, 129], [131, 141]], \"confidence\": 0.9999}, \"po_number\": {\"type\": \"text\", \"p_null\": 1, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 0.9995, \"value\": null}, \"days_to_pay\": {\"type\": \"estimate\", \"value\": 30, \"mean\": 29.535, \"median\": 30, \"p10\": 21, \"p90\": 38, \"p_below\": 5.9e-06, \"p_above\": 1.2e-05}}, \"truncated\": false}]" ], "alias": ["ai.response.toolCalls", "ai.response.text"], "visibility": "public", "additional_context": [ "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.", - "For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`. The third example shows this shape." + "For `gen_ai.extract` operations, the array holds one object `{answers: {: }, truncated: boolean, state_text?: string}`. This object is the response body as the provider returned it, without `model` and `usage`. Do not change the values. `answers` holds one answer for each field in the input, keyed by field name. A field that the model cannot determine has a `value` of `null`. `span` and `spans` are `[start, end]` character offsets into `state` (or into `state_text`, if the provider returns it), and `end` is exclusive. Set the model in `gen_ai.response.model` and the token counts in `gen_ai.usage.input_tokens` and `gen_ai.usage.output_tokens`. The third example shows this shape." ], "changelog": [ { diff --git a/python/src/sentry_conventions/attributes.py b/python/src/sentry_conventions/attributes.py index f503ff42..a2826f42 100644 --- a/python/src/sentry_conventions/attributes.py +++ b/python/src/sentry_conventions/attributes.py @@ -4926,7 +4926,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): Aliases: ai.texts, ai.prompt.messages, gen_ai.prompt, ai.prompt Example: "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]" Example: "[[{\"type\": \"evaluation\", \"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]]" - Example: "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00\", \"fields\": {\"invoice_number\": {\"type\": \"text\", \"instructions\": \"The invoice number\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"The date the payment is due\"}, \"total\": {\"type\": \"number\", \"unit\": \"USD\", \"decimals\": 2}}}]" + Example: "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.\", \"fields\": {\"invoice_number\": {\"type\": \"text\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"Issue date plus the net payment days\"}, \"total\": {\"type\": \"number\", \"decimals\": 2, \"unit\": \"USD\", \"instructions\": \"Amount due including shipping\"}, \"contacts\": {\"type\": \"list\", \"items\": \"text\"}, \"po_number\": {\"type\": \"text\", \"instructions\": \"Purchase order number\"}, \"days_to_pay\": {\"type\": \"estimate\", \"min\": 0, \"max\": 120, \"step\": 1, \"instructions\": \"Days after issue until this invoice is paid\"}}}]" """ # Path: model/attributes/gen_ai/gen_ai__memory__query__text.json @@ -5051,7 +5051,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): Aliases: ai.response.toolCalls, ai.response.text Example: "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]" Example: "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]" - Example: "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 0.01, \"guess\": \"2026-10-02\", \"confidence\": 0.97, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 0.01, \"guess\": 1080, \"confidence\": 0.98, \"value\": 1080}}}]" + Example: "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 1.9e-08, \"guess\": \"2026-10-02\", \"confidence\": 0.9999, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 2.3e-08, \"guess\": 1080, \"confidence\": 0.9999, \"value\": 1080}, \"contacts\": {\"type\": \"list\", \"value\": [\"Dana Ruiz\", \"Priya Shah\"], \"spans\": [[120, 129], [131, 141]], \"confidence\": 0.9999}, \"po_number\": {\"type\": \"text\", \"p_null\": 1, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 0.9995, \"value\": null}, \"days_to_pay\": {\"type\": \"estimate\", \"value\": 30, \"mean\": 29.535, \"median\": 30, \"p10\": 21, \"p90\": 38, \"p_below\": 5.9e-06, \"p_above\": 1.2e-05}}, \"truncated\": false}]" """ # Path: model/attributes/gen_ai/gen_ai__pipeline__name.json @@ -18665,7 +18665,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): examples=[ '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', '[[{"type": "evaluation", "state": "I cannot log in, and I also want a refund for last month.", "questions": {"authIssue": {"type": "noul", "instructions": "Is there a login problem?"}, "department": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "Charges and refunds", "technical": "Bugs and outages"}}}}]]', - '[{"state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. Total: $1,080.00", "fields": {"invoice_number": {"type": "text", "instructions": "The invoice number"}, "due_date": {"type": "date", "instructions": "The date the payment is due"}, "total": {"type": "number", "unit": "USD", "decimals": 2}}}]', + '[{"state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.", "fields": {"invoice_number": {"type": "text"}, "due_date": {"type": "date", "instructions": "Issue date plus the net payment days"}, "total": {"type": "number", "decimals": 2, "unit": "USD", "instructions": "Amount due including shipping"}, "contacts": {"type": "list", "items": "text"}, "po_number": {"type": "text", "instructions": "Purchase order number"}, "days_to_pay": {"type": "estimate", "min": 0, "max": 120, "step": 1, "instructions": "Days after issue until this invoice is paid"}}}]', ], aliases=["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], changelog=[ @@ -18687,7 +18687,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ], additional_context=[ 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. The second example shows this shape.', - "For `gen_ai.extract` operations, the array holds one object `{state: string, fields: {: }}`. `state` is the input text that the model reads. `fields` holds the field specs keyed by field name, as the caller passed them. Do not change the field specs. The third example shows this shape.", + 'For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with its MIME type, for example `"image/png"`. For a data URL, use the MIME type from the URL. For a base64 image object, use its `content_type`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape.', ], ), "gen_ai.memory.query.text": AttributeMetadata( @@ -18833,7 +18833,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): examples=[ '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', '[[{"type": "evaluation", "answers": {"authIssue": {"type": "noul", "noul": 0.98}, "department": {"type": "choice", "choice": "billing", "confidence": 0.28, "probabilities": {"billing": 0.64, "technical": 0.36}}}}]]', - '[{"answers": {"invoice_number": {"type": "text", "p_null": 3.8e-10, "span": [8, 16], "guess": "INV-2291", "confidence": 1, "value": "INV-2291"}, "due_date": {"type": "date", "p_null": 0.01, "guess": "2026-10-02", "confidence": 0.97, "value": "2026-10-02"}, "total": {"type": "number", "p_null": 0.01, "guess": 1080, "confidence": 0.98, "value": 1080}}}]', + '[{"answers": {"invoice_number": {"type": "text", "p_null": 3.8e-10, "span": [8, 16], "guess": "INV-2291", "confidence": 1, "value": "INV-2291"}, "due_date": {"type": "date", "p_null": 1.9e-08, "guess": "2026-10-02", "confidence": 0.9999, "value": "2026-10-02"}, "total": {"type": "number", "p_null": 2.3e-08, "guess": 1080, "confidence": 0.9999, "value": 1080}, "contacts": {"type": "list", "value": ["Dana Ruiz", "Priya Shah"], "spans": [[120, 129], [131, 141]], "confidence": 0.9999}, "po_number": {"type": "text", "p_null": 1, "span": [8, 16], "guess": "INV-2291", "confidence": 0.9995, "value": null}, "days_to_pay": {"type": "estimate", "value": 30, "mean": 29.535, "median": 30, "p10": 21, "p90": 38, "p_below": 5.9e-06, "p_above": 1.2e-05}}, "truncated": false}]', ], aliases=["ai.response.toolCalls", "ai.response.text"], changelog=[ @@ -18851,7 +18851,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ], additional_context=[ 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.', - "For `gen_ai.extract` operations, the array holds one object `{answers: {: }}`. `answers` holds one answer for each field in the input, keyed by field name, as the provider returned them. Do not change the answers. A field that the model cannot determine has a `value` of `null`. The third example shows this shape.", + "For `gen_ai.extract` operations, the array holds one object `{answers: {: }, truncated: boolean, state_text?: string}`. This object is the response body as the provider returned it, without `model` and `usage`. Do not change the values. `answers` holds one answer for each field in the input, keyed by field name. A field that the model cannot determine has a `value` of `null`. `span` and `spans` are `[start, end]` character offsets into `state` (or into `state_text`, if the provider returns it), and `end` is exclusive. Set the model in `gen_ai.response.model` and the token counts in `gen_ai.usage.input_tokens` and `gen_ai.usage.output_tokens`. The third example shows this shape.", ], ), "gen_ai.pipeline.name": AttributeMetadata( From fefc8770caf07177da5c4f8772f364f6c712e1b1 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 20 Oct 2026 15:11:51 +0200 Subject: [PATCH 8/9] Replace binary data with [Blob substitute] --- javascript/sentry-conventions/src/attributes.ts | 4 ++-- model/attributes/gen_ai/gen_ai__input__messages.json | 4 ++-- python/src/sentry_conventions/attributes.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/javascript/sentry-conventions/src/attributes.ts b/javascript/sentry-conventions/src/attributes.ts index 302cd779..f43a0fa1 100644 --- a/javascript/sentry-conventions/src/attributes.ts +++ b/javascript/sentry-conventions/src/attributes.ts @@ -27914,8 +27914,8 @@ export const ATTRIBUTE_METADATA: Record = { { version: '0.4.0', prs: [221] }, ], additionalContext: [ - 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. The second example shows this shape.', - 'For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with its MIME type, for example `"image/png"`. For a data URL, use the MIME type from the URL. For a base64 image object, use its `content_type`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape.', + 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. Replace binary data in `state`, including `data:` URLs, with the string `"[Blob substitute]"`. The second example shows this shape.', + 'For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with the string `"[Blob substitute]"`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape.', ], }, 'gen_ai.memory.query.text': { diff --git a/model/attributes/gen_ai/gen_ai__input__messages.json b/model/attributes/gen_ai/gen_ai__input__messages.json index 277354f8..8d2e7844 100644 --- a/model/attributes/gen_ai/gen_ai__input__messages.json +++ b/model/attributes/gen_ai/gen_ai__input__messages.json @@ -14,8 +14,8 @@ "alias": ["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], "visibility": "public", "additional_context": [ - "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. The second example shows this shape.", - "For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with its MIME type, for example `\"image/png\"`. For a data URL, use the MIME type from the URL. For a base64 image object, use its `content_type`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape." + "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. Replace binary data in `state`, including `data:` URLs, with the string `\"[Blob substitute]\"`. The second example shows this shape.", + "For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with the string `\"[Blob substitute]\"`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape." ], "changelog": [ { diff --git a/python/src/sentry_conventions/attributes.py b/python/src/sentry_conventions/attributes.py index a2826f42..00169727 100644 --- a/python/src/sentry_conventions/attributes.py +++ b/python/src/sentry_conventions/attributes.py @@ -18686,8 +18686,8 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ChangelogEntry(version="0.4.0", prs=[221]), ], additional_context=[ - 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. The second example shows this shape.', - 'For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with its MIME type, for example `"image/png"`. For a data URL, use the MIME type from the URL. For a base64 image object, use its `content_type`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape.', + 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. Replace binary data in `state`, including `data:` URLs, with the string `"[Blob substitute]"`. The second example shows this shape.', + 'For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with the string `"[Blob substitute]"`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape.', ], ), "gen_ai.memory.query.text": AttributeMetadata( From a416700a52407fd00a02b6d74276d7d3ffebbcc5 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Tue, 20 Oct 2026 15:52:47 +0200 Subject: [PATCH 9/9] Remove type field from decide messages --- javascript/sentry-conventions/src/attributes.ts | 12 ++++++------ model/attributes/gen_ai/gen_ai__input__messages.json | 4 ++-- .../attributes/gen_ai/gen_ai__output__messages.json | 4 ++-- python/src/sentry_conventions/attributes.py | 12 ++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/javascript/sentry-conventions/src/attributes.ts b/javascript/sentry-conventions/src/attributes.ts index f43a0fa1..0ed2d961 100644 --- a/javascript/sentry-conventions/src/attributes.ts +++ b/javascript/sentry-conventions/src/attributes.ts @@ -7975,7 +7975,7 @@ export type GEN_AI_FUNCTION_ID_TYPE = string; * Aliases: {@link AI_TEXTS} `ai.texts`, {@link AI_PROMPT_MESSAGES} `ai.prompt.messages`, {@link GEN_AI_PROMPT} `gen_ai.prompt`, {@link AI_PROMPT} `ai.prompt` * * @example "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]" - * @example "[[{\"type\": \"evaluation\", \"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]]" + * @example "[{\"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]" * @example "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.\", \"fields\": {\"invoice_number\": {\"type\": \"text\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"Issue date plus the net payment days\"}, \"total\": {\"type\": \"number\", \"decimals\": 2, \"unit\": \"USD\", \"instructions\": \"Amount due including shipping\"}, \"contacts\": {\"type\": \"list\", \"items\": \"text\"}, \"po_number\": {\"type\": \"text\", \"instructions\": \"Purchase order number\"}, \"days_to_pay\": {\"type\": \"estimate\", \"min\": 0, \"max\": 120, \"step\": 1, \"instructions\": \"Days after issue until this invoice is paid\"}}}]" */ export const GEN_AI_INPUT_MESSAGES = 'gen_ai.input.messages'; @@ -8177,7 +8177,7 @@ export type GEN_AI_OPERATION_TYPE_TYPE = string; * Aliases: {@link AI_RESPONSE_TOOLCALLS} `ai.response.toolCalls`, {@link AI_RESPONSE_TEXT} `ai.response.text` * * @example "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]" - * @example "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]" + * @example "[{\"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]" * @example "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 1.9e-08, \"guess\": \"2026-10-02\", \"confidence\": 0.9999, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 2.3e-08, \"guess\": 1080, \"confidence\": 0.9999, \"value\": 1080}, \"contacts\": {\"type\": \"list\", \"value\": [\"Dana Ruiz\", \"Priya Shah\"], \"spans\": [[120, 129], [131, 141]], \"confidence\": 0.9999}, \"po_number\": {\"type\": \"text\", \"p_null\": 1, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 0.9995, \"value\": null}, \"days_to_pay\": {\"type\": \"estimate\", \"value\": 30, \"mean\": 29.535, \"median\": 30, \"p10\": 21, \"p90\": 38, \"p_below\": 5.9e-06, \"p_above\": 1.2e-05}}, \"truncated\": false}]" */ export const GEN_AI_OUTPUT_MESSAGES = 'gen_ai.output.messages'; @@ -27897,7 +27897,7 @@ export const ATTRIBUTE_METADATA: Record = { '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', examples: [ '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', - '[[{"type": "evaluation", "state": "I cannot log in, and I also want a refund for last month.", "questions": {"authIssue": {"type": "noul", "instructions": "Is there a login problem?"}, "department": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "Charges and refunds", "technical": "Bugs and outages"}}}}]]', + '[{"state": "I cannot log in, and I also want a refund for last month.", "questions": {"authIssue": {"type": "noul", "instructions": "Is there a login problem?"}, "department": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "Charges and refunds", "technical": "Bugs and outages"}}}}]', '[{"state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.", "fields": {"invoice_number": {"type": "text"}, "due_date": {"type": "date", "instructions": "Issue date plus the net payment days"}, "total": {"type": "number", "decimals": 2, "unit": "USD", "instructions": "Amount due including shipping"}, "contacts": {"type": "list", "items": "text"}, "po_number": {"type": "text", "instructions": "Purchase order number"}, "days_to_pay": {"type": "estimate", "min": 0, "max": 120, "step": 1, "instructions": "Days after issue until this invoice is paid"}}}]', ], aliases: ['ai.texts', 'ai.prompt.messages', 'gen_ai.prompt', 'ai.prompt'], @@ -27914,7 +27914,7 @@ export const ATTRIBUTE_METADATA: Record = { { version: '0.4.0', prs: [221] }, ], additionalContext: [ - 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. Replace binary data in `state`, including `data:` URLs, with the string `"[Blob substitute]"`. The second example shows this shape.', + 'For `gen_ai.decide` operations, the array holds one object `{state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. Replace binary data in `state`, including `data:` URLs, with the string `"[Blob substitute]"`. The second example shows this shape.', 'For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with the string `"[Blob substitute]"`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape.', ], }, @@ -28044,7 +28044,7 @@ export const ATTRIBUTE_METADATA: Record = { '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', examples: [ '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', - '[[{"type": "evaluation", "answers": {"authIssue": {"type": "noul", "noul": 0.98}, "department": {"type": "choice", "choice": "billing", "confidence": 0.28, "probabilities": {"billing": 0.64, "technical": 0.36}}}}]]', + '[{"answers": {"authIssue": {"type": "noul", "noul": 0.98}, "department": {"type": "choice", "choice": "billing", "confidence": 0.28, "probabilities": {"billing": 0.64, "technical": 0.36}}}}]', '[{"answers": {"invoice_number": {"type": "text", "p_null": 3.8e-10, "span": [8, 16], "guess": "INV-2291", "confidence": 1, "value": "INV-2291"}, "due_date": {"type": "date", "p_null": 1.9e-08, "guess": "2026-10-02", "confidence": 0.9999, "value": "2026-10-02"}, "total": {"type": "number", "p_null": 2.3e-08, "guess": 1080, "confidence": 0.9999, "value": 1080}, "contacts": {"type": "list", "value": ["Dana Ruiz", "Priya Shah"], "spans": [[120, 129], [131, 141]], "confidence": 0.9999}, "po_number": {"type": "text", "p_null": 1, "span": [8, 16], "guess": "INV-2291", "confidence": 0.9995, "value": null}, "days_to_pay": {"type": "estimate", "value": 30, "mean": 29.535, "median": 30, "p10": 21, "p90": 38, "p_below": 5.9e-06, "p_above": 1.2e-05}}, "truncated": false}]', ], aliases: ['ai.response.toolCalls', 'ai.response.text'], @@ -28059,7 +28059,7 @@ export const ATTRIBUTE_METADATA: Record = { { version: '0.4.0', prs: [221] }, ], additionalContext: [ - 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.', + 'For `gen_ai.decide` operations, the array holds one object `{answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.', 'For `gen_ai.extract` operations, the array holds one object `{answers: {: }, truncated: boolean, state_text?: string}`. This object is the response body as the provider returned it, without `model` and `usage`. Do not change the values. `answers` holds one answer for each field in the input, keyed by field name. A field that the model cannot determine has a `value` of `null`. `span` and `spans` are `[start, end]` character offsets into `state` (or into `state_text`, if the provider returns it), and `end` is exclusive. Set the model in `gen_ai.response.model` and the token counts in `gen_ai.usage.input_tokens` and `gen_ai.usage.output_tokens`. The third example shows this shape.', ], }, diff --git a/model/attributes/gen_ai/gen_ai__input__messages.json b/model/attributes/gen_ai/gen_ai__input__messages.json index 8d2e7844..d6957ff5 100644 --- a/model/attributes/gen_ai/gen_ai__input__messages.json +++ b/model/attributes/gen_ai/gen_ai__input__messages.json @@ -8,13 +8,13 @@ "is_in_otel": true, "examples": [ "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]", - "[[{\"type\": \"evaluation\", \"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]]", + "[{\"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]", "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.\", \"fields\": {\"invoice_number\": {\"type\": \"text\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"Issue date plus the net payment days\"}, \"total\": {\"type\": \"number\", \"decimals\": 2, \"unit\": \"USD\", \"instructions\": \"Amount due including shipping\"}, \"contacts\": {\"type\": \"list\", \"items\": \"text\"}, \"po_number\": {\"type\": \"text\", \"instructions\": \"Purchase order number\"}, \"days_to_pay\": {\"type\": \"estimate\", \"min\": 0, \"max\": 120, \"step\": 1, \"instructions\": \"Days after issue until this invoice is paid\"}}}]" ], "alias": ["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], "visibility": "public", "additional_context": [ - "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. Replace binary data in `state`, including `data:` URLs, with the string `\"[Blob substitute]\"`. The second example shows this shape.", + "For `gen_ai.decide` operations, the array holds one object `{state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. Replace binary data in `state`, including `data:` URLs, with the string `\"[Blob substitute]\"`. The second example shows this shape.", "For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with the string `\"[Blob substitute]\"`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape." ], "changelog": [ diff --git a/model/attributes/gen_ai/gen_ai__output__messages.json b/model/attributes/gen_ai/gen_ai__output__messages.json index 88b1345f..6c6e2887 100644 --- a/model/attributes/gen_ai/gen_ai__output__messages.json +++ b/model/attributes/gen_ai/gen_ai__output__messages.json @@ -8,13 +8,13 @@ "is_in_otel": true, "examples": [ "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]", - "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]", + "[{\"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]", "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 1.9e-08, \"guess\": \"2026-10-02\", \"confidence\": 0.9999, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 2.3e-08, \"guess\": 1080, \"confidence\": 0.9999, \"value\": 1080}, \"contacts\": {\"type\": \"list\", \"value\": [\"Dana Ruiz\", \"Priya Shah\"], \"spans\": [[120, 129], [131, 141]], \"confidence\": 0.9999}, \"po_number\": {\"type\": \"text\", \"p_null\": 1, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 0.9995, \"value\": null}, \"days_to_pay\": {\"type\": \"estimate\", \"value\": 30, \"mean\": 29.535, \"median\": 30, \"p10\": 21, \"p90\": 38, \"p_below\": 5.9e-06, \"p_above\": 1.2e-05}}, \"truncated\": false}]" ], "alias": ["ai.response.toolCalls", "ai.response.text"], "visibility": "public", "additional_context": [ - "For `gen_ai.decide` operations, the array holds one object `{type: \"evaluation\", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.", + "For `gen_ai.decide` operations, the array holds one object `{answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.", "For `gen_ai.extract` operations, the array holds one object `{answers: {: }, truncated: boolean, state_text?: string}`. This object is the response body as the provider returned it, without `model` and `usage`. Do not change the values. `answers` holds one answer for each field in the input, keyed by field name. A field that the model cannot determine has a `value` of `null`. `span` and `spans` are `[start, end]` character offsets into `state` (or into `state_text`, if the provider returns it), and `end` is exclusive. Set the model in `gen_ai.response.model` and the token counts in `gen_ai.usage.input_tokens` and `gen_ai.usage.output_tokens`. The third example shows this shape." ], "changelog": [ diff --git a/python/src/sentry_conventions/attributes.py b/python/src/sentry_conventions/attributes.py index 00169727..87180d9f 100644 --- a/python/src/sentry_conventions/attributes.py +++ b/python/src/sentry_conventions/attributes.py @@ -4925,7 +4925,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): Visibility: public Aliases: ai.texts, ai.prompt.messages, gen_ai.prompt, ai.prompt Example: "[{\"role\": \"user\", \"parts\": [{\"type\": \"text\", \"content\": \"Weather in Paris?\"}]}, {\"role\": \"assistant\", \"parts\": [{\"type\": \"tool_call\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"name\": \"get_weather\", \"arguments\": {\"location\": \"Paris\"}}]}, {\"role\": \"tool\", \"parts\": [{\"type\": \"tool_call_response\", \"id\": \"call_VSPygqKTWdrhaFErNvMV18Yl\", \"result\": \"rainy, 57°F\"}]}]" - Example: "[[{\"type\": \"evaluation\", \"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]]" + Example: "[{\"state\": \"I cannot log in, and I also want a refund for last month.\", \"questions\": {\"authIssue\": {\"type\": \"noul\", \"instructions\": \"Is there a login problem?\"}, \"department\": {\"type\": \"choice\", \"instructions\": \"Which team should handle this?\", \"criteria\": {\"billing\": \"Charges and refunds\", \"technical\": \"Bugs and outages\"}}}}]" Example: "[{\"state\": \"Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.\", \"fields\": {\"invoice_number\": {\"type\": \"text\"}, \"due_date\": {\"type\": \"date\", \"instructions\": \"Issue date plus the net payment days\"}, \"total\": {\"type\": \"number\", \"decimals\": 2, \"unit\": \"USD\", \"instructions\": \"Amount due including shipping\"}, \"contacts\": {\"type\": \"list\", \"items\": \"text\"}, \"po_number\": {\"type\": \"text\", \"instructions\": \"Purchase order number\"}, \"days_to_pay\": {\"type\": \"estimate\", \"min\": 0, \"max\": 120, \"step\": 1, \"instructions\": \"Days after issue until this invoice is paid\"}}}]" """ @@ -5050,7 +5050,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): Visibility: public Aliases: ai.response.toolCalls, ai.response.text Example: "[{\"role\": \"assistant\", \"parts\": [{\"type\": \"text\", \"content\": \"The weather in Paris is currently rainy with a temperature of 57°F.\"}], \"finish_reason\": \"stop\"}]" - Example: "[[{\"type\": \"evaluation\", \"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]]" + Example: "[{\"answers\": {\"authIssue\": {\"type\": \"noul\", \"noul\": 0.98}, \"department\": {\"type\": \"choice\", \"choice\": \"billing\", \"confidence\": 0.28, \"probabilities\": {\"billing\": 0.64, \"technical\": 0.36}}}}]" Example: "[{\"answers\": {\"invoice_number\": {\"type\": \"text\", \"p_null\": 3.8e-10, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 1, \"value\": \"INV-2291\"}, \"due_date\": {\"type\": \"date\", \"p_null\": 1.9e-08, \"guess\": \"2026-10-02\", \"confidence\": 0.9999, \"value\": \"2026-10-02\"}, \"total\": {\"type\": \"number\", \"p_null\": 2.3e-08, \"guess\": 1080, \"confidence\": 0.9999, \"value\": 1080}, \"contacts\": {\"type\": \"list\", \"value\": [\"Dana Ruiz\", \"Priya Shah\"], \"spans\": [[120, 129], [131, 141]], \"confidence\": 0.9999}, \"po_number\": {\"type\": \"text\", \"p_null\": 1, \"span\": [8, 16], \"guess\": \"INV-2291\", \"confidence\": 0.9995, \"value\": null}, \"days_to_pay\": {\"type\": \"estimate\", \"value\": 30, \"mean\": 29.535, \"median\": 30, \"p10\": 21, \"p90\": 38, \"p_below\": 5.9e-06, \"p_above\": 1.2e-05}}, \"truncated\": false}]" """ @@ -18664,7 +18664,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): example='[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', examples=[ '[{"role": "user", "parts": [{"type": "text", "content": "Weather in Paris?"}]}, {"role": "assistant", "parts": [{"type": "tool_call", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "name": "get_weather", "arguments": {"location": "Paris"}}]}, {"role": "tool", "parts": [{"type": "tool_call_response", "id": "call_VSPygqKTWdrhaFErNvMV18Yl", "result": "rainy, 57°F"}]}]', - '[[{"type": "evaluation", "state": "I cannot log in, and I also want a refund for last month.", "questions": {"authIssue": {"type": "noul", "instructions": "Is there a login problem?"}, "department": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "Charges and refunds", "technical": "Bugs and outages"}}}}]]', + '[{"state": "I cannot log in, and I also want a refund for last month.", "questions": {"authIssue": {"type": "noul", "instructions": "Is there a login problem?"}, "department": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "Charges and refunds", "technical": "Bugs and outages"}}}}]', '[{"state": "Invoice INV-2291 from Northwind Supply, issued 2026-09-02, net 30. 4 pallets at $250.00 each, shipping $80.00. Contact: Dana Ruiz, Priya Shah.", "fields": {"invoice_number": {"type": "text"}, "due_date": {"type": "date", "instructions": "Issue date plus the net payment days"}, "total": {"type": "number", "decimals": 2, "unit": "USD", "instructions": "Amount due including shipping"}, "contacts": {"type": "list", "items": "text"}, "po_number": {"type": "text", "instructions": "Purchase order number"}, "days_to_pay": {"type": "estimate", "min": 0, "max": 120, "step": 1, "instructions": "Days after issue until this invoice is paid"}}}]', ], aliases=["ai.texts", "ai.prompt.messages", "gen_ai.prompt", "ai.prompt"], @@ -18686,7 +18686,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ChangelogEntry(version="0.4.0", prs=[221]), ], additional_context=[ - 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. Replace binary data in `state`, including `data:` URLs, with the string `"[Blob substitute]"`. The second example shows this shape.', + 'For `gen_ai.decide` operations, the array holds one object `{state: ..., questions: {...}}`. `state` is the evaluated state. `questions` holds the questions keyed by name, as the caller passed them. Replace binary data in `state`, including `data:` URLs, with the string `"[Blob substitute]"`. The second example shows this shape.', 'For `gen_ai.extract` operations, the array holds one object `{state?: string, fields: {: }, images?: string[], reference_date?: string, options?: {...}}`. This object is the request body as the caller passed it, without `model`. Do not change the values, and leave out the keys that the caller did not set. Do not record the image data. Replace each image with the string `"[Blob substitute]"`. `state` is the text that the model reads. `fields` holds the field specs keyed by field name. Set the model in `gen_ai.request.model`. The third example shows this shape.', ], ), @@ -18832,7 +18832,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): example='[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', examples=[ '[{"role": "assistant", "parts": [{"type": "text", "content": "The weather in Paris is currently rainy with a temperature of 57°F."}], "finish_reason": "stop"}]', - '[[{"type": "evaluation", "answers": {"authIssue": {"type": "noul", "noul": 0.98}, "department": {"type": "choice", "choice": "billing", "confidence": 0.28, "probabilities": {"billing": 0.64, "technical": 0.36}}}}]]', + '[{"answers": {"authIssue": {"type": "noul", "noul": 0.98}, "department": {"type": "choice", "choice": "billing", "confidence": 0.28, "probabilities": {"billing": 0.64, "technical": 0.36}}}}]', '[{"answers": {"invoice_number": {"type": "text", "p_null": 3.8e-10, "span": [8, 16], "guess": "INV-2291", "confidence": 1, "value": "INV-2291"}, "due_date": {"type": "date", "p_null": 1.9e-08, "guess": "2026-10-02", "confidence": 0.9999, "value": "2026-10-02"}, "total": {"type": "number", "p_null": 2.3e-08, "guess": 1080, "confidence": 0.9999, "value": 1080}, "contacts": {"type": "list", "value": ["Dana Ruiz", "Priya Shah"], "spans": [[120, 129], [131, 141]], "confidence": 0.9999}, "po_number": {"type": "text", "p_null": 1, "span": [8, 16], "guess": "INV-2291", "confidence": 0.9995, "value": null}, "days_to_pay": {"type": "estimate", "value": 30, "mean": 29.535, "median": 30, "p10": 21, "p90": 38, "p_below": 5.9e-06, "p_above": 1.2e-05}}, "truncated": false}]', ], aliases=["ai.response.toolCalls", "ai.response.text"], @@ -18850,7 +18850,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ChangelogEntry(version="0.4.0", prs=[221]), ], additional_context=[ - 'For `gen_ai.decide` operations, the array holds one object `{type: "evaluation", answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.', + "For `gen_ai.decide` operations, the array holds one object `{answers: {...}}`. `answers` holds the answers keyed by question name, as the provider returned them. The second example shows this shape.", "For `gen_ai.extract` operations, the array holds one object `{answers: {: }, truncated: boolean, state_text?: string}`. This object is the response body as the provider returned it, without `model` and `usage`. Do not change the values. `answers` holds one answer for each field in the input, keyed by field name. A field that the model cannot determine has a `value` of `null`. `span` and `spans` are `[start, end]` character offsets into `state` (or into `state_text`, if the provider returns it), and `end` is exclusive. Set the model in `gen_ai.response.model` and the token counts in `gen_ai.usage.input_tokens` and `gen_ai.usage.output_tokens`. The third example shows this shape.", ], ),