Claude Agent SDK fornisce informazioni dettagliate sull'utilizzo dei token per ogni interazione con Claude. Questa guida spiega come tracciare correttamente i costi e comprendere la segnalazione dell'utilizzo, specialmente quando si affrontano usi di strumenti paralleli e conversazioni multi-step.
Per la documentazione API completa, consulta il riferimento TypeScript SDK.
Quando Claude elabora le richieste, segnala l'utilizzo dei token a livello di messaggio. Questi dati di utilizzo sono essenziali per tracciare i costi e fatturare gli utenti in modo appropriato.
Quando Claude esegue gli strumenti, la segnalazione dell'utilizzo differisce a seconda che gli strumenti vengano eseguiti sequenzialmente o in parallelo:
import { query } from "@anthropic-ai/claude-agent-sdk";
// Example: Tracking usage in a conversation
const result = await query({
prompt: "Analyze this codebase and run tests",
options: {
onMessage: (message) => {
if (message.type === 'assistant' && message.usage) {
console.log(`Message ID: ${message.id}`);
console.log(`Usage:`, message.usage);
}
}
}
});Ecco come i messaggi e l'utilizzo vengono segnalati in una tipica conversazione multi-step:
<!-- Step 1: Initial request with parallel tool uses -->
assistant (text) { id: "msg_1", usage: { output_tokens: 100, ... } }
assistant (tool_use) { id: "msg_1", usage: { output_tokens: 100, ... } }
assistant (tool_use) { id: "msg_1", usage: { output_tokens: 100, ... } }
assistant (tool_use) { id: "msg_1", usage: { output_tokens: 100, ... } }
user (tool_result)
user (tool_result)
user (tool_result)
<!-- Step 2: Follow-up response -->
assistant (text) { id: "msg_2", usage: { output_tokens: 98, ... } }Tutti i messaggi con lo stesso campo id segnalano un utilizzo identico. Quando Claude invia più messaggi nello stesso turno (ad es. testo + usi di strumenti), condividono lo stesso ID messaggio e dati di utilizzo.
// All these messages have the same ID and usage
const messages = [
{ type: 'assistant', id: 'msg_123', usage: { output_tokens: 100 } },
{ type: 'assistant', id: 'msg_123', usage: { output_tokens: 100 } },
{ type: 'assistant', id: 'msg_123', usage: { output_tokens: 100 } }
];
// Charge only once per unique message ID
const uniqueUsage = messages[0].usage; // Same for all messages with this IDDovresti addebitare gli utenti una sola volta per step, non per ogni singolo messaggio. Quando vedi più messaggi dell'assistente con lo stesso ID, utilizza l'utilizzo da uno qualsiasi di essi.
Il messaggio result finale contiene l'utilizzo cumulativo totale da tutti gli step nella conversazione:
// Final result includes total usage
const result = await query({
prompt: "Multi-step task",
options: { /* ... */ }
});
console.log("Total usage:", result.usage);
console.log("Total cost:", result.usage.total_cost_usd);Il messaggio di risultato include anche modelUsage, che fornisce dati di utilizzo per modello autorevoli. Come total_cost_usd, questo campo è accurato e adatto a scopi di fatturazione. Questo è particolarmente utile quando si utilizzano più modelli (ad es. Haiku per i subagenti, Opus per l'agente principale).
// modelUsage provides per-model breakdown
type ModelUsage = {
inputTokens: number
outputTokens: number
cacheReadInputTokens: number
cacheCreationInputTokens: number
webSearchRequests: number
costUSD: number
contextWindow: number
}
// Access from result message
const result = await query({ prompt: "..." });
// result.modelUsage is a map of model name to ModelUsage
for (const [modelName, usage] of Object.entries(result.modelUsage)) {
console.log(`${modelName}: $${usage.costUSD.toFixed(4)}`);
console.log(` Input tokens: ${usage.inputTokens}`);
console.log(` Output tokens: ${usage.outputTokens}`);
}Per le definizioni di tipo complete, consulta il riferimento TypeScript SDK.
Ecco un esempio completo di implementazione di un sistema di tracciamento dei costi:
import { query } from "@anthropic-ai/claude-agent-sdk";
class CostTracker {
private processedMessageIds = new Set<string>();
private stepUsages: Array<any> = [];
async trackConversation(prompt: string) {
const result = await query({
prompt,
options: {
onMessage: (message) => {
this.processMessage(message);
}
}
});
return {
result,
stepUsages: this.stepUsages,
totalCost: result.usage?.total_cost_usd || 0
};
}
private processMessage(message: any) {
// Only process assistant messages with usage
if (message.type !== 'assistant' || !message.usage) {
return;
}
// Skip if we've already processed this message ID
if (this.processedMessageIds.has(message.id)) {
return;
}
// Mark as processed and record usage
this.processedMessageIds.add(message.id);
this.stepUsages.push({
messageId: message.id,
timestamp: new Date().toISOString(),
usage: message.usage,
costUSD: this.calculateCost(message.usage)
});
}
private calculateCost(usage: any): number {
// Implement your pricing calculation here
// This is a simplified example
const inputCost = usage.input_tokens * 0.00003;
const outputCost = usage.output_tokens * 0.00015;
const cacheReadCost = (usage.cache_read_input_tokens || 0) * 0.0000075;
return inputCost + outputCost + cacheReadCost;
}
}
// Usage
const tracker = new CostTracker();
const { result, stepUsages, totalCost } = await tracker.trackConversation(
"Analyze and refactor this code"
);
console.log(`Steps processed: ${stepUsages.length}`);
console.log(`Total cost: $${totalCost.toFixed(4)}`);In rari casi, potresti osservare valori diversi di output_tokens per messaggi con lo stesso ID. Quando ciò accade:
total_cost_usd nel messaggio di risultato è autorevoleQuando si utilizza la memorizzazione nella cache dei prompt, traccia questi tipi di token separatamente:
interface CacheUsage {
cache_creation_input_tokens: number;
cache_read_input_tokens: number;
cache_creation: {
ephemeral_5m_input_tokens: number;
ephemeral_1h_input_tokens: number;
};
}Ogni oggetto di utilizzo contiene:
input_tokens: Token di input di base elaboratioutput_tokens: Token generati nella rispostacache_creation_input_tokens: Token utilizzati per creare voci di cachecache_read_input_tokens: Token letti dalla cacheservice_tier: Il livello di servizio utilizzato (ad es. "standard")total_cost_usd: Costo totale in USD (solo nel messaggio di risultato)Ecco come aggregare i dati di utilizzo per una dashboard di fatturazione:
class BillingAggregator {
private userUsage = new Map<string, {
totalTokens: number;
totalCost: number;
conversations: number;
}>();
async processUserRequest(userId: string, prompt: string) {
const tracker = new CostTracker();
const { result, stepUsages, totalCost } = await tracker.trackConversation(prompt);
// Update user totals
const current = this.userUsage.get(userId) || {
totalTokens: 0,
totalCost: 0,
conversations: 0
};
const totalTokens = stepUsages.reduce((sum, step) =>
sum + step.usage.input_tokens + step.usage.output_tokens, 0
);
this.userUsage.set(userId, {
totalTokens: current.totalTokens + totalTokens,
totalCost: current.totalCost + totalCost,
conversations: current.conversations + 1
});
return result;
}
getUserBilling(userId: string) {
return this.userUsage.get(userId) || {
totalTokens: 0,
totalCost: 0,
conversations: 0
};
}
}Was this page helpful?