AI / LLM Observability
Anthropic SDK
The Anthropic SDK integration provides a drop-in replacement for the official @anthropic-ai/sdk package. Use the same API you already know with automatic observability built-in.
Package: @databuddy/ai | Import: @databuddy/ai/anthropic
Installation
bash
bun add @databuddy/ai @anthropic-ai/sdkQuick Start
Replace your Anthropic import with the Databuddy version:
tsx
// Before
// import Anthropic from "@anthropic-ai/sdk";
// After
import { Anthropic } from "@databuddy/ai/anthropic";
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
databuddy: {
apiKey: process.env.DATABUDDY_API_KEY
}
});
const response = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello!" }]
});Configuration
Constructor Options
The Anthropic class accepts all standard Anthropic options plus databuddy configuration:
tsx
import { Anthropic } from "@databuddy/ai/anthropic";
const client = new Anthropic({
// Standard Anthropic options
apiKey: process.env.ANTHROPIC_API_KEY,
baseURL: "https://api.anthropic.com",
// Databuddy options
databuddy: {
// Required: API key for authentication
apiKey: process.env.DATABUDDY_API_KEY,
// Optional: Custom API endpoint
apiUrl: "https://basket.databuddy.cc/llm",
// Optional: Compute token costs (default: true)
computeCosts: true,
// Optional: Don't capture message content (default: false)
privacyMode: false,
// Optional: Success callback
onSuccess: (call) => console.log("Call completed:", call.traceId),
// Optional: Error callback
onError: (call) => console.error("Call failed:", call.error)
}
});Databuddy Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | DATABUDDY_API_KEY env var | Required. API key for authentication |
apiUrl | string | https://api.databuddy.cc/llm | API endpoint (or DATABUDDY_API_URL env var) |
transport | Transport | HTTP transport | Custom transport function |
computeCosts | boolean | true | Compute token costs using TokenLens |
privacyMode | boolean | false | Don't capture input/output content |
onSuccess | (call) => void | - | Callback on successful calls |
onError | (call) => void | - | Callback on failed calls |
Basic Usage
Messages
tsx
import { Anthropic } from "@databuddy/ai/anthropic";
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
databuddy: {
apiKey: process.env.DATABUDDY_API_KEY
}
});
const response = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
system: "You are a helpful assistant.",
messages: [
{ role: "user", content: "What is the capital of France?" }
]
});
console.log(response.content[0].text);Streaming
tsx
const stream = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "Write a poem" }],
stream: true
});
for await (const event of stream) {
if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
process.stdout.write(event.delta.text);
}
}
// Usage is tracked when stream completesPer-Call Options
Override Databuddy options for specific calls:
tsx
const response = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "Process sensitive data..." }],
// Per-call Databuddy options
databuddy: {
// Custom trace ID
traceId: "conversation-123",
// Enable privacy mode for this call
privacyMode: true,
// Disable cost computation
computeCosts: false,
// Custom callbacks
onSuccess: (call) => console.log("Done:", call.durationMs),
onError: (call) => console.error("Failed:", call.error)
}
});Per-Call Options Reference
| Option | Type | Description |
|---|---|---|
traceId | string | Custom trace ID to link related calls |
transport | Transport | Override transport for this call |
computeCosts | boolean | Override cost computation |
privacyMode | boolean | Override privacy mode |
onSuccess | (call) => void | Override success callback |
onError | (call) => void | Override error callback |
Tool Use
Tools are automatically tracked:
tsx
const response = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "What's the weather in London?" }],
tools: [
{
name: "get_weather",
description: "Get current weather for a city",
input_schema: {
type: "object",
properties: {
city: { type: "string" }
},
required: ["city"]
}
}
]
});
// Tracked data includes:
// tools: {
// callCount: 1,
// calledTools: ["get_weather"],
// availableTools: ["get_weather"]
// }Error Tracking
Errors are automatically captured:
tsx
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
databuddy: {
apiKey: process.env.DATABUDDY_API_KEY,
onError: (call) => {
console.error("AI call failed:", {
model: call.model,
error: call.error?.message,
httpStatus: call.httpStatus,
durationMs: call.durationMs
});
}
}
});
try {
await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "..." }]
});
} catch (error) {
// Error is logged automatically, plus your onError callback runs
}Privacy Mode
Enable privacy mode to track usage without capturing message content:
tsx
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
databuddy: {
apiKey: process.env.DATABUDDY_API_KEY,
privacyMode: true // Don't capture prompts/responses
}
});
// Only usage, costs, and metadata are tracked
// input: [] and output: [] in the logged dataTrace IDs
Link related calls with trace IDs:
tsx
import { Anthropic, createTraceId } from "@databuddy/ai/anthropic";
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
databuddy: { apiKey: process.env.DATABUDDY_API_KEY }
});
// Generate a trace ID for a conversation
const traceId = createTraceId();
// First message
const result1 = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "What is 2+2?" }],
databuddy: { traceId }
});
// Follow-up with same trace ID
const result2 = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [
{ role: "user", content: "What is 2+2?" },
{ role: "assistant", content: result1.content[0].text },
{ role: "user", content: "And what is that times 3?" }
],
databuddy: { traceId }
});Custom Transport
Use a custom transport for logging to other destinations:
tsx
import { Anthropic, httpTransport, type AnthropicLLMCall } from "@databuddy/ai/anthropic";
// Custom transport that logs locally and sends to API
const customTransport = async (call: AnthropicLLMCall) => {
console.log("AI call:", {
model: call.model,
tokens: call.usage.totalTokens,
cost: call.cost.totalCostUSD
});
// Also send to Databuddy
await httpTransport("https://api.databuddy.cc/llm", "your-api-key")(call);
};
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
databuddy: {
transport: customTransport
}
});What Gets Tracked
Each call captures:
json
{
"timestamp": "2024-01-15T10:30:00.000Z",
"traceId": "01234567-89ab-cdef-0123-456789abcdef",
"type": "generate",
"model": "claude-sonnet-4-20250514",
"provider": "anthropic",
"finishReason": "end_turn",
"input": [
{ "role": "system", "content": [{ "type": "text", "text": "You are helpful." }] },
{ "role": "user", "content": [{ "type": "text", "text": "Hello!" }] }
],
"output": [
{ "role": "assistant", "content": [{ "type": "text", "text": "Hi there!" }] }
],
"usage": {
"inputTokens": 15,
"outputTokens": 45,
"totalTokens": 60,
"cacheCreationInputTokens": 0,
"cacheReadInputTokens": 0
},
"cost": {
"inputCostUSD": 0.000045,
"outputCostUSD": 0.000675,
"totalCostUSD": 0.00072
},
"tools": {
"callCount": 0,
"resultCount": 0,
"calledTools": [],
"availableTools": []
},
"durationMs": 920,
"httpStatus": 200
}Supported Models
| Model | Description |
|---|---|
claude-sonnet-4-20250514 | Latest Sonnet model |
claude-opus-4-20250514 | Latest Opus model |
claude-3-5-sonnet-20241022 | Claude 3.5 Sonnet |
claude-3-5-haiku-20241022 | Claude 3.5 Haiku |
claude-3-opus-20240229 | Claude 3 Opus |
claude-3-sonnet-20240229 | Claude 3 Sonnet |
claude-3-haiku-20240307 | Claude 3 Haiku |
TypeScript Types
tsx
import {
Anthropic,
createTraceId,
httpTransport,
type AnthropicCallOptions,
type AnthropicLLMCall,
type AnthropicTrackerOptions,
type AnthropicTransport
} from "@databuddy/ai/anthropic";Related
How is this guide?