К курсу

Цикл агента

Один шаг цикла агентаПрактика: один шаг циклаЦикл в кодеПрактика: цикл в кодеОстановка и повторыПрактика: остановка и повторыЧто решает только кодПрактика: что решает код

Надёжность в проде

Таймаут и ключ идемпотентностиПрактика: таймаут и ключ идемпотентности

Устройство агентов

Workflow или агентПрактика: workflow или агентReAct и plan-and-executeПрактика: ReAct и plan-and-executeОдин агент или ройПрактика: один агент или рой

Контекст и стоимость

Почему растёт счёт за агентаПрактика: токены и кэшКонтекст-инженерияПрактика: управление окномПамять агентаПрактика: что агент хранит

Инструменты и протоколы

MCPПрактика: MCP
←→ENВойти
Агенты › Контекст и стоимость

Почему растёт счёт за агента

Опирается наОдин шаг цикла агента

В этом блоке посчитаем, почему счёт за входные токены растёт быстрее числа шагов, что меняет кэширование промпта и что незаметно его выключает. Цены взяты со страниц провайдеров 2026-11-10. Меняются они часто, поэтому считайте их примерами для расчёта.

Спорный возврат в Northwind Goods занимает у агента поддержки 20 вызовов модели, обычное обращение — 10. В финансах ждали, что спорный случай обойдётся вдвое дороже. Он обходится больше чем втрое.

Снова зачитать записи

Вернёмся к коллеге на телефоне, который забывает всё, как только вы кладёте трубку. Перезванивая, вы каждый раз зачитываете весь разговор с начала и платите за каждое прочитанное слово. Первое чтение короткое. Двадцатое длинное, и большую часть слов в нём вы уже оплачивали.

Возьмём три числа из этого прогона:

Получается, вызов 1 отправляет 6 000, вызов 2 — 7 500, а вызов 20 — 34 500.

Счёт — это площадь столбиков: плоский прямоугольник и треугольник, который растёт вместе с прогоном.
Счёт — это площадь столбиков: плоский прямоугольник и треугольник, который растёт вместе с прогоном.

Если сложить столбики, получится формула, где n — число вызовов, P — токены в начале, d — токены, добавленные за шаг:

всего на входе = n * P + d * n * (n - 1) / 2

Вызовов

Всего входных токенов

10

127 500

20

405 000

40

1 410 000

При переходе от 20 вызовов к 40 вход вырастает в 3,5 раза. Первое слагаемое растёт вместе с n, второе — с квадратом n. В коротких прогонах первое заслоняет второе, поэтому на быстром тесте всё выглядит безобидно.

На Claude Sonnet 5.5 миллион входных токенов стоит $2, выходных — $10. Прогон из 20 вызовов тратит $0,81 на вход и $0,06 на выход, то есть вход составляет 93% счёта.

Копия на столе

Допустим, коллега снимает копию того, что вы прочитали, и держит её на столе пять минут. Вы всё равно читаете с самого начала. Пока ваши слова совпадают с копией, он просто ведёт по ней пальцем, а это быстро и дёшево. На первом же несовпавшем слове копия перестаёт помогать, и дальше он слушает как обычно.

Это и есть кэширование промпта. Провайдер хранит результат обработки начала промпта, то есть префикса. В API вроде Anthropic всю историю вы всё равно отправляете при каждом вызове, и вся она по-прежнему остаётся контекстом модели. Дешевле становится только совпавшая часть.

В Messages API от Anthropic кэширование включаете вы сами. Ваш код добавляет одно поле:

{
  "model": "claude-sonnet-5-5",
  "max_tokens": 1024,
  "cache_control": {
    "type": "ephemeral"
  },
  "system": "You are the Northwind support agent...",
  "messages": []
}

Что происходит от вызова к вызову при такой настройке:

Вызов 1. API ничего не находит, обрабатывает промпт и сохраняет его. Это запись, она стоит в 1,25 раза дороже обычного входа при стандартном сроке в 5 минут.

Вызов 2. API находит тот же префикс и читает его. На Sonnet 5.5 чтение стоит 0,05 от цены входа. Блок, добавленный после вызова 1, записывается.

Каждое чтение бесплатно продлевает эти 5 минут. Отсчёт идёт с начала запроса, поэтому долгий ответ тоже расходует это время. Если прогон остановится дольше, следующий вызов запишет всё заново.

Каждый вызов читает то, что сохранил предыдущий, и записывает только новое. Долгая пауза стоит вам копии.
Каждый вызов читает то, что сохранил предыдущий, и записывает только новое. Долгая пауза стоит вам копии.

Вызов 20 сообщает об этом в usage:

{
  "usage": {
    "input_tokens": 0,
    "cache_read_input_tokens": 33000,
    "cache_creation_input_tokens": 1500,
    "output_tokens": 300
  }
}

Весь вход — это сумма первых трёх полей. В API Anthropic input_tokens считает только то, что идёт после последней точки кэширования, поэтому дашборд, который смотрит лишь на это поле, покажет почти ноль.

Вызовов

Запись

Чтение

Выход

Итого

Без кэша

20

$0,09

$0,04

$0,06

$0,18

$0,87

50

$0,20

$0,21

$0,15

$0,55

$4,43

100

$0,39

$0,79

$0,30

$1,47

$16,35

Каждое число округлено до цента, поэтому строка может расходиться со своей суммой на цент.

Посмотрите на столбец «Чтение». Кэш снижает цену токена, а форму роста не трогает: чтение по-прежнему растёт с квадратом n. К 100 вызовам на него приходится больше половины счёта. На выход скидки нет вообще.

Что ломает совпадение

Сравнение идёт от начала промпта и не может пройти дальше первого различия. В API Anthropic для чтения нужна ещё и запись в кэше, которую более ранний запрос сделал в точке кэширования. Порядок такой: tools, потом system, потом messages, и изменение на одном уровне сбрасывает этот уровень и все следующие.

 system:
-  Current time: 2026-11-10T14:03:22Z. You are the Northwind support agent...
+  You are the Northwind support agent...
 messages:
   ...earlier steps...
+  Current time: 2026-11-10T14:03:22Z

Поэтому всё неизменное идёт первым, а всё меняющееся — последним.

В API Anthropic здесь нужен ещё один шаг. cache_control на верхнем уровне запроса ставит точку кэширования на последний блок, а при такой раскладке этот блок меняется при каждом вызове, и читать будет нечего. Поставьте cache_control на последний блок, который не меняется, как советует документация. Время тогда попадёт в input_tokens.

Что случилось

Что теряется в API Anthropic

Время или id запроса в начале промпта

Если точка кэширования одна и в конце, всё чтение при каждом вызове

Инструмент добавили, убрали или переписали

Весь кэш

Поправили фразу в системном промпте

System и messages

Поменяли tool_choice, добавили или убрали картинку

Messages

Пауза дольше 5 минут, например ожидание подтверждения от человека

Всё. Есть срок в 1 час, но запись тогда стоит вдвое дороже обычного входа

Промпт короче минимума модели, на Sonnet 5.5 это 512 токенов

Ошибки нет. Оба поля кэша в usage равны 0

В руководстве OpenAI про инструменты тот же совет: не менять определения, порядок и схемы.

Сломанный кэш хуже, чем никакого. Если время новое при каждом вызове, из кэша не читается ничего, а каждый токен оплачивается по цене записи.

Стоимость одного прогона на Sonnet 5.5. Префикс, который меняется при каждом вызове, обходится дороже, чем отказ от кэша.
Стоимость одного прогона на Sonnet 5.5. Префикс, который меняется при каждом вызове, обходится дороже, чем отказ от кэша.

У провайдеров по-разному

Проверено 2026-11-10:

Как включается

Запись

Чтение

Anthropic Messages API

Вы добавляете cache_control

1,25x на 5 минут, 2x на 1 час

0,1x; 0,05x на Opus 5.5 и Sonnet 5.5; 0,025x на Fable 5.1 и 5.2

OpenAI, GPT-5.6 и новее

По умолчанию

1,25x на 30 минут, 2,5x на 12 часов в Responses API

0,1x; 0,05x на GPT-6.1 Sol и Terra

У старых моделей OpenAI другие правила, а Gemini 2.5 и новее кэшируют неявно и по умолчанию. Прежде чем строить на этом оценку, посмотрите страницу цен своей модели.

Вывод

Глубже

Prompt caching (Anthropic)Справочник: точки кэширования, окно поиска на 20 блоков, сроки жизни и что сбрасывает каждый уровень.Prompt caching (OpenAI)Автоматические и явные точки кэша, сроки 30 минут и 12 часов, разобранное сравнение цены записи и чтения.Expensively Quadratic (exe.dev)Симулятор и замеры агента для кода одной компании: чтение из кэша начинает преобладать в длинных разговорах.Pricing (Anthropic)Текущие цены по моделям. Сверьтесь с ней, прежде чем брать любое число из этого блока.
‹ Назад
Предложить улучшениеНашёл ошибку