Claude Code agent_summary : mesurer et réduire les coûts

Mesurez les requêtes qui produisent les libellés de progression des agents en arrière-plan de Claude Code. Comparez les 16.4% estimés par une équipe aux 2% globaux et aux 6% dans le terminal rapportés par l’équipe Claude Code. Utilisez un récepteur OpenTelemetry local, puis évaluez le correctif de cache de 2.1.311+, les contrôles des agents et les correctifs communautaires.

Sommaire
Claude Code agent_summary : mesurer et réduire les coûts

Mettez Claude Code à jour vers 2.1.311 ou une version ultérieure, puis mesurez agent_summary avec OpenTelemetry avant de désactiver les fonctions d’agent. Ces requêtes de résumé peuvent augmenter les coûts pendant que les agents travaillent en arrière-plan. Le chiffre de 16.4% souvent cité représente la part des coûts estimés d’une équipe, pas une surcharge universelle de tokens.

Ce que fait agent_summary

agent_summary produit des libellés de progression au moyen de requêtes distinctes au modèle. Dans son rapport sur Claude Code 2.1.312, dblumenau décrit l’envoi de l’historique d’un agent actif en arrière-plan à son propre modèle. Le résultat demandé était un libellé de trois à cinq mots. Cette reproduction utilisait Haiku : le mécanisme ne concerne donc pas uniquement Opus.

Les agents actifs en arrière-plan peuvent déclencher ces requêtes toutes les 30 secondes environ. Si l’historique ne change pas, certains déclenchements peuvent être ignorés, comme l’indique le journal officiel des modifications. Comptez les requêtes réelles plutôt que de multiplier les minutes écoulées par deux.

Le volume du contexte peut donc peser davantage sur le coût que la longueur du libellé affiché. Examinez le modèle indiqué et l’utilisation du cache pour comprendre les coûts.

Ce mécanisme est distinct de la barre d’état configurable du terminal. La documentation de la ligne d’état personnalisée décrit un script local qui ne consomme aucun token d’API. Supprimer ce script ne désactive pas les requêtes de résumé au modèle.

Ce que mesurent réellement 16.4%, 2% et 6%

Ces trois pourcentages de coût portent sur des populations différentes. Au 2026-11-01, les rapports publiés pertinents sont les suivants :

SourcePopulation et périodePart des coûts attribuée aux résumésBase de calcul
Flamerix AIUne semaine de mesures dans une équipe16.4%Estimations cost_usd de Claude Code pour chaque requête
edwinarbus, membre de l’équipe Claude CodeUtilisateurs envoyant de la télémétrie, pendant la semaine précédant la réponse du 29 octobreEnviron 2%Tarifs catalogue de l’API
Même réponse, sous-ensemble utilisant le terminalUtilisation du terminal dans cet échantillon de télémétrieEnviron 6%Tarifs catalogue de l’API

Flamerix a également indiqué que les résumés représentaient 19.7% des requêtes d’API. La part des requêtes et la part des coûts ont des dénominateurs différents. Aucune des deux ne détermine la part du quota de votre abonnement consommée par les résumés.

Ces rapports justifient une mesure de votre propre utilisation. Une équipe qui délègue de nombreuses tâches longues peut obtenir un résultat très différent d’un développeur travaillant surtout dans la conversation principale.

Mettez à jour sans présumer d’une économie fixe

Selon la réponse de l’équipe Claude Code, la version 2.1.311+ corrige le cas coûteux des requêtes de résumé qui ne réutilisent pas le cache de prompts. Il s’agit d’un correctif de cache, pas de la suppression des requêtes de résumé. Cette annonce ne permet pas de prévoir une économie fixe pour vos sessions.

Si vous avez utilisé l’installateur natif, exécutez ces commandes dans Bash :

claude --version
claude update
claude --version

Redémarrez Claude Code après la mise à jour. Si un gestionnaire de paquets gère l’installation, utilisez sa commande de mise à jour dans les instructions officielles. Vérifiez la version obtenue. Le canal de mise à jour ou les règles de votre organisation peuvent la limiter.

La même réponse décrit un mode moins coûteux en cours de développement, fondé sur de courtes notes et un modèle plus petit. Elle ne donne aucune date de lancement. Au 2026-11-01, aucun réglage public permettant d’activer ce mode n’est documenté. N’intégrez pas encore ces économies à votre budget.

Mesurez votre session avec OpenTelemetry

Collectez les événements de journal claude_code.api_request, puis regroupez-les par query_source. La référence de surveillance de l’utilisation décrit cet attribut, le modèle indiqué dans model et le coût estimé cost_usd.

Si votre organisation collecte déjà ces événements, utilisez sa plateforme de supervision. Filtrez une session ou une période définie, comptez les événements de requête API et additionnez cost_usd par source. Ajoutez model comme second critère de regroupement pour comparer les modèles.

L’exemple local ci-dessous nécessite Bash, Python 3 et une installation de Claude Code avec une authentification déjà fonctionnelle. Utilisez une machine dont vous contrôlez la destination de télémétrie. Le récepteur conserve les agrégats en mémoire et affiche des métadonnées sans nécessiter la capture des prompts ou des réponses bruts.

Démarrez le récepteur local

Exécutez ce bloc dans un premier terminal. Il reçoit les données OTLP HTTP JSON sur l’interface de bouclage et affiche les totaux cumulés par source :

python3 -u - <<'PY'
import gzip, json, math
from collections import defaultdict
from http.server import BaseHTTPRequestHandler, HTTPServer

rows = defaultdict(lambda: [0, 0.0, 0])
models = defaultdict(set)
seen = set()

def scalar(value):
    return next((value[k] for k in ("stringValue", "doubleValue", "intValue", "boolValue")
                 if k in value), None)

def report():
    count = sum(row[0] for row in rows.values())
    cost = sum(row[1] for row in rows.values())
    missing = sum(row[2] for row in rows.values())
    print("\nquery_source\trequests\trequest_%\tknown_USD\tcost_%\tmissing_cost\tmodels")
    for source, (n, usd, absent) in sorted(rows.items()):
        share = f"{100 * usd / cost:.2f}" if cost > 0 and not missing else "n/a"
        names = ",".join(sorted(models[source]))
        print(f"{source}\t{n}\t{100 * n / count:.2f}\t{usd:.6f}\t{share}\t{absent}\t{names}")
    print(f"Total API records: {count}; missing costs: {missing}", flush=True)

class Receiver(BaseHTTPRequestHandler):
    def log_message(self, *args):
        pass

    def do_POST(self):
        if self.path != "/v1/logs":
            self.send_error(404)
            return
        raw = self.rfile.read(int(self.headers.get("Content-Length", "0")))
        try:
            if self.headers.get("Content-Encoding") == "gzip":
                raw = gzip.decompress(raw)
            data = json.loads(raw)
        except (ValueError, OSError):
            self.send_error(400)
            return
        for resource in data.get("resourceLogs", []):
            for scope in resource.get("scopeLogs", []):
                for record in scope.get("logRecords", []):
                    a = {item["key"]: scalar(item["value"])
                         for item in record.get("attributes", [])}
                    event = a.get("event.name") or scalar(record.get("body", {}))
                    if event in ("user_prompt", "claude_code.user_prompt"):
                        print("Received user_prompt event.", flush=True)
                    if event not in ("api_request", "claude_code.api_request"):
                        continue
                    identity = a.get("request_id") or json.dumps(record, sort_keys=True)
                    if identity in seen:
                        continue
                    seen.add(identity)
                    source = str(a.get("query_source") or "(missing)")
                    models[source].add(str(a.get("model") or "(missing)"))
                    row = rows[source]
                    row[0] += 1
                    try:
                        usd = (float(a["cost_usd"]) if a.get("cost_usd") is not None
                               else float(a["cost_usd_micros"]) / 1_000_000)
                        if not math.isfinite(usd) or usd < 0:
                            raise ValueError()
                        row[1] += usd
                    except (KeyError, ValueError, TypeError):
                        row[2] += 1
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(b"{}")
        report()

server = HTTPServer(("127.0.0.1", 4318), Receiver)
print("Listening on 127.0.0.1:4318. Stop after Claude exits with Ctrl+C.", flush=True)
try:
    server.serve_forever()
except KeyboardInterrupt:
    pass
finally:
    server.server_close()
    report()
PY

Lancez la session à mesurer

Exécutez ce bloc dans un second terminal. Le sous-shell limite ces changements de variables d’environnement au processus mesuré :

(
  export CLAUDE_CODE_ENABLE_TELEMETRY=1
  export OTEL_LOGS_EXPORTER=otlp
  export OTEL_METRICS_EXPORTER=none
  export OTEL_TRACES_EXPORTER=none
  export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=http/json
  export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://127.0.0.1:4318/v1/logs
  export OTEL_LOGS_EXPORT_INTERVAL=1000
  claude
)

Choisissez une tâche habituelle qui justifie un travail en arrière-plan. Par exemple, demandez à un agent d’examiner les tests d’authentification en arrière-plan, sans modifier de fichiers. Continuez à travailler dans la conversation principale et vérifiez que l’agent démarre réellement.

Gardez une session interactive, sans transmettre la sortie de Claude à un autre programme via un tube. Remplacer ce lancement par claude -p change le mode d’exécution et peut modifier le comportement des résumés.

Après l’envoi d’un prompt, le premier terminal doit afficher Received user_prompt event.. Les lignes correspondant aux requêtes d’API doivent ensuite apparaître. Laissez la tâche se terminer, quittez Claude normalement et attendez le dernier export avant d’arrêter le récepteur avec Ctrl+C. Copiez le tableau final depuis l’historique du terminal.

Interprétez les résultats et diagnostiquez les données manquantes

Repérez la ligne agent_summary pour la période mesurée. Le dénominateur de request_% est le nombre total d’événements de requête API capturés. Celui de cost_% est la somme des coûts estimés de toutes les requêtes API capturées :

summary cost share = 100 × summary estimated USD / all captured estimated USD

La colonne models répertorie les modèles indiqués pour chaque source. Pour étudier le cache dans votre plateforme de supervision, examinez aussi input_tokens, cache_read_tokens, cache_creation_tokens et output_tokens.

Le récepteur conserve dans le dénominateur les requêtes sans source, regroupées sous (missing). Si une seule requête capturée n’a pas de coût valide, il affiche n/a pour les pourcentages de coût. Résolvez les champs manquants avant de considérer la ventilation comme complète.

L’absence de ligne agent_summary signifie qu’aucune requête de ce type n’a été observée pendant cette période. Elle ne prouve pas que la fonction est désactivée. Vérifiez d’abord la présence d’événements de prompt, de requêtes d’API et d’un travail réel en arrière-plan.

Si rien n’arrive, vérifiez que le récepteur fonctionne, que le protocole est http/json et que l’adresse se termine par /v1/logs. Une destination gérée par l’organisation peut remplacer la configuration locale. Pour approfondir le diagnostic, lancez claude --debug-file ./otel-debug.log dans le même sous-shell. Recherchez les erreurs de l’exporteur portant le préfixe [3P telemetry] en suivant le guide de surveillance.

Pourquoi les historiques, /usage et les factures peuvent différer

L’absence d’une ligne dans l’historique peut masquer l’origine des coûts sans fausser le total de la session. Dans le ticket #104358, rabitlord1324 signale des enregistrements manquants pour les requêtes en arrière-plan. Il décrit toutefois la comptabilisation interne de Claude Code comme correcte.

La documentation actuelle de l’utilisation décrit les totaux de session et l’utilisation par modèle. Elle ne fournit pas la ventilation par query_source nécessaire ici. Ne concluez pas que tous les résumés sont absents de /usage parce qu’un analyseur d’historique les ignore.

cost_usd reste une estimation. Claude Code utilise normalement les tarifs catalogue, mais le paramètre administré modelPricing peut modifier les tarifs utilisés dans les rapports. La consommation du quota d’abonnement et les frais d’API sont deux mesures distinctes. Avec une facturation à l’usage, rapprochez vos calculs des données réelles de votre fournisseur.

Pour BetterToken, l’URL de base documentée pour Claude Code est https://bettertoken.ai. Au 2026-11-01, son catalogue répertorie claude-opus-5-5. Comparez les modèles, les tokens consommés et les frais dans la console, sur la même période de mesure.

Réduisez les coûts sans perdre de travail utile

Commencez par des tâches plus ciblées ou moins d’agents en arrière-plan si le surcoût mesuré est significatif. Au 2026-11-01, les références des variables d’environnement et des sous-agents ne documentent aucune option désactivant uniquement les résumés.

OptionEffetCompromis
Moins de tâches en arrière-plan, ou des tâches plus courtesRéduit les occasions de résumer à nouveau les historiquesPeut réduire le parallélisme utile ; comparez le temps nécessaire
Un modèle plus petit pour un sous-agent chargé d’une tâche délimitéeChange le modèle qui effectue le travail déléguéVérifiez la qualité du résultat et le modèle réellement indiqué dans la télémétrie
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 claudeDésactive l’exécution en arrière-plan dans les outils concernésClaude attend la fin des sous-agents avant de continuer
CLAUDE_CODE_FORK_SUBAGENT=0 claudeDésactive la création autonome de branches de conversationLes sous-agents peuvent encore travailler en arrière-plan ; l’arrêt des résumés n’est pas garanti
Correctif communautaire via Bun preloadTente d’intercepter le minuteur des résumésExécute du code tiers dans Claude Code et peut cesser de fonctionner après une mise à jour

La variable de contrôle des tâches en arrière-plan supprime run_in_background et empêche le passage automatique en arrière-plan via les outils concernés. Les tâches MCP, l’outil Monitor et les sessions distinctes en arrière-plan ont des exceptions ou des contrôles séparés. Cette variable ne désactive donc pas toute activité en arrière-plan.

Le contrôle du mode fork est documenté, mais l’arrêt des résumés comme effet secondaire n’est pas garanti. Avec 2.1.312, chrisvaillancourt a signalé leur arrêt sur macOS. dblumenau observait encore des requêtes sur Linux. La configuration et le mode d’exécution diffèrent entre ces rapports.

Définissez la variable avant de lancer une nouvelle session. Vérifiez les entrées env dans ~/.claude/settings.json et les paramètres du projet. Elles peuvent remplacer les valeurs héritées du shell.

Considérez le correctif préchargé de Flamerix comme une solution communautaire expérimentale. Examinez une révision précise et figée du code avant d’envisager son utilisation. Vérifiez le nombre de requêtes après chaque mise à jour du client. Un libellé figé ne suffit pas à prouver l’arrêt des requêtes.

Pour des recherches ciblées, consultez le guide de vérification du modèle d’un sous-agent en lecture seule. Si de volumineuses définitions d’outils alourdissent le contexte, utilisez le comparatif des coûts du contexte MCP. Il permet de tester l’intérêt d’un ensemble d’outils plus réduit.

Changez un seul paramètre à la fois. Comparez la même tâche, le même modèle, les mêmes conditions de contexte et l’obtention d’un résultat acceptable. Examinez aussi le temps écoulé et les coûts par source. Rétablissez le travail en arrière-plan si la perte de parallélisme utile coûte plus que l’économie mesurée.

Prêt à optimiser votre workflow LLM ?

Connectez vos modèles via une API unique, gérez les clés et maîtrisez vos dépenses d’IA.

Commencer gratuitement