Install
npm install @fluxgate/sdk @fluxgate/anthropic @anthropic-ai/sdk
One-time setup
// lib/anthropic.ts
import Anthropic from "@anthropic-ai/sdk";
import { FluxGate } from "@fluxgate/sdk";
import { createAnthropicCostTracker } from "@fluxgate/anthropic";
const _client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY!,
});
const fg = new FluxGate({
apiKey: process.env.FLUXGATE_API_KEY!,
});
export const anthropic = createAnthropicCostTracker(_client, fg);
Messages — non-streaming
import { anthropic } from "@/lib/anthropic";
const message = await anthropic
.withContext({
feature: "summarization",
user: { id: session.user.id, email: session.user.email },
sessionId: session.id,
})
.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [{ role: "user", content: userPrompt }],
});
const text = message.content[0].type === "text" ? message.content[0].text : "";
const { cost, trackingId } = message.fluxGateCostTrackingResponse;
Messages — streaming
const stream = await anthropic
.withContext({ feature: "streaming-chat" })
.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [{ role: "user", content: prompt }],
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);
}
}
// Available after the stream closes
console.log(stream.fluxGateCostTrackingResponse);
Rich user attribution
Pass a TrackedUser object (instead of a plain string ID) to enable per-user revenue attribution in FluxGate's Cost Breakdown views.
await anthropic
.withContext({
feature: "premium-chat",
user: {
id: currentUser.id,
name: currentUser.name,
email: currentUser.email,
monthlyRevenue: currentUser.mrr, // optional — used in spend/revenue ratio charts
},
conversationId: thread.id,
})
.messages.create({ model: "claude-sonnet-4-6", max_tokens: 2048, messages });
Error handling
Errors are tracked automatically. Surface them to your own error handling pipeline — FluxGate records the event with status: "ERROR" before the exception propagates.
try {
const message = await anthropic
.withContext({ feature: "code-review" })
.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 4096,
messages,
});
} catch (err) {
// Already recorded in FluxGate — just re-throw
throw err;
}
Without context
Use the .client property when you need a tracked call with no feature tag (e.g. internal health checks):
const message = await anthropic.client.messages.create({
model: "claude-haiku-3",
max_tokens: 256,
messages: [{ role: "user", content: "ping" }],
});
FluxGateCostTrackingResponse shape
interface FluxGateCostTrackingResponse {
status:
| "SUCCESS"
| "ERROR"
| "BLOCKED"
| "MAX_TOKENS"
| "CONTENT_FILTER"
| "RECITATION"
| "MALFORMED_REQUEST";
cost: number | null; // USD
trackingId: string | null;
createdAt: string | null; // ISO 8601
errorMessage?: string;
}
Tracked automatically: input tokens, output tokens, model name, latency (ms), stream duration, and stop reason (end_turn, max_tokens, content_filter).
Supported methods
| Method | Non-streaming | Streaming |
|---|---|---|
messages.create | ✅ | ✅ |