Claude Agent SDK предоставляет подробную информацию об использовании токенов для каждого взаимодействия с Claude. Это руководство объясняет, как правильно отслеживать затраты и понимать отчеты об использовании, особенно при работе с параллельным использованием инструментов и многошаговыми разговорами.
Для полной документации API см. справочник TypeScript SDK.
Когда Claude обрабатывает запросы, он сообщает об использовании токенов на уровне сообщений. Эти данные об использовании необходимы для отслеживания затрат и правильного выставления счетов пользователям.
Когда Claude выполняет инструменты, отчетность об использовании различается в зависимости от того, выполняются ли инструменты последовательно или параллельно:
import { query } from "@anthropic-ai/claude-agent-sdk";
// Пример: Отслеживание использования в разговоре
const result = await query({
prompt: "Проанализируй эту кодовую базу и запусти тесты",
options: {
onMessage: (message) => {
if (message.type === 'assistant' && message.usage) {
console.log(`ID сообщения: ${message.id}`);
console.log(`Использование:`, message.usage);
}
}
}
});Вот как сообщения и использование сообщаются в типичном многошаговом разговоре:
<!-- Шаг 1: Начальный запрос с параллельным использованием инструментов -->
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)
<!-- Шаг 2: Последующий ответ -->
assistant (text) { id: "msg_2", usage: { output_tokens: 98, ... } }Все сообщения с одинаковым полем id сообщают об идентичном использовании. Когда Claude отправляет несколько сообщений в одном ходе (например, текст + использование инструментов), они имеют один и тот же ID сообщения и данные об использовании.
// Все эти сообщения имеют одинаковый ID и использование
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 } }
];
// Взимайте плату только один раз за уникальный ID сообщения
const uniqueUsage = messages[0].usage; // Одинаково для всех сообщений с этим IDВы должны взимать плату с пользователей только один раз за шаг, а не за каждое отдельное сообщение. Когда вы видите несколько сообщений ассистента с одинаковым ID, используйте использование из любого одного из них.
Финальное сообщение result содержит общее кумулятивное использование из всех шагов в разговоре:
// Финальный результат включает общее использование
const result = await query({
prompt: "Многошаговая задача",
options: { /* ... */ }
});
console.log("Общее использование:", result.usage);
console.log("Общая стоимость:", result.usage.total_cost_usd);Вот полный пример реализации системы отслеживания затрат:
В редких случаях вы можете наблюдать разные значения output_tokens для сообщений с одинаковым ID. Когда это происходит:
total_cost_usd в сообщении результата является авторитетнымПри использовании кэширования промптов отслеживайте эти типы токенов отдельно:
interface CacheUsage {
cache_creation_input_tokens: number;
cache_read_input_tokens: number;
cache_creation: {
ephemeral_5m_input_tokens: number;
ephemeral_1h_input_tokens: number;
};
}Каждый объект использования содержит:
input_tokens: Базовые входные токены, обработанныеoutput_tokens: Токены, сгенерированные в ответеcache_creation_input_tokens: Токены, используемые для создания записей кэшаcache_read_input_tokens: Токены, прочитанные из кэшаservice_tier: Используемый уровень сервиса (например, "standard")total_cost_usd: Общая стоимость в долларах США (только в сообщении результата)Вот как агрегировать данные об использовании для панели выставления счетов:
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);
// Обновляем итоги пользователя
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
};
}
}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) {
// Обрабатываем только сообщения ассистента с использованием
if (message.type !== 'assistant' || !message.usage) {
return;
}
// Пропускаем, если мы уже обработали этот ID сообщения
if (this.processedMessageIds.has(message.id)) {
return;
}
// Отмечаем как обработанное и записываем использование
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 {
// Реализуйте здесь расчет цены
// Это упрощенный пример
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;
}
}
// Использование
const tracker = new CostTracker();
const { result, stepUsages, totalCost } = await tracker.trackConversation(
"Проанализируй и рефактори этот код"
);
console.log(`Обработано шагов: ${stepUsages.length}`);
console.log(`Общая стоимость: $${totalCost.toFixed(4)}`);