Comprendre l’utilisation des tokens
Les SDKs TypeScript et Python exposent les mêmes données d’utilisation avec des noms de champs différents :- TypeScript fournit des ventilations de tokens par étape sur chaque message d’assistant (
message.message.id,message.message.usage), le coût par modèle viamodelUsagesur le message de résultat, et un total cumulatif sur le message de résultat. - Python fournit des ventilations de tokens par étape sur chaque message d’assistant en tant que
message.usageetmessage.message_id, le coût par modèle viamodel_usagesur le message de résultat, et le total cumulatif sur le message de résultat en tant quetotal_cost_usd.
- Appel
query(): une invocation de la fonctionquery()du SDK. Un seul appel peut impliquer plusieurs étapes : Claude répond, utilise des outils, obtient des résultats et répond à nouveau. Chaque appel produit un messageresultà la fin, sauf en mode d’entrée en streaming, où un appelquery()porte plusieurs tours d’utilisateur et chaque tour émet son propre messageresult. - Étape : un seul cycle requête/réponse au sein d’un appel
query(). Chaque étape produit des messages d’assistant avec l’utilisation des tokens. - Session : une série d’appels
query()liés par un ID de session via l’optionresume. Les résultats d’un appel repris rapportent la dépense totale de la session, pas seulement celle de cet appel. Consultez Accumuler les coûts sur plusieurs appels pour voir comment les totaux se reportent.
query(), avec l’utilisation des tokens rapportée à chaque étape et l’estimation cumulative à la fin :
1
Chaque étape produit des messages d'assistant
Quand Claude répond, il envoie un ou plusieurs messages d’assistant. En TypeScript, chaque message d’assistant contient un
BetaMessage imbriqué (accessible via message.message) avec un id et un objet usage avec les comptages de tokens (input_tokens, output_tokens). En Python, la classe de données AssistantMessage expose les mêmes données directement via message.usage et message.message_id. Quand Claude utilise plusieurs outils en un seul tour, tous les messages de ce tour partagent le même ID, donc dédupliquez par ID pour éviter le double comptage.2
Le message de résultat fournit l'estimation cumulative
Quand l’appel
query() se termine, le SDK émet un message de résultat avec total_cost_usd et l’utilisation cumulative usage, typé en tant que SDKResultMessage en TypeScript et ResultMessage en Python. Si vous avez seulement besoin du total estimé, vous pouvez ignorer l’utilisation par étape et lire cette valeur unique.Si vous effectuez plusieurs appels query() indépendants, chaque résultat reflète uniquement le coût de cet appel individuel. Un appel qui reprend une session compte également la dépense antérieure de la session.En mode d’entrée en streaming, chaque tour émet son propre message de résultat. Consultez Suivre les coûts en mode d’entrée en streaming pour savoir comment lire les totaux d’appels dans ce mode.Suivre les coûts en mode d’entrée en continu
En mode d’entrée en continu, un appelquery() porte plusieurs tours d’utilisateur et chaque tour émet son propre message de résultat. Les champs de résultat diffèrent en portée :
usage: couvre uniquement ce tour, et au sein de celui-ci uniquement la boucle principale de l’agent, pas les sous-agents qu’il a exécutés.total_cost_usdetmodelUsage, oumodel_usageen Python : portent le total cumulé pour l’ensemble de l’appel jusqu’à présent, plus toute dépense restaurée lorsque l’appel a repris une session.
/clear, /reset, ou /new, lisez le dernier résultat pour les totaux d’appel plutôt que de les additionner entre les résultats.
Les totaux cumulés recommencent à zéro chaque fois que votre application envoie l’une de ces trois commandes, et à l’intérieur d’un appel query() rien d’autre ne les réinitialise. Trois résultats importent pour votre comptabilité :
- Le propre résultat du tour
/clear: couvre uniquement ce qui s’est exécuté depuis la réinitialisation, et porte un nouveausession_id. - Chaque résultat ultérieur : continue à compter à partir de cette réinitialisation.
- Le dernier résultat avant chaque
/clear: contient le total pour les tours depuis la réinitialisation précédente.
/clear au résultat final de l’appel. Tous les autres résultats, y compris celui du tour /clear, sont remplacés par un résultat ultérieur.
En TypeScript, le SDK émet également un SDKConversationResetMessage à chaque réinitialisation, vous permettant de détecter les réinitialisations à partir du flux. En Python, le SDK émet de même un ConversationResetMessage. Avant la version 0.2.137 du SDK Python, l’itérateur Python supprimait ce message, donc sur ces versions comptez les réinitialisations vous-même à partir des tours /clear que votre application envoie.
maxBudgetUsd (TypeScript) ou max_budget_usd (Python) compte uniquement la dépense propre de l’appel : les totaux restaurés à partir d’une session reprise ne comptent pas contre lui, et un /clear recommence le budget.
Obtenir le coût total d’une requête
Le message de résultat, typé commeSDKResultMessage en TypeScript et ResultMessage en Python, marque la fin de la boucle d’agent pour un appel query(). Il inclut total_cost_usd, le coût estimé cumulatif sur toutes les étapes de cet appel. Un appel qui reprend une session compte également les dépenses antérieures de la session. Deux mises en garde s’appliquent lorsque vous lisez la valeur :
- En Python, le champ est typé comme optionnel, donc vérifiez qu’il n’est pas
Noneavant de le lire. - Les résultats de succès et d’erreur le portent tous les deux, bien que le résultat final d’un plantage de session peut le porter à zéro.
modelUsage, ou model_usage en Python, pour la comptabilité des jetons de l’arborescence complète ; le champ usage sous-compte dès que l’imbrication se produit.
En mode d’entrée de message unique, lorsque les sous-agents d’arrière-plan s’exécutent toujours à la fin du dernier tour, Claude Code les attend, jusqu’à la limite décrite dans tâches d’arrière-plan à la sortie, avant d’émettre le résultat. Le
total_cost_usd, duration_api_ms et modelUsage du résultat, ou model_usage en Python, incluent le travail effectué pendant cette attente.
Les exemples suivants itèrent sur le flux de messages d’un appel query() et impriment le coût total à l’arrivée du message result :
total_cost_usd, définissez les limites de profondeur, de concurrence et de dépenses sur la requête.
Suivre l’utilisation par étape et par modèle
Les exemples de cette section utilisent les noms de champs TypeScript. En Python, les champs équivalents sontAssistantMessage.usage et AssistantMessage.message_id pour l’utilisation par étape, et ResultMessage.model_usage pour les ventilations par modèle.
Suivre l’utilisation par étape
Chaque message d’assistant contient unBetaMessage imbriqué (accessible via message.message) avec un id et un objet usage contenant les comptages de jetons. Lorsque Claude utilise des outils en parallèle, plusieurs messages partagent le même id avec des données d’utilisation identiques. Suivez les ID que vous avez déjà comptabilisés et ignorez les doublons pour éviter des totaux gonflés.
L’exemple suivant accumule les jetons d’entrée sur toutes les étapes, en comptant chaque ID de message de boucle principale unique une seule fois et en ignorant les messages des sous-agents, et lit le total de sortie du message de résultat, qui couvre la boucle principale :
Ventiler l’utilisation par modèle
Le message de résultat inclutmodelUsage, une carte du nom du modèle aux comptages de jetons par modèle et au coût. Ceci est utile lorsque vous exécutez plusieurs modèles (par exemple, Haiku pour les sous-agents et Opus pour l’agent principal) et que vous souhaitez voir où vont les jetons.
Le costBasis de chaque entrée indique quelle table de prix a tarifé la dernière demande de ce modèle : list pour le prix catalogue, managed pour une table modelPricing, ou unknown lorsqu’aucune ne correspondait à l’ID du modèle. Le champ nécessite Claude Code v2.1.246 ou version ultérieure.
L’exemple suivant exécute une requête et affiche la ventilation des coûts et des jetons pour chaque modèle utilisé :
Accumuler les coûts sur plusieurs appels
Chaque appelquery() retourne total_cost_usd sur ses résultats. La façon dont vous combinez les valeurs dépend de si les appels partagent une session :
- Appels indépendants, sans option
resumeoucontinue: chaque résultat couvre uniquement son propre appel, donc additionnez les totaux vous-même, comme le font les exemples ci-dessous. - Appels qui reprennent la même session : Claude Code enregistre les totaux de la session dans sa transcription lorsque le processus se termine normalement et les restaure lorsqu’un appel ultérieur reprend ou crée une branche de la session. Chaque résultat inclut déjà les dépenses antérieures de la session. Lisez le dernier résultat pour le total de la session ; additionner les résultats double-compte les dépenses restaurées. Avant v2.1.277, une session que vous aviez reprise via le SDK ou
claude -pcommençait ses totaux à zéro, donc chaque appel couvrait uniquement cet appel.
query() séquentiellement, ajoutent le total_cost_usd de chaque appel à un total cumulatif, et affichent à la fois le coût par appel et le coût combiné :
Gérer les erreurs, la mise en cache et les comptages de jetons de sortie
Pour un suivi précis des coûts, tenez compte du comptage de sortie fictif sur les messages d’assistant, des jetons qu’une conversation échouée a consommés et de la tarification des jetons en cache.Lire les jetons de sortie du message de résultat
Claude Code construit chaque message d’assistant à partir de l’utilisation que l’API a signalée au début de la réponse, de sorte que leoutput_tokens du message n’est que le comptage que l’API avait signalé à message_start, avant que la réponse ne soit générée. Une réponse API peut produire plusieurs messages d’assistant, et chacun d’eux porte ce même placeholder.
L’API signale le comptage de sortie réel à la fin de la réponse, et Claude Code l’ajoute au message de résultat. Lisez les jetons de sortie à partir de usage du résultat, ou à partir de modelUsage pour une ventilation par modèle.
Pour regarder le comptage de sortie d’une réponse augmenter pendant qu’elle est diffusée en continu, définissez includePartialMessages, ou include_partial_messages en Python, et lisez usage à partir de chaque événement de flux message_delta, typé comme SDKPartialAssistantMessage en TypeScript et StreamEvent en Python.
Suivre les coûts sur les conversations échouées
Les messages de résultat de succès et d’erreur incluent tous deuxusage et total_cost_usd ; en Python, les deux champs sont typés comme optionnels, donc vérifiez qu’ils ne sont pas None avant de les lire.
Si une conversation échoue à mi-chemin, vous avez toujours consommé des jetons jusqu’au point de défaillance. Lisez les données de coût à partir de chaque message de résultat, que son subtype soit success ou l’un des sous-types d’erreur. Sur certains résultats d’erreur, usage signale moins que ce que l’appel a dépensé :
error_during_executionaprès un plantage de session : chaque champ de coût peut être mis à zéro.error_max_budget_usd:usageomet la réponse qui a dépassé le budget, tandis quetotal_cost_usdetmodelUsagel’incluent.
total_cost_usd ou modelUsage plutôt que de usage.
Récupérer les totaux après un plantage de session
Lorsque le processus Claude Code plante, il émet un résultaterror_during_execution final et se termine, en mode d’entrée unique et en mode d’entrée en continu. Ce résultat peut porter des usage, total_cost_usd et modelUsage mis à zéro, donc récupérez les totaux de l’appel à partir de ce qui est arrivé avant. L’étape 1 récupère les totaux complets chaque fois qu’un résultat antérieur existe ; le secours à l’étape 2 récupère uniquement les jetons d’entrée et de cache de la boucle principale.
- Utilisez le résultat du tour avant le plantage. En mode d’entrée en continu, il contient le total cumulé décrit dans Suivre les coûts en mode d’entrée en continu. Allez à l’étape 2 à la place lorsque ce résultat ne peut pas vous aider :
- L’appel était unique, donc aucun résultat antérieur n’existe.
- Le plantage s’est produit au premier tour.
- Le tour avant le plantage était le
/clearlui-même, donc son résultat couvre uniquement la réinitialisation.
- Additionnez plutôt le
usagesur les messages d’assistant, en comptant chaque réponse API une fois, comme l’exemple Track per-step usage le fait. En mode unique, additionnez-les tous ; en mode d’entrée en continu, additionnez ceux qui sont arrivés après le dernier résultat. Cela vous donne les jetons d’entrée et de cache de la boucle principale. L’utilisation des sous-agents n’est pas récupérable de cette façon, pas plus que les jetons de sortie ou le coût en USD, car leoutput_tokenspar étape est un placeholder.
Suivre les jetons en cache
Le SDK Agent utilise automatiquement la mise en cache des invites pour réduire les coûts sur le contenu répété. Vous n’avez pas besoin de configurer la mise en cache vous-même. L’objet d’utilisation inclut deux champs supplémentaires pour le suivi du cache :cache_creation_input_tokens: jetons utilisés pour créer de nouvelles entrées de cache (facturés à un taux plus élevé que les jetons d’entrée standard).cache_read_input_tokens: jetons lus à partir des entrées de cache existantes (facturés à un taux réduit).
input_tokens pour comprendre les économies de mise en cache. En TypeScript, ces champs sont typés sur l’objet Usage. En Python, ils apparaissent comme des clés dans le dictionnaire ResultMessage.usage (par exemple, message.usage.get("cache_read_input_tokens", 0)).
Étendre le TTL du cache d’invite à une heure
Vos propres tours se situent dans le bucket TTL de conversation principal, ainsi que les assistants que Claude Code exécute en ligne avec eux. Les demandes que Claude Code effectue en dehors de cette conversation, telles que les sous-agents, ont un contrôle TTL séparé. Les entrées de cache pour vos propres tours utilisent un TTL de 5 minutes par défaut lorsque vous vous authentifiez avec une clé API ou que vous exécutez sur Amazon Bedrock, la plateforme d’agent de Google Cloud, Microsoft Foundry, ou Claude Platform on AWS. Si votre charge de travail exécute de nombreuses sessions courtes contre le même invite système et contexte avec des écarts plus longs que 5 minutes entre elles, le cache expire entre les sessions et chaque nouvelle session paie le prix d’entrée complet. Pour demander un TTL d’1 heure sur les écritures de cache, définissez la variable d’environnementENABLE_PROMPT_CACHING_1H. Vous pouvez l’exporter dans votre environnement shell ou conteneur, ou la transmettre via options.env.
L’exemple suivant active le TTL d’1 heure pour un agent s’exécutant sur Amazon Bedrock. Parce qu’il définit CLAUDE_CODE_USE_BEDROCK, il nécessite des identifiants AWS fonctionnels pour Amazon Bedrock ; sans eux, la requête échoue.
ENABLE_PROMPT_CACHING_1H demande le TTL d’1 heure sur chaque demande dans les deux buckets. Pour choisir un TTL pour chaque bucket séparément, utilisez plutôt ces contrôles. Chacun prend 5m ou 1h et a la priorité sur ENABLE_PROMPT_CACHING_1H :
- Conversation principale : la variable d’environnement
CLAUDE_CODE_PROMPT_CACHE_TTL, ou le paramètrepromptCacheTtl - Tout le reste : la variable d’environnement
CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL, ou le paramètresubagentPromptCacheTtl
promptCacheTtl à 1h maintient le cache d’1 heure sur la conversation principale tandis que vous tirez sur les crédits d’utilisation. Pour l’ordre de précédence complet, consultez choisir le TTL vous-même.
Documentation connexe
- Référence du SDK TypeScript - Documentation complète de l’API
- Aperçu du SDK - Prise en main du SDK
- Permissions du SDK - Gestion des permissions des outils