Робота агентів AI AWS у масштабі: токени, витрати, ліміти та автономія
Підрахунок токенів, моніторинг витрат, відновлення після перевищення лімітів контексту та стійкі автономні робочі процеси для агентів AWS, кожен з яких пояснюється за допомогою патернів, відомих розробникам full-stack JavaScript.
Агент, який розроблений з урахуванням всіх аспектів та підтримується механізмами верифікації та отримання даних, все одно мусить витримати перший місяць роботи в продакшені. Те, що визначає його успіх, здебільшого є не надто привабливим: спосіб підрахунку токенів, контроль витрат, те, що відбувається, коли заповнюється вікно контексту, та чи побудовано довготривалий автономний цикл як справжній двигун роботи з завданнями. Якщо ви маєте досвід роботи з повноцінним JavaScript на AWS, кожен із цих аспектів легко відповідає чомусь, що ви вже знаєте, і цей огляд постійно використовує саме ці паралелі.
Токенізація — це шар серіалізації
Веб-додаток серіалізує дані перед їх надсиланням за допомогою JSON.stringify або protobuf. Модель мови робить те саме з текстом: перш ніж вона щось побачить, текст розділяється на токени — це фрагменти під словами, а не символи чи цілі слова.
"Enterprise agents scale."
→ ["Enterprise", " agents", " scale", "."] (≈4 tokens, illustrative)
Причини, чому інженеру варто цим перейматися, зводяться до трьох аспектів.
- Токени — це те, за що вас беруть у рахунок; вони подібні до ГБ-секунд у 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 може повторно використовувати довгі, стабільні префікси, такі як системні запити, визначення інструментів та приклади типу „few-shot“, з значною економією та нижчою затримкою. Розміщуйте незмінний контент на початку, інакше ви будете платити повну ціну за ідентичні токени при кожному виклику.
- Створіть сповіщення 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, у вас вже є ці інстинкти. Залишається лише спрямувати їх на незнайому, непередбачувану залежність, яка відповідає реченнями.