Skip to content

vercelAIIntegration: span op stays 'default' instead of 'gen_ai.invoke_agent' - AI Agents dashboard shows no data #18448

@jam3gw

Description

@jam3gw

Is there an existing issue for this?

How do you use Sentry?

Sentry SaaS (sentry.io)

Which SDK are you using?

@sentry/nextjs

SDK Version

10.29.0

Framework Version

Next.js 15.4.1

Link to Sentry event

https://pedestalai.sentry.io/explore/traces/?query=span.description%3A*ai.generateText*&project=4510505607364608

Reproduction Example/SDK Setup

sentry.server.config.ts:
```typescript
import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: "...",
tracesSampleRate: 1,
integrations: [
Sentry.vercelAIIntegration({
recordInputs: true,
recordOutputs: true,
}),
],
sendDefaultPii: true,
});
```

AI SDK call with telemetry:
```typescript
const result = await generateText({
model: google("gemini-2.5-flash"),
prompt: "...",
experimental_telemetry: {
isEnabled: true,
functionId: "generate-title",
recordInputs: true,
recordOutputs: true,
},
});
```

Steps to Reproduce

  1. Configure `vercelAIIntegration()` in Sentry.init()
  2. Make AI SDK calls with `experimental_telemetry: { isEnabled: true }`
  3. Check spans in Trace Explorer - they appear with `span.op: default`
  4. Check AI Agents dashboard at `/insights/ai-agents/` - no data appears

Expected Result

Spans should have:

  • `span.op: gen_ai.invoke_agent` (for `ai.generateText`, `ai.streamText`)
  • `span.op: gen_ai.generate_text` (for `ai.generateText.doGenerate`)

This would make them appear in the AI Agents dashboard.

Actual Result

Spans have:

  • `span.op: default` ❌
  • `span.description: ai.generateText` ✅
  • All other `gen_ai.*` attributes are correctly set ✅

The common attributes (`gen_ai.system`, `gen_ai.request.model`, `gen_ai.usage.*`, etc.) are populated correctly, but the `op` transformation never happens.

Root Cause Analysis

The issue is in `packages/core/src/tracing/vercel-ai/index.ts`:

```typescript
function onVercelAiSpanStart(span: Span): void {
const { data: attributes, description: name } = spanToJSON(span);
// ...

// THE BUG: These attributes don't exist yet when the span STARTS
const aiModelId = attributes[AI_MODEL_ID_ATTRIBUTE];
const aiModelProvider = attributes[AI_MODEL_PROVIDER_ATTRIBUTE];

// This check FAILS because attributes are undefined at span start
if (typeof aiModelId !== 'string' || typeof aiModelProvider !== 'string' || !aiModelId || !aiModelProvider) {
return; // ← Exits early, never sets the op!
}

processGenerateSpan(span, name, attributes); // ← Never reached
}
```

The AI SDK adds `ai.model.id` and `ai.model.provider` attributes after the span starts (when the LLM response completes), not at span creation time.

The `vercelAiEventProcessor` (which runs after spans end when attributes ARE available) only renames attributes but does NOT set the `op`.

Suggested Fix

Add `op` transformation logic to `processEndedVercelAiSpan`:

```typescript
function processEndedVercelAiSpan(span: SpanJSON): void {
const { data: attributes, origin, description: name } = span;

if (origin !== 'auto.vercelai.otel') {
return;
}

// FIX: Set op based on span name (attributes are now available)
if (name === 'ai.generateText' || name === 'ai.streamText' || name === 'ai.generateObject') {
span.op = 'gen_ai.invoke_agent';
} else if (name === 'ai.generateText.doGenerate') {
span.op = 'gen_ai.generate_text';
} else if (name === 'ai.streamText.doStream') {
span.op = 'gen_ai.stream_text';
}
// ... handle other cases

// existing attribute renaming logic...
}
```

Related

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Waiting for: Product Owner

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions