Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/getsentry/sentry-javascript/llms.txt

Use this file to discover all available pages before exploring further.

The Anthropic integration automatically instruments Anthropic SDK calls to capture performance data and errors for Claude models.

Installation

The integration is enabled by default in Node.js:
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: 'your-dsn',
  // anthropicAIIntegration is included by default
});

Basic Usage

Just use the Anthropic SDK normally:
import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

// Automatically instrumented
const message = await anthropic.messages.create({
  model: 'claude-3-5-sonnet-20241022',
  max_tokens: 1024,
  messages: [
    { role: 'user', content: 'What is the capital of France?' },
  ],
});

Configuration

Default Behavior

By default, prompts and responses are not captured:
Sentry.init({
  dsn: 'your-dsn',
  sendDefaultPii: false, // Default: no prompts/responses
});

Capture Prompts and Responses

Enable for all AI integrations:
Sentry.init({
  dsn: 'your-dsn',
  sendDefaultPii: true, // Captures all inputs/outputs
});

Integration Options

recordInputs
boolean
default:"sendDefaultPii"
Capture prompt messages
recordOutputs
boolean
default:"sendDefaultPii"
Capture completion responses

Captured Data

Always Captured

These attributes are always included:
{
  'gen_ai.operation.name': 'chat',
  'gen_ai.request.model': 'claude-3-5-sonnet-20241022',
  'gen_ai.system': 'anthropic',
  'gen_ai.usage.input_tokens': 20,
  'gen_ai.usage.output_tokens': 95,
  'gen_ai.response.finish_reasons': ['end_turn'],
  'gen_ai.request.temperature': 1.0,
  'gen_ai.request.max_tokens': 1024,
}

When recordInputs: true

Prompt messages and system prompts are captured:
{
  'gen_ai.system': 'You are a helpful AI assistant.',
  'gen_ai.prompt.0.role': 'user',
  'gen_ai.prompt.0.content': 'What is the capital of France?',
}

When recordOutputs: true

Completion responses are captured:
{
  'gen_ai.completion.0.role': 'assistant',
  'gen_ai.completion.0.content': 'The capital of France is Paris.',
  'gen_ai.completion.0.finish_reason': 'end_turn',
}

Supported Operations

Message Creation

const message = await anthropic.messages.create({
  model: 'claude-3-5-sonnet-20241022',
  max_tokens: 1024,
  messages: [
    { role: 'user', content: 'Hello, Claude!' },
  ],
});
// Span: gen_ai.chat.completions

Streaming Messages

const stream = await anthropic.messages.create({
  model: 'claude-3-5-sonnet-20241022',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Tell me a story' }],
  stream: true,
});

for await (const event of stream) {
  if (event.type === 'content_block_delta') {
    process.stdout.write(event.delta.text);
  }
}
// Span includes full streaming response

System Prompts

const message = await anthropic.messages.create({
  model: 'claude-3-5-sonnet-20241022',
  max_tokens: 1024,
  system: 'You are a helpful customer service agent.',
  messages: [
    { role: 'user', content: 'I need help with my order' },
  ],
});
// System prompt captured when recordInputs: true

Tool Use (Function Calling)

const message = await anthropic.messages.create({
  model: 'claude-3-5-sonnet-20241022',
  max_tokens: 1024,
  tools: [
    {
      name: 'get_weather',
      description: 'Get the current weather for a location',
      input_schema: {
        type: 'object',
        properties: {
          location: {
            type: 'string',
            description: 'City name',
          },
        },
        required: ['location'],
      },
    },
  ],
  messages: [
    { role: 'user', content: 'What is the weather in Paris?' },
  ],
});
// Tool use captured in span attributes

Practical Examples

Multi-Turn Conversation

import * as Sentry from '@sentry/node';
import Anthropic from '@anthropic-ai/sdk';

const anthropic = new Anthropic();

async function chat(conversationHistory) {
  return await Sentry.startSpan(
    {
      name: 'Claude Chat',
      op: 'ai.chat',
      attributes: {
        'conversation.turns': conversationHistory.length,
      },
    },
    async () => {
      const message = await anthropic.messages.create({
        model: 'claude-3-5-sonnet-20241022',
        max_tokens: 1024,
        messages: conversationHistory,
      });
      
      return message.content[0].text;
    }
  );
}

// Usage
const history = [
  { role: 'user', content: 'What is 2+2?' },
  { role: 'assistant', content: '2+2 equals 4.' },
  { role: 'user', content: 'What about 3+3?' },
];

const response = await chat(history);

Content Moderation

async function moderateContent(content) {
  return await Sentry.startSpan(
    {
      name: 'Content Moderation',
      op: 'ai.moderation',
    },
    async () => {
      const message = await anthropic.messages.create({
        model: 'claude-3-5-sonnet-20241022',
        max_tokens: 256,
        system: 'You are a content moderation assistant. Analyze the following content and determine if it violates community guidelines.',
        messages: [
          { role: 'user', content },
        ],
      });
      
      return {
        safe: message.content[0].text.includes('safe'),
        analysis: message.content[0].text,
      };
    }
  );
}

Document Analysis

async function analyzeDocument(documentText) {
  return await Sentry.startSpan(
    {
      name: 'Analyze Document',
      op: 'ai.analysis',
      attributes: {
        'document.length': documentText.length,
      },
    },
    async () => {
      const message = await anthropic.messages.create({
        model: 'claude-3-5-sonnet-20241022',
        max_tokens: 2048,
        messages: [
          {
            role: 'user',
            content: `Please analyze this document and provide a summary:\n\n${documentText}`,
          },
        ],
      });
      
      return message.content[0].text;
    }
  );
}

Tool Use with Weather API

async function getWeatherAssistant(userQuery) {
  const tools = [
    {
      name: 'get_weather',
      description: 'Get current weather for a location',
      input_schema: {
        type: 'object',
        properties: {
          location: { type: 'string' },
          unit: { type: 'string', enum: ['celsius', 'fahrenheit'] },
        },
        required: ['location'],
      },
    },
  ];

  return await Sentry.startSpan(
    { name: 'Weather Assistant', op: 'ai.tool_use' },
    async () => {
      const message = await anthropic.messages.create({
        model: 'claude-3-5-sonnet-20241022',
        max_tokens: 1024,
        tools,
        messages: [{ role: 'user', content: userQuery }],
      });

      // Check if Claude wants to use a tool
      const toolUse = message.content.find(block => block.type === 'tool_use');
      
      if (toolUse) {
        // Call the actual weather API
        const weatherData = await fetchWeather(toolUse.input.location);
        
        // Continue conversation with tool result
        const followUp = await anthropic.messages.create({
          model: 'claude-3-5-sonnet-20241022',
          max_tokens: 1024,
          tools,
          messages: [
            { role: 'user', content: userQuery },
            { role: 'assistant', content: message.content },
            {
              role: 'user',
              content: [
                {
                  type: 'tool_result',
                  tool_use_id: toolUse.id,
                  content: JSON.stringify(weatherData),
                },
              ],
            },
          ],
        });
        
        return followUp.content[0].text;
      }
      
      return message.content[0].text;
    }
  );
}

Model Support

The integration supports all Claude models:
  • Claude 3.5 Sonnet: claude-3-5-sonnet-20241022
  • Claude 3 Opus: claude-3-opus-20240229
  • Claude 3 Sonnet: claude-3-sonnet-20240229
  • Claude 3 Haiku: claude-3-haiku-20240307
  • Claude 2.1: claude-2.1
  • Claude 2.0: claude-2.0

Performance Monitoring

Track Claude performance metrics:
  • Response Times: API latency per model
  • Token Usage: Input and output tokens
  • Stop Reasons: Track why generations ended
  • Error Rates: Rate limits and API errors

Source Code

The Anthropic integration is implemented in: packages/node/src/integrations/tracing/anthropic-ai/index.ts:11

Privacy Best Practices

Claude conversations may contain sensitive user information.

Filter Personal Information

Sentry.init({
  dsn: 'your-dsn',
  sendDefaultPii: true,
  
  beforeSendSpan(span) {
    // Remove PII from prompts
    const promptContent = span.attributes?.['gen_ai.prompt.0.content'];
    if (promptContent && typeof promptContent === 'string') {
      // Redact email addresses
      span.attributes['gen_ai.prompt.0.content'] = promptContent
        .replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, '[EMAIL]');
    }
    
    return span;
  },
});

Selective Capture by Use Case

async function processQuery(query, options = {}) {
  const isPublic = options.isPublic ?? false;
  
  // Use a custom client configuration based on sensitivity
  const integrations = isPublic
    ? [Sentry.anthropicAIIntegration({ recordInputs: true, recordOutputs: true })]
    : [Sentry.anthropicAIIntegration({ recordInputs: false, recordOutputs: false })];
  
  // Process with appropriate privacy settings
  const message = await anthropic.messages.create({...});
  return message;
}

Troubleshooting

Spans Not Appearing

Ensure tracing is enabled:
Sentry.init({
  dsn: 'your-dsn',
  tracesSampleRate: 1.0, // Capture 100% of traces
});

Streaming Responses Not Captured

Streaming responses are fully captured. Token usage appears after the stream completes.

Tool Use Not Showing

Tool use is captured in span attributes. Enable recordOutputs: true to see tool calls:
Sentry.anthropicAIIntegration({
  recordOutputs: true, // Captures tool use blocks
});

Build docs developers (and LLMs) love