Claude Code agent_summary: как измерить и снизить расход токенов
Проверьте расходы на сводки фоновых агентов Claude Code через локальный приёмник OpenTelemetry. Разберите оценки 16.4%, 2% и 6%, отделите расчётную стоимость от лимитов подписки и выберите способ снизить затраты: обновление, ограничения фоновой работы или смену модели.
Содержание

Обновите Claude Code до 2.1.311 или новее и измерьте расход agent_summary через OpenTelemetry. Решайте, нужно ли отключать фоновых агентов, по результатам этого замера. Оценка 16.4% — доля расчётных затрат одной команды, а не универсальная надбавка к расходу токенов.
Что делает agent_summary
Служебные запросы agent_summary создают короткие подписи о работе фоновых агентов. В отчёте о Claude Code 2.1.312 dblumenau описал повторную отправку всей истории работающего фонового агента его модели. Модель должна была вернуть подпись из трёх–пяти слов. В этом примере агент работал на Haiku, поэтому механизм не ограничен Opus.
Пока фоновый агент работает, такие запросы могут выполняться примерно раз в 30 секунд. Если история не изменилась, очередной вызов может быть пропущен, как описано в официальном журнале изменений. Поэтому считайте реальные запросы, а не удваивайте число прошедших минут.
На стоимость может сильнее влиять объём контекста, чем длина видимой подписи. Проверяйте модель запроса и использование кэша.
Настраиваемая строка состояния терминала — другой механизм. В документации строки состояния описан локальный скрипт, который не расходует API-токены. Удаление такого скрипта не отключает запросы agent_summary.
Что означают 16.4%, 2% и 6%
Эти доли затрат относятся к разным выборкам. По состоянию на 2026-11-01 опубликованы следующие оценки:
| Источник | Выборка и период | Доля затрат на сводки | Основа расчёта |
|---|---|---|---|
| Flamerix AI | Неделя измерений одной команды | 16.4% | Оценки cost_usd для отдельных запросов Claude Code |
| Участник команды Claude Code edwinarbus | Пользователи, отправляющие телеметрию; неделя перед ответом 29 октября | Около 2% | Стоимость по прайс-листу API |
| Тот же ответ команды: терминал | Работа в терминале внутри этой выборки | Около 6% | Стоимость по прайс-листу API |
Flamerix отдельно сообщила, что на сводки пришлось 19.7% API-запросов. Доля запросов и доля затрат считаются от разных величин. Ни одна из них не показывает, какая часть лимита вашей подписки ушла на сводки.
Проверьте собственные задачи, прежде чем переносить на них чужие проценты. У команды с множеством длительных фоновых задач результат может заметно отличаться от сеанса, где работа идёт в основном диалоге.
Что даст обновление до 2.1.311+
Версия 2.1.311+ исправляет дорогие запросы сводок, которые не использовали кэш промпта, согласно ответу команды Claude Code. Это исправление кэширования, а не отключение сводок. Оно не гарантирует одинаковую экономию во всех сеансах.
Если Claude Code установлен нативным установщиком, обновите его в Bash:
claude --version
claude update
claude --version
После обновления перезапустите Claude Code. Если установкой управляет пакетный менеджер, используйте его команду обновления из официальной инструкции. Проверьте итоговую версию: канал обновлений или правила организации могут ограничивать доступный выпуск.
В том же ответе команда описывает разработку более дешёвого режима с короткими заметками и моделью меньшего размера. Дата выпуска не указана. На 2026-11-01 публичная настройка для включения этого режима не документирована. Пока не закладывайте эту экономию в бюджет.
Как измерить расход через OpenTelemetry
Соберите события журнала claude_code.api_request и сгруппируйте их по query_source — подсистеме, отправившей запрос. В справочнике мониторинга описаны этот атрибут, модель в поле model и расчётная стоимость cost_usd.
Если организация уже собирает такие события, используйте её систему мониторинга. Выберите один сеанс или фиксированный интервал, посчитайте API-запросы и сложите cost_usd по каждому источнику. Для сравнения моделей добавьте вторую группировку по model.
Для локального примера нужны Bash, Python 3 и Claude Code с уже настроенной аутентификацией. Используйте компьютер, где вы сами задаёте адрес получателя телеметрии. Приёмник хранит итоговые значения в памяти и выводит метаданные; записывать исходные промпты и ответы не требуется.
Запустите локальный приёмник
В первом окне терминала запустите код ниже. Приёмник принимает OTLP HTTP JSON только на 127.0.0.1 и выводит накопленные итоги по источникам запросов:
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
Запустите сеанс для замера
Во втором окне терминала выполните следующий блок. Подоболочка ограничивает изменения переменных окружения этим запуском Claude Code:
(
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
)
Выберите обычную задачу, для которой полезна фоновая работа. Например, попросите фонового агента проверить тесты аутентификации без изменения файлов. Продолжайте работу в основном диалоге и убедитесь, что фоновый агент действительно запущен.
Сохраните интерактивный режим и не передавайте вывод Claude через конвейер. Замена запуска на claude -p меняет режим работы и может изменить поведение сводок.
После отправки промпта в первом окне должно появиться сообщение Received user_prompt event.. Затем должны появиться строки API-запросов. Дождитесь завершения задачи, выйдите из Claude обычным способом и дождитесь последней отправки телеметрии. После этого остановите приёмник сочетанием Ctrl+C и скопируйте итоговую таблицу из истории вывода терминала.
Как прочитать результат и найти пропуски
Найдите строку agent_summary за выбранный интервал. В request_% знаменатель — все полученные события API-запросов. В cost_% — сумма расчётной стоимости всех полученных API-запросов:
summary cost share = 100 × summary estimated USD / all captured estimated USD
Столбец models перечисляет модели, зафиксированные для каждого источника. Если проверяете кэш в существующей системе мониторинга, изучите также input_tokens, cache_read_tokens, cache_creation_tokens и output_tokens.
Запросы без источника остаются в общем расчёте под именем (missing). Если хотя бы у одного запроса нет корректной стоимости, приёмник выводит n/a вместо долей затрат. Устраните пропуски в полях, прежде чем считать разбивку полной.
Отсутствие строки agent_summary означает лишь, что за этот интервал такие запросы не наблюдались. Это не доказывает, что функция отключена. Сначала убедитесь, что поступили события промптов и API-запросов, а агент действительно работал в фоне.
Если ничего не поступает, проверьте, что приёмник запущен, протокол задан как http/json, а адрес заканчивается на /v1/logs. Адрес, заданный организацией, может иметь приоритет над локальными настройками. Для дальнейшей диагностики запустите claude --debug-file ./otel-debug.log внутри той же подоболочки. Найдите ошибки экспортёра с префиксом [3P telemetry], следуя инструкции мониторинга.
Почему история сеанса, /usage и счёт могут расходиться
Пропуск записи в истории может скрыть источник расхода, даже если общий итог сеанса верен. В отчёте #104358 rabitlord1324 сообщает об отсутствующих записях фоновых запросов, но отмечает корректность внутреннего учёта Claude Code.
В документации /usage описаны итоги сеанса и расход по моделям. Нужная здесь разбивка по query_source в документации не приведена. Если анализатор истории пропустил запросы сводок, это ещё не доказывает их отсутствие в общем итоге /usage.
cost_usd — расчётная стоимость. Обычно Claude Code использует цены по прайс-листу, но управляемая настройка modelPricing позволяет задать другие ставки для отчётов. Расход лимита подписки и списания за API — разные величины. При оплате по факту использования сверяйте расчёты с реальными данными провайдера.
Если вы используете BetterToken, базовый адрес для Claude Code — https://bettertoken.ai. По состоянию на 2026-11-01 в каталоге есть claude-opus-5-5. Сверьте выбранный интервал с моделью, расходом токенов и списаниями в консоли.
Для подключения к API BetterToken из России VPN не нужен. BetterToken поддерживает оплату в рублях. Актуальные условия оплаты смотрите в консоли. Эти условия не охватывают доступ к сторонним сайтам, загрузкам, входу в аккаунты и обновлениям. API-доступ не включает подписку Claude.ai.
Как снизить расходы и сохранить полезную работу
Если затраты на сводки существенны для вашего бюджета, начните с более узких задач или меньшего числа фоновых агентов. На 2026-11-01 в справочниках переменных окружения и субагентов нет документированного переключателя только для сводок.
| Вариант | Что меняется | Ограничение |
|---|---|---|
| Меньше фоновых задач или более короткие задачи | Меньше поводов повторно отправлять историю для сводок | Можно потерять полезный параллелизм; сравните время выполнения |
| Модель меньшего размера для субагента с узкой задачей | Меняется модель, которая выполняет порученную задачу | Проверьте качество результата и модель, указанную в телеметрии |
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 claude | Отключает фоновое выполнение для соответствующих инструментов | Claude ждёт завершения субагентов, прежде чем продолжить |
CLAUDE_CODE_FORK_SUBAGENT=0 claude | Запрещает Claude самостоятельно создавать ответвления диалога | Фоновые субагенты всё ещё могут работать; отключение сводок не гарантировано |
| Патч сообщества через Bun preload | Пытается перехватить таймер сводок | Сторонний код работает внутри Claude Code; обновление клиента может нарушить работу патча |
Переменная управления фоновыми задачами убирает run_in_background и отключает автоматический перенос работы в фон для соответствующих инструментов. Для задач MCP, инструмента Monitor и отдельных фоновых сеансов есть исключения или отдельные настройки. Это не общий выключатель всей фоновой активности.
Переключатель режима fork, который управляет ответвлениями диалога, документирован. Однако отключение сводок как побочный эффект не гарантировано. На 2.1.312 chrisvaillancourt сообщил об их остановке на macOS. dblumenau продолжал наблюдать такие запросы на Linux. В этих отчётах различаются настройки и режим запуска.
Задайте переменную перед запуском нового сеанса. Проверьте конфликтующие записи env в ~/.claude/settings.json и настройках проекта: они могут заменить значения из оболочки.
Рассматривайте preload-патч Flamerix как экспериментальный способ от сообщества, который подгружает сторонний код при запуске Claude Code. Изучите код закреплённой ревизии перед применением. После каждого обновления клиента проверяйте число запросов: застывшая подпись сама по себе не доказывает, что запросы прекратились.
Для узких исследовательских задач пригодится руководство по проверке модели субагента в режиме только чтения. Если определения инструментов раздувают контекст, сравните стоимость контекста MCP и проверьте эффект от меньшего набора инструментов.
Меняйте по одному параметру. Сравнивайте одну и ту же задачу, модель и условия контекста. Кроме затрат по источникам учитывайте, получен ли приемлемый результат и сколько времени потребовала работа. Верните фоновую работу, если потеря полезного параллелизма обходится дороже измеренной экономии.