Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ Affected SDKs: All SDKs.
- Legacy messaging (`messaging.*`) and database (`db.statement`, …) span attributes on the AMQP and Redis instrumentations were replaced by their current semantic-convention equivalents.
- The gen_ai cache token attributes `gen_ai.usage.cache_creation_input_tokens` and `gen_ai.usage.cache_read_input_tokens` were renamed to `gen_ai.usage.cache_creation.input_tokens` and `gen_ai.usage.cache_read.input_tokens`.
- The `gen_ai.system` span attribute was renamed to `gen_ai.provider.name` across all AI integrations.
- The `gen_ai.request.available_tools` span attribute was renamed to `gen_ai.tool.definitions` across all AI integrations.
- Span attributes now use the shared `@sentry/conventions` package under the hood.

If you reference these attributes in custom instrumentation, `beforeSendSpan`, dashboards, or alerts, update them to the new names.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
GEN_AI_REQUEST_TEMPERATURE,
Expand All @@ -14,6 +13,7 @@ import {
GEN_AI_RESPONSE_TEXT,
GEN_AI_RESPONSE_TOOL_CALLS,
GEN_AI_SYSTEM_INSTRUCTIONS,
GEN_AI_TOOL_DEFINITIONS,
GEN_AI_USAGE_INPUT_TOKENS,
GEN_AI_USAGE_OUTPUT_TOKENS,
GEN_AI_USAGE_TOTAL_TOKENS,
Expand Down Expand Up @@ -453,7 +453,7 @@ describe('Anthropic integration', () => {
expect(firstSpan!.name).toBe('chat claude-3-haiku-20240307');
expect(firstSpan!.status).toBe('ok');
expect(firstSpan!.attributes['sentry.op'].value).toBe('gen_ai.chat');
expect(firstSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS].value).toBe(EXPECTED_TOOLS_JSON);
expect(firstSpan!.attributes[GEN_AI_TOOL_DEFINITIONS].value).toBe(EXPECTED_TOOLS_JSON);
expect(firstSpan!.attributes[GEN_AI_RESPONSE_TOOL_CALLS].value).toBe(EXPECTED_TOOL_CALLS_JSON);
},
})
Expand Down Expand Up @@ -483,7 +483,7 @@ describe('Anthropic integration', () => {
expect(span.attributes['sentry.op'].value).toBe('gen_ai.chat');
expect(span.attributes[GEN_AI_RESPONSE_STREAMING].value).toBe(true);
expect(span.attributes[GEN_AI_RESPONSE_FINISH_REASONS].value).toBe('["tool_use"]');
expect(span.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS].value).toBe(EXPECTED_TOOLS_JSON);
expect(span.attributes[GEN_AI_TOOL_DEFINITIONS].value).toBe(EXPECTED_TOOLS_JSON);
expect(span.attributes[GEN_AI_RESPONSE_TOOL_CALLS].value).toBe(EXPECTED_TOOL_CALLS_JSON);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
GEN_AI_REQUEST_TEMPERATURE,
Expand All @@ -16,6 +15,7 @@ import {
GEN_AI_RESPONSE_TEXT,
GEN_AI_RESPONSE_TOOL_CALLS,
GEN_AI_SYSTEM_INSTRUCTIONS,
GEN_AI_TOOL_DEFINITIONS,
GEN_AI_USAGE_INPUT_TOKENS,
GEN_AI_USAGE_OUTPUT_TOKENS,
GEN_AI_USAGE_TOTAL_TOKENS,
Expand Down Expand Up @@ -182,7 +182,7 @@ describe('Google GenAI integration', () => {
expect(container.items).toHaveLength(3);
const nonStreamingToolsSpan = container.items.find(
span =>
span.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]?.value === EXPECTED_AVAILABLE_TOOLS_JSON &&
span.attributes[GEN_AI_TOOL_DEFINITIONS]?.value === EXPECTED_AVAILABLE_TOOLS_JSON &&
span.attributes[GEN_AI_RESPONSE_STREAMING] === undefined,
);
expect(nonStreamingToolsSpan).toBeDefined();
Expand All @@ -198,7 +198,7 @@ describe('Google GenAI integration', () => {

const streamingToolsSpan = container.items.find(
span =>
span.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]?.value === EXPECTED_AVAILABLE_TOOLS_JSON &&
span.attributes[GEN_AI_TOOL_DEFINITIONS]?.value === EXPECTED_AVAILABLE_TOOLS_JSON &&
span.attributes[GEN_AI_RESPONSE_STREAMING]?.value === true,
);
expect(streamingToolsSpan).toBeDefined();
Expand All @@ -214,9 +214,7 @@ describe('Google GenAI integration', () => {
expect(streamingToolsSpan!.attributes[GEN_AI_USAGE_OUTPUT_TOKENS].value).toBe(10);
expect(streamingToolsSpan!.attributes[GEN_AI_USAGE_TOTAL_TOKENS].value).toBe(22);

const noToolsSpan = container.items.find(
span => span.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS] === undefined,
);
const noToolsSpan = container.items.find(span => span.attributes[GEN_AI_TOOL_DEFINITIONS] === undefined);
expect(noToolsSpan).toBeDefined();
expect(noToolsSpan!.name).toBe('generate_content gemini-2.0-flash-001');
expect(noToolsSpan!.status).toBe('ok');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_PIPELINE_NAME,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_RESPONSE_MODEL,
GEN_AI_RESPONSE_TEXT,
GEN_AI_RESPONSE_TOOL_CALLS,
GEN_AI_SYSTEM_INSTRUCTIONS,
GEN_AI_TOOL_DEFINITIONS,
GEN_AI_TOOL_NAME,
GEN_AI_USAGE_INPUT_TOKENS,
GEN_AI_USAGE_OUTPUT_TOKENS,
Expand Down Expand Up @@ -128,7 +128,7 @@ describe('LangGraph integration', () => {
expect(toolAgentInvokeSpan).toBeDefined();
expect(toolAgentInvokeSpan!.status).toBe('ok');
expect(toolAgentInvokeSpan!.attributes['sentry.op'].value).toBe('gen_ai.invoke_agent');
expect(toolAgentInvokeSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS].value).toContain('get_weather');
expect(toolAgentInvokeSpan!.attributes[GEN_AI_TOOL_DEFINITIONS].value).toContain('get_weather');
expect(toolAgentInvokeSpan!.attributes[GEN_AI_INPUT_MESSAGES].value).toContain('What is the weather?');
expect(toolAgentInvokeSpan!.attributes[GEN_AI_RESPONSE_MODEL].value).toBe('gpt-4-0613');
expect(toolAgentInvokeSpan!.attributes[GEN_AI_RESPONSE_TEXT].value).toContain(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_MODEL,
GEN_AI_RESPONSE_FINISH_REASONS,
GEN_AI_RESPONSE_ID,
GEN_AI_RESPONSE_MODEL,
GEN_AI_RESPONSE_STREAMING,
GEN_AI_RESPONSE_TEXT,
GEN_AI_RESPONSE_TOOL_CALLS,
GEN_AI_TOOL_DEFINITIONS,
GEN_AI_USAGE_INPUT_TOKENS,
GEN_AI_USAGE_OUTPUT_TOKENS,
GEN_AI_USAGE_TOTAL_TOKENS,
Expand Down Expand Up @@ -106,7 +106,7 @@ describe('OpenAI Tool Calls integration', () => {
type: 'string',
value: 'gpt-4',
});
expect(chatToolsSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]).toEqual({
expect(chatToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
Expand Down Expand Up @@ -165,7 +165,7 @@ describe('OpenAI Tool Calls integration', () => {
type: 'boolean',
value: true,
});
expect(streamingChatToolsSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]).toEqual({
expect(streamingChatToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
Expand Down Expand Up @@ -225,7 +225,7 @@ describe('OpenAI Tool Calls integration', () => {
value: 'gpt-4',
});
expect(responsesToolsSpan!.attributes[GEN_AI_REQUEST_STREAM_ATTRIBUTE]).toBeUndefined();
expect(responsesToolsSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]).toEqual({
expect(responsesToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
Expand Down Expand Up @@ -284,7 +284,7 @@ describe('OpenAI Tool Calls integration', () => {
type: 'boolean',
value: true,
});
expect(streamingResponsesToolsSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]).toEqual({
expect(streamingResponsesToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
Expand Down Expand Up @@ -358,7 +358,7 @@ describe('OpenAI Tool Calls integration', () => {
type: 'string',
value: '[{"role":"user","content":"What is the weather like in Paris today?"}]',
});
expect(chatToolsSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]).toEqual({
expect(chatToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
Expand Down Expand Up @@ -429,7 +429,7 @@ describe('OpenAI Tool Calls integration', () => {
type: 'string',
value: '[{"role":"user","content":"What is the weather like in Paris today?"}]',
});
expect(streamingChatToolsSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]).toEqual({
expect(streamingChatToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
Expand Down Expand Up @@ -497,7 +497,7 @@ describe('OpenAI Tool Calls integration', () => {
type: 'string',
value: '[{"role":"user","content":"What is the weather like in Paris today?"}]',
});
expect(responsesToolsSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]).toEqual({
expect(responsesToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
Expand Down Expand Up @@ -564,7 +564,7 @@ describe('OpenAI Tool Calls integration', () => {
type: 'string',
value: '[{"role":"user","content":"What is the weather like in Paris today?"}]',
});
expect(streamingResponsesToolsSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]).toEqual({
expect(streamingResponsesToolsSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toEqual({
type: 'string',
value: WEATHER_TOOL_DEFINITION,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_OUTPUT_MESSAGES,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_MODEL,
GEN_AI_RESPONSE_MODEL,
GEN_AI_TOOL_DEFINITIONS,
GEN_AI_TOOL_DESCRIPTION,
GEN_AI_TOOL_INPUT,
GEN_AI_TOOL_NAME,
Expand Down Expand Up @@ -209,12 +209,12 @@ describe('Vercel AI integration (streaming v4)', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: attr(expectedOrigin),
}),
}),
// Fifth span - tool call generate_content with available_tools
// Fifth span - tool call generate_content with tool definitions
expect.objectContaining({
name: 'generate_content mock-model-id',
status: 'ok',
attributes: expect.objectContaining({
[GEN_AI_REQUEST_AVAILABLE_TOOLS]: expect.objectContaining({
[GEN_AI_TOOL_DEFINITIONS]: expect.objectContaining({
value: expect.stringContaining('getWeather'),
}),
[GEN_AI_REQUEST_MODEL]: attr('mock-model-id'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_OUTPUT_MESSAGES,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_MODEL,
GEN_AI_RESPONSE_MODEL,
GEN_AI_TOOL_DEFINITIONS,
GEN_AI_TOOL_DESCRIPTION,
GEN_AI_TOOL_INPUT,
GEN_AI_TOOL_NAME,
Expand Down Expand Up @@ -203,12 +203,12 @@ describe('Vercel AI integration (streaming, v6)', () => {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: attr(origin),
}),
}),
// Fifth span - tool call generate_content with available_tools
// Fifth span - tool call generate_content with tool definitions
expect.objectContaining({
name: 'generate_content mock-model-id',
status: 'ok',
attributes: expect.objectContaining({
[GEN_AI_REQUEST_AVAILABLE_TOOLS]: expect.objectContaining({
[GEN_AI_TOOL_DEFINITIONS]: expect.objectContaining({
value: expect.stringContaining('getWeather'),
}),
[GEN_AI_REQUEST_MODEL]: attr('mock-model-id'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import {
GEN_AI_OPERATION_NAME,
GEN_AI_OUTPUT_MESSAGES,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_MODEL,
GEN_AI_RESPONSE_MODEL,
GEN_AI_SYSTEM_INSTRUCTIONS,
GEN_AI_TOOL_DEFINITIONS,
GEN_AI_TOOL_DESCRIPTION,
GEN_AI_TOOL_INPUT,
GEN_AI_TOOL_NAME,
Expand Down Expand Up @@ -223,13 +223,13 @@ describe('Vercel AI integration (v4)', () => {
const toolGenerateContentSpan = container.items.find(
span =>
span.name === 'generate_content mock-model-id' &&
getStringAttributeValue(span.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]?.value)?.includes('getWeather'),
getStringAttributeValue(span.attributes[GEN_AI_TOOL_DEFINITIONS]?.value)?.includes('getWeather'),
);
expect(toolGenerateContentSpan).toBeDefined();
expect(toolGenerateContentSpan!.name).toBe('generate_content mock-model-id');
expect(toolGenerateContentSpan!.status).toBe('ok');
expect(toolGenerateContentSpan!.attributes['sentry.op'].value).toBe('gen_ai.generate_content');
expect(toolGenerateContentSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS].value).toContain('getWeather');
expect(toolGenerateContentSpan!.attributes[GEN_AI_TOOL_DEFINITIONS].value).toContain('getWeather');
expect(toolGenerateContentSpan!.attributes[GEN_AI_USAGE_INPUT_TOKENS].value).toBe(15);

const toolExecutionSpan = container.items.find(span => span.name === 'execute_tool getWeather');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OUTPUT_MESSAGES,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_MODEL,
GEN_AI_RESPONSE_MODEL,
GEN_AI_TOOL_DEFINITIONS,
GEN_AI_TOOL_DESCRIPTION,
GEN_AI_TOOL_INPUT,
GEN_AI_TOOL_NAME,
Expand Down Expand Up @@ -229,13 +229,13 @@ describe('Vercel AI integration (v5)', () => {
const toolGenerateContentSpan = container.items.find(
span =>
span.name === 'generate_content mock-model-id' &&
span.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS] !== undefined,
span.attributes[GEN_AI_TOOL_DEFINITIONS] !== undefined,
);
expect(toolGenerateContentSpan).toBeDefined();
expect(toolGenerateContentSpan!.name).toBe('generate_content mock-model-id');
expect(toolGenerateContentSpan!.status).toBe('ok');
expect(toolGenerateContentSpan!.attributes['sentry.op'].value).toBe('gen_ai.generate_content');
expect(toolGenerateContentSpan!.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]).toBeDefined();
expect(toolGenerateContentSpan!.attributes[GEN_AI_TOOL_DEFINITIONS]).toBeDefined();
expect(toolGenerateContentSpan!.attributes[GEN_AI_USAGE_INPUT_TOKENS].value).toBe(15);

const toolExecutionSpan = container.items.find(span => span.name === 'execute_tool getWeather');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OUTPUT_MESSAGES,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_MODEL,
GEN_AI_RESPONSE_FINISH_REASONS,
GEN_AI_RESPONSE_MODEL,
GEN_AI_SYSTEM_INSTRUCTIONS,
GEN_AI_TOOL_DEFINITIONS,
GEN_AI_TOOL_DESCRIPTION,
GEN_AI_TOOL_INPUT,
GEN_AI_TOOL_NAME,
Expand Down Expand Up @@ -132,13 +132,13 @@ describe.each(matrix)('Vercel AI integration (version %s)', (version, vercelAiVe
const toolGenerateContentSpan = container.items.find(
span =>
span.name === 'generate_content mock-model-id' &&
span.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS] !== undefined,
span.attributes[GEN_AI_TOOL_DEFINITIONS] !== undefined,
)!;
expect(toolGenerateContentSpan).toBeDefined();
expect(toolGenerateContentSpan.name).toBe('generate_content mock-model-id');
expect(toolGenerateContentSpan.status).toBe('ok');
expect(toolGenerateContentSpan.attributes['sentry.op']?.value).toBe('gen_ai.generate_content');
expect(toolGenerateContentSpan.attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS]).toBeDefined();
expect(toolGenerateContentSpan.attributes[GEN_AI_TOOL_DEFINITIONS]).toBeDefined();
expect(toolGenerateContentSpan.attributes[GEN_AI_USAGE_INPUT_TOKENS]?.value).toBe(15);

const toolExecutionSpan = container.items.find(span => span.name === 'execute_tool getWeather')!;
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/tracing/anthropic-ai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
GEN_AI_OPERATION_NAME,
GEN_AI_PROMPT,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_FREQUENCY_PENALTY,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
Expand All @@ -19,6 +18,7 @@ import {
GEN_AI_RESPONSE_MODEL,
GEN_AI_RESPONSE_TEXT,
GEN_AI_RESPONSE_TOOL_CALLS,
GEN_AI_TOOL_DEFINITIONS,
} from '@sentry/conventions/attributes';
import { GEN_AI_REQUEST_STREAM_ATTRIBUTE } from '../ai/gen-ai-attributes';
import type { InstrumentedMethodEntry } from '../ai/utils';
Expand Down Expand Up @@ -59,7 +59,7 @@ export function extractRequestAttributes(
if (args.length > 0 && typeof args[0] === 'object' && args[0] !== null) {
const params = args[0] as Record<string, unknown>;
if (params.tools && Array.isArray(params.tools)) {
attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS] = JSON.stringify(params.tools);
attributes[GEN_AI_TOOL_DEFINITIONS] = JSON.stringify(params.tools);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: Should we be more defensive with stringifying here? I think we have a helper for that now 🤔

}

attributes[GEN_AI_REQUEST_MODEL] = params.model ?? 'unknown';
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/tracing/google-genai/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_FREQUENCY_PENALTY,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
Expand All @@ -23,6 +22,7 @@ import {
GEN_AI_RESPONSE_TEXT,
GEN_AI_RESPONSE_TOOL_CALLS,
GEN_AI_SYSTEM_INSTRUCTIONS,
GEN_AI_TOOL_DEFINITIONS,
GEN_AI_USAGE_INPUT_TOKENS,
GEN_AI_USAGE_OUTPUT_TOKENS,
GEN_AI_USAGE_TOTAL_TOKENS,
Expand Down Expand Up @@ -125,7 +125,7 @@ export function extractRequestAttributes(
const functionDeclarations = config.tools.flatMap(
(tool: { functionDeclarations: unknown[] }) => tool.functionDeclarations,
);
attributes[GEN_AI_REQUEST_AVAILABLE_TOOLS] = JSON.stringify(functionDeclarations);
attributes[GEN_AI_TOOL_DEFINITIONS] = JSON.stringify(functionDeclarations);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here too, more defensive stringifying.

}
}
} else {
Expand Down
Loading
Loading