Ідея за 30 секунд
Моніторинг витрат для AI-агентів показує не тільки загальну суму витрат, а й те, де саме вони зростають: у токенах LLM, зовнішніх API і повторних кроках агента.
Без цього легко пропустити момент, коли система ще "працює", але вже стає занадто дорогою для production.
Основна проблема
Один run може завершитися успішно, але коштувати в 2-3 рази дорожче, ніж зазвичай.
Два запити з однаковою фінальною відповіддю можуть мати різну собівартість: через додаткові reasoning-кроки, retries або зайві виклики tools. Без cost monitoring це зазвичай видно тільки після перевищення бюджету.
Далі розберемо, як читати ці сигнали і знаходити, що саме робить run дорогим.
У production це часто виглядає так:
- токени ростуть хвилями після релізу;
- один tool непомітно починає споживати більшу частину бюджету;
- retries збільшують витрати навіть без зростання трафіку;
- команда бачить проблему вже після вибуху бюджету.
Саме тому cost-layer варто моніторити окремо, а не лише через загальні run-метрики.
Як це працює
Моніторинг витрат будується навколо двох типів сигналів:
- usage signals (
prompt_tokens,completion_tokens,tool_calls,retries); - cost signals (
llm_cost_usd,tool_cost_usd,total_cost_per_run).
Ці метрики відповідають на питання «де і чому дорожчає система в часі». Логи й трейсинг потрібні, щоб пояснити конкретний дорогий run.
Витрати ростуть не тільки через обсяг трафіку, а й через поведінку агента. Usage ≠ cost. Агент може виконати ту саму задачу з тим самим результатом, але коштувати в рази дорожче через retries, довші reasoning-ланцюги або дорогі tools.
Типові production-метрики витрат
| Метрика | Що показує | Навіщо потрібна |
|---|---|---|
| token_usage_per_run | скільки токенів витрачає один run | базовий контроль LLM-споживання |
| llm_cost_per_run | вартість LLM на один run | порівняння моделей і prompt-стратегій |
| tool_cost_per_run | вартість зовнішніх API/tools на run | пошук дорогих інструментів |
| total_cost_per_run | загальна вартість run | контроль собівартості відповіді |
| cost_p95 | «довгий хвіст» дорогих run | раннє виявлення дорогих аномалій |
| budget_burn_rate | швидкість витрачання бюджету | прогноз перевищення бюджету |
| cost_per_1k_runs | скільки коштують 1000 run | порівняння стабільності між релізами |
budget_burn_rate зазвичай рахується на рівні дашборду (витрати за одиницю часу), а не як окремий counter у runtime-коді.
Щоб метрики були практичними, їх зазвичай сегментують за release, model, tool і типом запиту.
Важливо: не додавай у labels висококардинальні поля (run_id, request_id, user_id), інакше сховище метрик швидко перевантажиться.
Як читати cost-layer
Що споживається → як агент поводиться → скільки це реально коштує. Це три рівні, які завжди потрібно дивитися разом.
Важливо дивитися на тренди у часі і різницю між релізами, а не на одиничні значення.
Далі дивимось на комбінації сигналів:
token_usage_per_run↑ +llm_cost_per_run↑ → агент витрачає більше токенів на один run;tool_cost_per_run↑ +total_cost_per_run↑ → over-tooling або дорогий tool-path;llm_cost_per_run↑ +tool_cost_per_run≈ стабільний → проблема в prompt або reasoning, не в tools;budget_burn_rate↑ +run_count≈ стабільний → регресія собівартості;cost_p95↑ +budget_burn_rate↑ → дорогі аномальні run починають прискорювати витрати.
Коли використовувати
Повний cost monitoring не завжди потрібен.
Для простого прототипу інколи достатньо базового token_usage і ліміту на денні витрати.
Але детальний моніторинг витрат стає критичним, коли:
- система вже в production і має бюджетні обмеження;
- агент використовує кілька tools із платними API;
- релізи виходять часто й важливо бачити регресії витрат;
- потрібно масштабувати трафік без втрати керованості бюджету.
Приклад реалізації
Нижче — спрощений приклад інструментації cost metrics у стилі Prometheus. Приклад показує базовий контроль вартості LLM, tools і загальної ціни run.
import time
from prometheus_client import Counter, Histogram
RUN_TOTAL = Counter(
"agent_run_total",
"Total number of agent runs",
["status", "stop_reason", "release"],
)
LLM_COST_USD_TOTAL = Counter(
"agent_llm_cost_usd_total",
"Total LLM cost in USD",
["model", "release"],
)
TOOL_COST_USD_TOTAL = Counter(
"agent_tool_cost_usd_total",
"Total tool/API cost in USD",
["tool", "release"],
)
TOKEN_USAGE_TOTAL = Counter(
"agent_token_usage_total",
"Total LLM tokens",
["model", "token_type", "release"],
)
RUN_COST_USD = Histogram(
"agent_run_cost_usd",
"Cost per run in USD",
["release"],
buckets=(0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1, 3),
)
BUDGET_BREACH_TOTAL = Counter(
"agent_budget_breach_total",
"Total runs that crossed cost budget",
["release"],
)
LLM_PRICING = {
# WARNING: приклад тарифу (може бути неактуальним).
# У production ці значення потрібно брати з конфігурації або API провайдера.
"gpt-4.1": {
"prompt": 0.0000015,
"completion": 0.0000020,
}
}
def estimate_llm_cost_usd(model, prompt_tokens, completion_tokens):
# WARNING: replace with actual provider pricing
pricing = LLM_PRICING.get(model)
if not pricing:
# WARNING: unknown model — cost will be reported as 0 (underestimated)
return 0.0
prompt_cost = prompt_tokens * pricing.get("prompt", 0)
completion_cost = completion_tokens * pricing.get("completion", 0)
return prompt_cost + completion_cost
def run_agent(agent, task, budget_limit_usd=0.25, release="2026-03-21"):
run_status = "ok"
stop_reason = "max_steps"
run_cost_usd = 0.0
try:
for step in agent.iter(task):
step_type = step.type
try:
result = step.execute()
except Exception as error:
run_status = "error"
if step_type == "tool_call":
stop_reason = "tool_error"
elif step_type == "llm_generate":
stop_reason = "llm_error"
else:
stop_reason = "step_error"
raise
if step_type == "llm_generate":
model = getattr(step, "model", "unknown")
usage = getattr(result, "token_usage", {}) or {}
prompt_tokens = usage.get("prompt_tokens", 0)
completion_tokens = usage.get("completion_tokens", 0)
TOKEN_USAGE_TOTAL.labels(model=model, token_type="prompt", release=release).inc(
prompt_tokens
)
TOKEN_USAGE_TOTAL.labels(
model=model, token_type="completion", release=release
).inc(completion_tokens)
llm_cost = estimate_llm_cost_usd(model, prompt_tokens, completion_tokens)
run_cost_usd += llm_cost
LLM_COST_USD_TOTAL.labels(model=model, release=release).inc(llm_cost)
if step_type == "tool_call":
tool_name = getattr(step, "tool_name", "unknown")
tool_cost = float(getattr(result, "cost_usd", 0.0) or 0.0)
run_cost_usd += tool_cost
TOOL_COST_USD_TOTAL.labels(tool=tool_name, release=release).inc(tool_cost)
if result and result.is_final:
stop_reason = "completed"
break
finally:
RUN_COST_USD.labels(release=release).observe(run_cost_usd)
if run_cost_usd > budget_limit_usd:
BUDGET_BREACH_TOTAL.labels(release=release).inc()
RUN_TOTAL.labels(status=run_status, stop_reason=stop_reason, release=release).inc()
# cost_per_1k_runs зазвичай рахується на рівні дашборду:
# (sum(agent_run_cost_usd) / run_count) * 1000
# budget_burn_rate зазвичай рахується на рівні дашборду:
# витрати за одиницю часу (наприклад USD/hour), а не окремим counter у коді.
Ось як ці метрики виглядають разом у реальному дашборді:
| Segment | cost_per_run | cost_p95 | burn_rate (hour) | Статус |
|---|---|---|---|---|
| gpt-4.1 + tools | $0.084 | $0.29 | $42/h | critical: budget risk |
| mini-model + cache | $0.021 | $0.07 | $11/h | ok |
| research workflow | $0.136 | $0.41 | $58/h | warning: p95 росте |
Investigation
Коли спрацьовує алерт по витратах:
- знайти сегмент із аномалією (
model,tool,release); - подивитись дорогі runs у трейсингу;
- перевірити в логах retries, stop_reason і tool-path;
- знайти root cause (prompt, логіка агента, дорогий API, помилковий routing).
Типові помилки
Навіть коли cost metrics уже додані, вони часто не дають користі через типові помилки нижче.
Є тільки загальна сума витрат за день
Денна сума не показує, який саме run або сегмент став дорожчим.
Без cost_per_run і cost_p95 проблему зазвичай помічають запізно.
Рахуються тільки токени, але ігнорується вартість tools
У багатьох агентних системах дорогими є саме зовнішні API-виклики.
Без tool_cost_per_run легко пропустити ранню фазу вибуху бюджету.
Немає розбиття за release і model
Без сегментації складно довести, що саме новий реліз або нова модель погіршили собівартість.
Висококардинальні labels
Додавання run_id, request_id або session_id у labels швидко перевантажує бекенд метрик.
Краще тримати ці дані в логах і трейсингу.
Немає алертів на burn rate і cost_p95
Без алертів проблеми накопичуються непомітно, поки не вдарять по бюджету. Це часто йде разом із надмірним використанням токенів.
Самоперевірка
Нижче — короткий checklist базового cost monitoring перед релізом.
Прогрес: 0/9
⚠ Бракує базової observability
Систему буде складно дебажити в production. Почніть з run_id, structured logs і tracing tool calls.
FAQ
Q: Чим моніторинг витрат відрізняється від моніторингу токенів?
A: Токени — це лише частина витрат. Cost monitoring включає і токени LLM, і платні tool/API-виклики, і загальну собівартість run.
Q: Який мінімум метрик витрат потрібен на старті?
A: Почни з token_usage_per_run, total_cost_per_run, cost_p95 і budget_burn_rate.
Q: Як рахувати cost_per_run, якщо в системі кілька провайдерів?
A: Нормалізуй усі кроки в єдину валюту (зазвичай USD) і сумуй витрати LLM + tools у межах одного run.
Q: Як відрізнити ріст трафіку від регресії собівартості?
A: Дивись одночасно на run_count і cost_per_run. Якщо трафік стабільний, а cost_per_run росте — це регресія собівартості.
Пов'язані сторінки
Далі за темою:
- Метрики агентів — загальна модель метрик для агентних систем.
- Метрики використання інструментів — контроль витрат і надійності на рівні tools.
- Трейсинг агента — як знайти дорогі кроки в межах одного run.
- Логування агентів — події для розбору витратних інцидентів.
- Моніторинг затримки агентів — зв’язок між latency і вартістю.