Как ограничить расходы AI-агента на VPS
Узнайте, как контролировать бюджет автономного AI-агента. В статье разобраны методы установки жестких лимитов, использование prompt caching, пакетная обработка и мониторинг токенов.
Как предотвратить чрезмерные расходы при работе постоянно запущенного AI-агента
Контроль расходов на AI-агента на VPS (виртуальном выделенном сервере) сводится к установке лимитов до запуска агента, так как никто не следит за счетчиком в процессе его работы. Ограничивайте каждый ответ параметром max_tokens, задавайте границы итераций цикла в собственном коде, кэшируйте неизменяемые части промпта и записывайте в лог показатели использования для каждого запроса, чтобы понимать, какая задача расходует средства. Аренда сервера — это фиксированная ежемесячная плата. API модели тарифицируется за токен, и автоматизированный цикл очень эффективно расходует токены в фоновом режиме.
Данное руководство предполагает, что агент уже существует и вызывает Messages API с вашего сервера. В статье Создание AI-агента с Claude на VPS описана техническая реализация.
Почему автономный агент имеет другую структуру затрат
Интерактивная сессия подразумевает участие человека. Если модель выбирает неверный путь или начинает читать лог на 40 000 строк, наблюдатель останавливает её. У автономного агента такого тормоза нет: он работает до завершения цикла, после чего таймер запускает его снова.
Частота — это множитель, который многие упускают из виду. Задача, выполняемая каждые пять минут, запускается 288 раз в день и около 8 640 раз в месяц. Стоимость одного запуска — это число, на которое нужно умножить итоговые затраты. Многим «постоянно работающим» агентам не нужно быть активными всё время. Им достаточно отвечать в течение нескольких минут, что подразумевает работу по расписанию.
Агент также оплачивает ресурсы, которые не требуются для обычного окна чата.
- Определения инструментов передаются с каждым запросом. Системный промпт для использования инструментов занимает 290 токенов в Claude Opus 4.8 с
tool_choiceизautoилиnone, и 410 сanyилиtool. Инструмент bash добавляет ещё 325 токенов. Каждый подключенный MCP server увеличивает этот объем за счет своих схем, так как MCP — это model context protocol. - Результаты работы инструментов — это входные токены. Команда, выводящая 8 000 строк, добавляет 8 000 строк в следующий запрос и во все последующие запросы в рамках этого цикла.
- Загруженные страницы — это входные токены. Веб-страница среднего размера в 10 кБ — это примерно 2 500 токенов, а исследовательский PDF на 500 кБ — около 125 000.
max_content_tokensобрезает только текстовые данные, так как это «применимо к текстовому контенту, а не к бинарному, например, к PDF». Ограничивайте PDF с помощьюmax_usesиallowed_domains. - Веб-поиск оплачивается за каждый запрос, по цене $10 за 1 000 поисковых запросов, независимо от количества полученных результатов. Поиск, завершившийся ошибкой, не тарифицируется.
Ничто из этого не является дорогим при однократном выполнении. Всё это становится дорогим при 8 640 запусках.
Жёсткие и мягкие ограничения решают разные задачи
max_tokens применяется принудительно. Это жёсткое ограничение общего объёма одного запроса: рассуждения и текста ответа вместе. Claude не генерирует текст сверх этого ограничения, а модель не видит его значение. При достижении лимита возвращается stop_reason: "max_tokens" и усечённый ответ. Для агентов есть важный нюанс: каждый запрос в цикле использования инструментов имеет собственное значение max_tokens, поэтому оно ограничивает один ответ, а не всю задачу. Десять вызовов инструментов по 4,000 дают для одного хода общий предел 40,000 токенов.
Бюджет задачи имеет рекомендательный характер. task_budget входит в output_config и сообщает модели, сколько токенов доступно для всего агентского цикла с учётом рассуждений, вызовов инструментов, результатов их работы и вывода.
resp = client.beta.messages.create(
model="claude-opus-4-8",
max_tokens=4096,
betas=["task-budgets-2026-03-13"],
output_config={"task_budget": {"type": "tokens", "total": 64000}},
messages=messages,
)«Бюджет задачи — это мягкая рекомендация, а не жёсткое ограничение». Claude может превысить его в середине действия, а принудительное ограничение вывода по-прежнему задаётся значением max_tokens. «Обратный отсчёт видит только модель», а ответы не содержат поля с оставшимся бюджетом. Минимальное допустимое значение task_budget.total — 20,000 токенов; меньшее значение приводит к ошибке 400. Если бюджета недостаточно для работы, модель может вести себя так, будто отказывается выполнять задачу: сузить её область или завершить работу раньше.
Одна настройка может увеличить расходы вместо их сокращения. Если клиент уменьшает task_budget.remaining при каждом последующем запросе, изменённое значение делает недействительным кэшированный префикс, который его содержит. Задайте это значение один раз, в первом запросе.
Бюджеты задач доступны в бета-режиме для Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, Claude Sonnet 5.5 и Claude Haiku 5.5. Claude Sonnet 5 и Claude Haiku 4.5 имеют статус Not supported, а бюджеты задач не применяются к Claude Code. Поэтому сессия Claude Code, отсоединённая в tmux, зависит от соблюдения правил работы с сессиями.
Третье ограничение находится в Claude Console: выделите агенту отдельное рабочее пространство, затем задайте для него месячный лимит расходов и ограничения частоты запросов в минуту. «Для Default Workspace нельзя задать ограничения», а «ограничения на уровне организации применяются всегда, даже если сумма ограничений рабочих пространств выше». Добавьте уведомления о расходах, чтобы получать предупреждение при достижении порога до срабатывания лимита.
Выбор модели для каждой задачи и фактический эффект уровня усилий
Выбор модели определяется отдельно для каждой задачи. По состоянию на October 2026 стоимость за 1 миллион токенов, сначала входных, затем выходных: Claude Fable 5.1 и Fable 5 — $10 и $50, Claude Opus 5.5 — $4 и $20, Claude Opus 5, Opus 4.8 и Opus 4.7 — $5 и $25, Claude Sonnet 5.5 и Sonnet 5 — $2 и $10, Claude Haiku 5.5 — $0.10 и $0.50 для запросов объёмом до 100,000 токенов ($0.50 и $2.50 выше этого объёма; кэшированные токены также учитываются), а Claude Haiku 4.5 — $1 и $5. Сначала Anthropic продавала Sonnet 5 по этой цене как вводный тариф, затем сделала её стандартной и отменила запланированное повышение до $3 и $15. Шаг, который только классифицирует строки журнала, не требует Opus.
Не рассчитывайте и на бесплатное использование как на способ покрыть большую нагрузку. Помимо небольшого кредита, который Claude API предоставляет при регистрации, единственная регулярная квота — ежемесячный кредит API, включённый в планы Claude Max и Team: $100 для Max 5x, $200 для Max 20x и до $500 общего кредита для Team. Кредит обновляется в каждом расчётном периоде. Получить его можно через 7 дней после подключения подходящего плана; способ оплаты не требуется. Кредит распространяется на Claude API, Managed Agents, Agent SDK и playground, но не на Claude Code. В конце каждого расчётного периода он сгорает и не переносится. Использование кредита учитывается в лимите расходов. После его исчерпания запросы прекращаются, если у организации нет также приобретённых кредитов.
Уровень усилий — второй рычаг управления расходами. output_config.effort принимает значения low, medium, high и xhigh и max, однако не каждая модель поддерживает каждый уровень. Для большинства моделей значение по умолчанию — high, а для Claude Opus 5.5 и Claude Haiku 5.5 — medium. Явная установка значения по умолчанию для модели эквивалентна его отсутствию. Меньший уровень усилий сокращает не только длину рассуждений. В документации указано, что Claude выполняет меньше вызовов инструментов и объединяет несколько операций в меньшее число вызовов. Для агента это даёт большую экономию, поскольку отменённый вызов инструмента означает, что целый запрос не выполняется.
Проблема в том, что уровень усилий влияет на кэш. Изменение значения верхнего уровня между запросами делает кэширование промпта недействительным. В задокументированном примере для Claude Opus 5.5 запрос 2 сообщил значение cache_read_input_tokens: 3546. В запросе 3 уровень усилий изменили с medium, значения по умолчанию для этой модели, на low. В результате запрос сообщил cache_creation_input_tokens из 3546 и cache_read_input_tokens из 0. Поэтому изменяйте уровень усилий верхнего уровня между рабочими нагрузками, но не внутри одного кэшированного диалога. Есть два способа изменить глубину без нарушения кэша. В Claude Fable 5.1, Opus 5.5, Opus 5, Sonnet 5.5 и Haiku 5.5 изменение уровня усилий для отдельного сообщения (beta, заголовок mid-conversation-output-config-2026-07-01) устанавливает новый уровень, сохраняя кэшированный префикс. В любой модели вместо этого можно задать направление в промпте. Например, строка "Answer directly without deliberating." в последнем сообщении пользователя сохраняет предыдущие точки разбиения. Однако в Claude Haiku 5.5 эта фраза не обеспечивает надёжного сокращения рассуждений.
Токены рассуждений оплачиваются по тарифам для выходных токенов и учитываются в max_tokens. Поэтому усечённый ответ часто означает, что бюджет был израсходован на рассуждения. Число токенов указано в usage.output_tokens_details.thinking_tokens. В статье Из чего фактически складывается счёт Claude за токены подробно разобрана структура этих расходов.
Кэшируйте стабильный префикс и не ломайте его случайно
Запись в кэш стоит 1.25 базовой стоимости входных данных для кэша на пять минут и 2 базовых стоимости для кэша на один час. Для большинства моделей чтение из кэша стоит 0.1 базовой стоимости, поэтому «кэширование окупается после одного чтения из кэша при длительности 5 минут (запись стоит 1.25x) или после двух чтений из кэша при длительности 1 час (запись стоит 2x)». На новейших моделях чтение стоит ещё дешевле: 0.05 базовой стоимости для Claude Opus 5.5 и Claude Sonnet 5.5 и 0.025 для Claude Fable 5.1.
Одна строка объясняет, почему это подходит для постоянно работающего агента: «Кэш обновляется без дополнительной платы при каждом использовании кэшированного содержимого». Задание, которое запускается каждые две минуты и обращается к кэшу на пять минут, поддерживает его префикс в актуальном состоянии весь день за одну запись.
Есть три способа незаметно потерять кэш.
Изменяющийся префикс. «Префиксы кэша создаются в следующем порядке: tools, system, затем messages». Любое изменение байта на более раннем уровне этого порядка делает недействительными все последующие элементы, а изменение определений инструментов инвалидирует весь кэш. Классическая ошибка — временная метка или идентификатор запуска в системном промпте: каждый запрос после этого содержит другой префикс, записывает новую запись по цене 1.25x и ничего не читает из кэша. Признак — usage.cache_read_input_tokens равен 0 в вызовах, которые выглядят одинаково. Перенесите изменяющийся текст в самое новое сообщение пользователя.
Слишком короткий префикс. Для каждой модели задана минимальная длина, при которой содержимое можно кэшировать. Если запрос короче, он обрабатывается без кэширования, и «ошибка не возвращается». Для Claude Fable 5.1, Fable 5, Opus 5.5, Opus 5, Sonnet 5.5 и Haiku 5.5 это 512 токенов; для Claude Opus 4.8 и Claude Sonnet 5 — 1,024; для Claude Haiku 4.5 — 4,096. Поэтому перенос задания с Sonnet 5 на Haiku 4.5 может незаметно отключить кэширование.
Диалог, который выходит за пределы окна просмотра назад. «Окно просмотра назад содержит 20 блоков». Система проверяет не более 20 позиций для каждой точки останова, а затем прекращает поиск. В документированном примере ход содержит 35 блоков, а точка останова установлена на блоке 35. Система проверяет блоки с 35 по 16, но запись предыдущего хода на блоке 15 оказывается за пределами окна, поэтому совпадения нет. Агент, который добавляет за один ход несколько блоков использования инструментов и результатов их работы, пересекает границу в 20 блоков за два или три хода. В каждом запросе доступно четыре точки останова, поэтому одну из них следует использовать для последних сообщений.
Отправляйте задачи, не требующие немедленного ответа, через Batches API
«Все операции тарифицируются с 50% скидкой от стандартных цен API» как для входящих, так и для исходящих данных. Пакетная обработка выполняется асинхронно, «большинство пакетов завершаются менее чем за 1 час», а результаты становятся доступны после завершения всех запросов или по истечении 24 часов, в зависимости от того, что наступит раньше. Это типичный, но не гарантированный срок.
Опрашивайте processing_status, пока статус не примет значение ended. Запросы, возвращающие errored, canceled или expired, не тарифицируются. Важное замечание для тех, кто использует лимиты расходов: «пакеты могут незначительно превышать установленный для вашего Workspace лимит затрат».
Скидки суммируются, и поскольку обработка пакета может занимать более пяти минут, документация рекомендует использовать часовое кэширование для пакетов с общим контекстом. Разделяйте нагрузку: всё, чего ожидает пользователь или вебхук, должно оставаться в основном потоке, а ночные сводки или классификация логов за вчерашний день могут быть отправлены в пакетную обработку за полцены.
Записывайте поля usage каждого ответа в собственное хранилище
Нельзя отнести к проекту расходы, которые вы не записали. Каждый ответ содержит данные о своей стоимости.
u = resp.usage
row = {
"job": job_name,
"model": resp.model,
"uncached_input": u.input_tokens,
"cache_write": u.cache_creation_input_tokens,
"cache_read": u.cache_read_input_tokens,
"output": u.output_tokens,
"stop_reason": resp.stop_reason,
}Добавляйте по одной строке на каждый вызов API в файл JSON Lines и указывайте имя задания. Через неделю вы сможете определить, какое задание расходует средства, а какое только создаёт видимость активности. Следите за cache_read: столбец, состоящий из нулей, — самая частая ошибка учёта расходов в self-hosted agent.
Одно поле легко неправильно интерпретировать. input_tokens учитывает только токены после последней точки кэширования, поэтому фактический размер prompt равен total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens. Если agent сообщает input_tokens: 400 для большого prompt, это не означает низкую стоимость: остальные токены были получены из кэша.
Считайте токены до отправки запроса. Подсчёт токенов бесплатен, а его ограничения частоты запросов не зависят от создания сообщений, поэтому используйте count_tokens, чтобы отклонить слишком большое вложение, а не платить за обнаружение его размера. Результат является оценкой, поэтому выполняйте повторный подсчёт для каждой модели и не используйте результат, полученный с tokenizer другого поставщика. Модели Claude 4.7 и более поздние, включая Claude Fable 5 и Claude Sonnet 5, используют новый tokenizer, который «создаёт примерно на 30% больше токенов для того же текста». Claude Sonnet 4.6 и более ранние модели, включая Claude Haiku 4.5, используют предыдущий tokenizer.
Для получения официальных данных Admin API предоставляет сведения об использовании по адресу https://api.anthropic.com/v1/organizations/usage_report/messages и данные о стоимости по адресу https://api.anthropic.com/v1/organizations/cost_report. Для обоих запросов требуется admin key (sk-ant-admin01-...), передаваемый как x-api-key: $ANTHROPIC_ADMIN_KEY, с помощью anthropic-version: 2023-06-01. Отчёт об использовании принимает bucket_width=1d, group_by[]=model и api_key_ids[]=. Отчёт о стоимости формируется только за день и группирует данные по workspace_id или description. Ограничение: «Admin API недоступен для индивидуальных аккаунтов».
Параметр api_key_ids[] позволяет недорого распределять расходы: назначьте каждому заданию отдельный API key, отфильтруйте отчёт об использовании с помощью api_key_ids[] и разделите данные по ключам с помощью group_by[]=api_key_id. Фильтр использует множественное число, а измерение группировки — единственное. Храните ключи в переменных окружения, а не в коде, как это сделано в первом приложении Claude API на VPS.
Ограничьте цикл, потому что больше это никто не сделает
Здесь ограничение числа итераций обязательно. Цикл принадлежит вам, поэтому и счётчик должны добавить вы:
for step in range(MAX_STEPS): # MAX_STEPS = 12, never "while True"
resp = client.messages.create(...)
if resp.stop_reason != "tool_use":
break
else:
log.warning("job %s hit MAX_STEPS=%d, giving up", job_name, MAX_STEPS)Ни один из указанных выше пределов не решает эту задачу: max_tokens ограничивает один ответ, а модель лишь получает рекомендацию о бюджете задачи. Размещённый сервис остановил бы выполнение на этом этапе, как ограничение Claude на вызовы инструментов в рамках одного хода завершает сеанс после слишком большого числа вызовов. Но в самостоятельно написанном цикле такой защиты нет, пока вы её не добавите.
Добавьте второй механизм остановки за пределами процесса. Запускайте задание через таймер systemd, а не как постоянно работающий процесс, и задайте для его service unit ограничение по реальному времени. Для задания таймера обычно используется Type=oneshot, а RuntimeMaxSec= «не оказывает никакого влияния на службы Type=oneshot», поэтому укажите там TimeoutStartSec=600. Используйте RuntimeMaxSec=600 только для юнита Type=simple. В обоих случаях зависшее выполнение будет остановлено через десять минут, а не продолжит работать, пока вы его не обнаружите. В материале Запуск программы как службы и таймера systemd описаны сами файлы юнитов. Узнать, что сделал конкретный запуск, можно с помощью journalctl -u triage-agent.service --since "1 hour ago".
Ограничьте также число повторных попыток, потому что обработчик, который повторяет запросы бесконечно, учитывает в счёте каждую попытку. Для ошибки 429 или 500 можно выполнить несколько попыток с увеличением интервала между ними. Для ошибки 400 повторные попытки не нужны: тот же запрос завершится с той же ошибкой.
Контроль затрат AI-агента начинается с анализа собственных показателей
Нельзя заранее назвать стоимость постоянно работающего агента, поскольку она равна количеству токенов за один запуск, умноженному на число запусков в день. Оба значения зависят от вас. Запустите агент один раз, прочитайте записанную строку с данными об использовании и умножьте её на расписание запусков. Через два дня сравните отчёт о затратах с этим расчётом. Если значения не совпадают, причина почти всегда заключается в неработающем кэше или в цикле, который выполнялся дольше, чем вы предполагали.
Здесь предполагается использование API key, поскольку агент является вашей собственной программой, вызывающей Messages API. Для интерактивной работы какой план Claude соответствует вашему сценарию работы описывает варианты подписки. Все указанные здесь цены и ограничения проверены по документации Anthropic в October 2026. Перед составлением бюджета ещё раз проверьте страницу с ценами.
FAQ
Сколько стоит постоянно работающий AI-агент на VPS?
Есть два вида расходов, но предсказуем только один. Сервер имеет фиксированную ежемесячную стоимость. API модели оплачивается по числу токенов, поэтому стоимость равна расходу одного запуска, умноженному на частоту запусков. Anthropic не публикует данных о стоимости постоянно работающего агента на собственном сервере, поэтому любое указанное число следует считать оценкой. Запишите usage одного реального запуска и умножьте это значение на расписание.
В чём разница между max_tokens и бюджетом задачи?
max_tokens принудительно ограничивается и не виден модели. Он ограничивает вывод одного запроса, включая рассуждения, а при достижении лимита возвращается stop_reason: "max_tokens". Бюджет задачи работает иначе: модели сообщается это число, и она подстраивает агентский цикл под него, но «бюджеты задач — это мягкая рекомендация, а не жёсткий лимит», а фактическим ограничением по-прежнему остаётся max_tokens.
Почему значение cache_read_input_tokens всегда равно нулю для моего агента?
Потому что префикс меняется между запросами или слишком короток для кэширования. Обычно причина заключается в метке времени или идентификаторе запуска, подставленном в системный prompt: кэш индексируется по префиксу, поэтому любое изменение байта делает всё последующее содержимое недействительным для кэша. Изменение определений инструментов или значения верхнего уровня effort приводит к тому же результату. В противном случае причина связана с размером: более короткие prompt не кэшируются, и ошибка при этом не возвращается.
Как остановить AI-агента, если он зациклился?
Считайте итерации в коде цикла и останавливайте его после фиксированного максимального числа, поскольку max_tokens ограничивает один ответ, а агент выполняет много ответов. Добавьте ограничение по реальному времени за пределами процесса: запускайте задачу через systemd timer и задавайте TimeoutStartSec= для oneshot unit либо RuntimeMaxSec= для simple unit, чтобы зависший запуск был принудительно остановлен по расписанию. Ограничьте также число повторных попыток, поскольку каждая попытка в цикле повторной отправки оплачивается отдельно.
Можно ли установить лимит расходов для одного ключа Claude API?
Документированный лимит расходов действует на уровне workspace, а не отдельного ключа, поэтому выделите для агента отдельный workspace и установите там месячный лимит расходов. «Нельзя устанавливать лимиты для Default Workspace». Добавьте уведомления о расходах, чтобы сначала получать оповещение при достижении заданного порога. Для раздельного учёта выдайте каждому заданию собственный ключ, а затем сгруппируйте отчёт об использовании с помощью group_by[]=api_key_id.