Работа агентов AWS AI в масштабе: токены, расходы, лимиты и автономность
Подсчёт токенов, мониторинг расходов, восстановление после превышения лимита контекста и надёжные автономные рабочие процессы для агентов AWS, каждый из которых объясняется с помощью паттернов, знакомых разработчикам full-stack JavaScript.
Агент, чьи параметры разработаны разумно и который подкреплен механизмами проверки и извлечения данных, всё равно должен выдержать первый месяц работы в производственной среде. Определяющими факторами здесь являются в основном не самые привлекательные аспекты: способ подсчёта токенов, мониторинг расходов ресурсов, что происходит, когда заполняется окно контекста, и то, построен ли длительный автономный цикл как настоящий движок рабочих процессов. Если вы работали с полноценным JavaScript на AWS, каждый из этих аспектов легко соотносится с чем-то, что вам уже знакомо, и в данном обзоре постоянно используются эти аналогии.
Токенизация — это слой сериализации
Веб-приложения сериализуют данные перед их передачей по сети с помощью JSON.stringify или protobuf. Языковая модель выполняет аналогичную функцию с текстом: прежде чем она начнёт обрабатывать информацию, текст разбивается на токены — фрагменты между словами, а не отдельные символы или целые слова.
"Enterprise agents scale."
→ ["Enterprise", " agents", " scale", "."] (≈4 tokens, illustrative)
Причины, по которым инженеру важно обращать на это внимание, сводятся к трём моментам.
- Токены — это единица измерения, по которой взимается плата; они сопоставимы с единицей GB-секунд в Lambda. И входные, и выходные данные стоят денег, и поскольку цены в Bedrock различаются в зависимости от модели, количество токенов напрямую влияет на счёт от AWS.
- Токены также определяют максимальный размер данных, передаваемых в запросе, подобно лимиту для тела запроса, как в примере
express.json({ limit: '5mb' }). В данном случае таким лимитом является окно контекста, которое у современных моделей может достигать сотен тысяч токенов и продолжает расти; поэтому уточните реальный лимит для вашей модели, а не делайте предположения. - Процесс токенизации неодинаков для разных языков. Для текста на языках, отличных от английского, часто требуется больше токенов на одно слово, что имеет значение для продуктов, работающих в нескольких регионах.
В Node.js подсчёт количества токенов перед отправкой запроса похож на измерение размера данных перед вызовом функции fetch:
// Node.js: counting tokens before sending a request
// (conceptually like calculating payload size before a fetch call)
import { encoding_for_model } from "tiktoken";
const enc = encoding_for_model("gpt-4o");
const tokens = enc.encode(userPrompt);
console.log(`Payload size: ${tokens.length} tokens`); // like Content-Length
enc.free();
В Bedrock можно обойтись без стороннего токенизатора. API CountTokens подсчитывает количество токенов с серверной стороны для поддерживаемых моделей Claude, использует ту же структуру сообщений, что и API Converse, и позволяет заранее проверить количество токенов в запросе без необходимости оплачивать обработку:
# Python (boto3): pre-flight token count via Bedrock, no separate tokenizer library needed
response = bedrock_runtime.count_tokens(
modelId="anthropic.claude-3-5-sonnet-20241022-v2:0",
input={"converse": {"messages": [{"role": "user", "content": [{"text": userPrompt}]}]}}
)
print(f"Input tokens: {response['inputTokens']}")
Урок: измеряйте количество токенов так же, как вы измеряете размер HTTP-полезной нагрузки, до отправки запроса, а не после того, как вам выставлен счёт или запрос отклонён.
Контроль расхода токенов как CloudWatch для счётов за LLM
В предыдущем разделе рассматривался один запрос. В общем виде показывается, сколько токенов потратил каждый агент за день для каждого арендатора, и вам нужно узнать это раньше, чем сделают финансовый отдел. Никто бы не запустил Express API на AWS без панелей управления и сигнализации, и мониторинг токенов заслуживает такого же подхода.
Ключевые показатели для агента:
- Количество токенов на запрос, аналогично размеру входящей полезной нагрузки.
- Количество токенов на завершение запроса, аналогично размеру ответа.
- Общее количество токенов за сессию, что соответствует объёму памяти сессии.
- Стоимость за агента, пользователя или арендатора — тот же показатель, что и для использования базы данных в мультиарендаторских SaaS-решениях.
Конкретные шаги в AWS:
- Отправляйте пользовательские метрики CloudWatch для токенов ввода, токенов завершения и стоимости в долларах (
prompt_tokens,completion_tokens,cost_usd), с метками имени агента и тенанта. - Включите кэширование вводных данных. Bedrock может повторно использовать длинные, стабильные префиксы, такие как системные запросы, определения инструментов и примеры работы с небольшим количеством данных, что позволяет значительно снизить затраты и уменьшить задержку. Размещайте неизменяемый контент в первую очередь, иначе вы будете платить полную стоимость за одинаковые токены при каждом вызове.
- Создайте сигнализации CloudWatch, которые уведомляют через SNS при превышении ежедневных расходов установленного порога, точно как сигнализации биллинга AWS.
- Записывайте каждый вызов агента в S3 с помощью Kinesis Firehose или напрямую, чтобы сохранять историю операций. Это потребуется со стороны проверяющих SOC 2 и крупных клиентов.
- Для оценки достаточно простого расчёта, аналогичного тому, что используется для Lambda: добавьте токены начала и завершения обработки, умножьте на стоимость модели, затем добавьте расходы на получение данных и инфраструктуру за сессию.
Если вы не можете указать, сколько стоил агент X в прошлый вторник в разбивке по клиентам, это означает, что продукт готов только к демонстрации, а не к использованию в производстве, и между этими состояниями огромная разница.
Ошибки из-за ограничения объёма данных: защита от сбоев и пагинация
У каждого окна контекста есть предел. Длинные разговоры, обширные результаты работы инструментов и перегруженные фрагменты данных могут превысить этот лимит. Это аналог ошибки 413 Payload Too Large в мире агентов, только хуже, поскольку она может возникнуть на любом этапе многошаговой задачи.
Стратегии восстановления заимствованы непосредственно из инженерии бэкенда:
- Суммаризация и сжатие. Периодически компрессировать старые сообщения, как при ротации журналов логов.
- Использование скользящего окна или обрезка. Удалять самые старые сообщения, подобно тому как при просмотре большого набора результатов запроса не загружаются все из них сразу.
- Перенос данных на внешние системы. Хранить материалы вне запроса и загружать их по мере необходимости, следуя принципу отложенной загрузки.
- Разделение на подагентов. Разбивать одну огромную задачу на мелкие этапы с новым контекстом, как превращение монолитной задачи в очередь небольших операций.
Вот пример шаблона обработки ошибок и сжатия в коде, аналогичного тому, что используется для обработки превышения времени ожидания в базе данных:
# Conceptual: catching a context-limit error, like catching a DB timeout
try:
result = agent.run(task, conversation_history)
except AgentError as err:
if err.code == "context_length_exceeded":
# Keep the system prompt intact — compact the *conversation*, never the identity.
# Summarizing everything (including system instructions) is how agents quietly
# "forget" their role mid-task, the same way you'd never let a cache-eviction
# policy drop your app's config alongside its session data.
compacted = summarize(conversation_history, preserve="system_prompt")
result = agent.run(task, compacted)
else:
raise # don't swallow unrelated errors
Ошибки, связанные с ограничением объёма данных, являются обычным явлением и не считаются исключениями. Рассматривайте их как ограничения по частоте запросов и таймауты: используйте повторные попытки с задержками, храните контрольные точки в DynamoDB и обеспечивайте плавную работу системы при сбоях. Пустой блок catch, который просто поглощает ошибку, никогда не является приемлемым решением.
Автономные рабочие процессы как машины состояний
Автономный агент не действует один раз — он планирует, выполняет действия, наблюдает за ситуацией и повторяет этот цикл до достижения цели. Любой, кто создавал машину состояний XState, схему Redux saga или поток AWS Step Functions для многоэтапной процедуры оплаты, уже знаком с такой структурой. Это знакомый цикл в стиле ReAct, состоящий из планирования, действия, наблюдения и оценки, с возможностями завершения работы или передачи задачи человеку, и его следует проектировать как надёжный движок рабочих процессов.
- Идемпотентные шаги. Повторная обработка шага не должна дважды взимать плату с клиента или отправлять дублирующиеся электронные письма.
while(true), связанных с использованием кредитной карты.Чекпоинт — это просто ещё одна запись о задании, которое можно возобновить, в DynamoDB; Step Functions считывает её при перезапуске, чтобы продолжить выполнение с последнего успешного шага:
{
"pk": "session#8f2c1a",
"sk": "checkpoint#2026-08-23T10:15:00Z",
"step": "plan",
"hop_count": 2,
"cost_so_far_usd": 0.014,
"state": { "goal": "resolve billing dispute", "last_action": "lookup_charge" },
"ttl": 1788084900
}
Не создавайте систему автономии в виде цикла while, окружающего вызов LLM. Составьте надежную, отслеживаемую и способную к возобновлению машину состояний, ведь именно этим она на самом деле является. Если вам нужен готовый решение, Step Functions отлично подходит для этих целей.
Над всем этим существует еще один уровень: процедуры оценки. Правила безопасности, качество получаемой информации и ее соответствие реальности требуют тестов на регрессию так же, как и код приложения. Набор инструментов для оценки воспроизводит фиксированный набор входных данных для агента и оценивает результаты по сравнению с ожидаемым поведением, так что изменение промпта или замена модели не могут тайно ухудшить работу системы. Ragas оценивает показатели, связанные с получением информации, такие как точность и релевантность контекста, в то время как Promptfoo и Braintrust обеспечивают более широкую проверку промптов и результатов. Подключите выбранный инструмент в процесс CI так же, как вы это делаете с pytest, чтобы сбой в оценке блокировал развертывание, и никому не пришлось бы вручную проверять результаты.
Чек-лист готовности к производственному использованию
- У каждого агента есть одна проверяемая обязанность и узко определённые разрешения IAM.
- Передача данных осуществляется с использованием структурированного контекста через надёжный канал (SQS или EventBridge) и защищена от циклов.
- Механизмы контроля входных и выходных данных являются отдельными, комбинируемыми элементами и имеют собственные версии.
- Качество получаемых данных оценивается с помощью отдельных показателей точности и полноты, их не сводят к формулировке «ИИ ошибается».
- Все критически важные элементы проходят проверки на галлюцинации: проверка на основе реальных данных, оценка уровня уверенности или участие человека.
- Использование токенов измеряется до отправки запроса, а не только после его выполнения.
- Панели управления CloudWatch показывают расходы по каждому арендатору и каждому агенту, с алертами о достижении лимитов бюджета через SNS.
- Существует чёткий план восстановления при ошибках, связанных с ограничением объёма контекста: сжатие, обрезка или перенос данных.
Что это дает в итоге
Каждая концепция агента имеет свой аналог в мире полноценных фреймворков, с которым вы знакомы. Агенты — это микросервисы с способностью к принятию решений, а передача данных осуществляется с использованием надежных, отслеживаемых маршрутов с ограничением по количеству этапов. Механизмы контроля представляют собой слои промежуточного программирования, процесс извлечения информации осуществляется с помощью усовершенствованного слоя запросов, а галлюцинации выявляются путем связывания с реальностью и проверки, а не простым вежливым запросом. Токены одновременно служат мерой размера данных и единицей оплаты. Мониторинг расходов — это аналог CloudWatch для отслеживания использования моделей. Полное окно контекста представляет собой фактор, приводящий к предсказуемым сбоям, требующим плана восстановления, а автономия — это надежная машина состояний, совершенно не похожая на простой цикл while.
Энтерпрайз-агенты редко терпят неудачу в производственной среде из-за недостаточной умности модели. Они терпят неудачу потому, что команды игнорируют основные принципы работы распределенных систем, которые они никогда бы не проигнорировали при работе с обычным API: валидацию, возможность наблюдения за работой системы, повторные попытки выполнения операций, идемпотентность, а также механизмы плавного снижения нагрузки. Если вы уже развернули устойчивое JavaScript-приложение на AWS, у вас уже есть соответствующие навыки. Остается лишь направить эти навыки на неизвестную и непредсказуемую зависимость, которая отвечает в виде текстовых сообщений.