Оптимизация затрат на агентов: практическое руководство по сокращению расходов на API
Оптимизация затрат на агентов: практическое руководство по сокращению расходов на API
Ваш агент отлично справляется с задачами. Он обрабатывает 200 запросов в день, пользователи довольны. Затем вы смотрите счёт за API: $3 400 в этом месяце. Разбирая цифры, вы понимаете, что агент в среднем делает 12 обращений к API на каждый запрос, причём каждое из них содержит системный промпт объёмом 4 000 токенов. Это 9,6 миллиона входных токенов в день только на системные промпты. При цене $3 за миллион токенов получается $864 в месяц только на повторяющийся контент.
Именно стоимость — главная причина, по которой продакшн-развёртывания агентов урезают или полностью закрывают. Оптимизация — это не преждевременная мера, это вопрос выживания. Хорошая новость: в большинстве развёртываний агентов можно сократить затраты на 50–80% с помощью простых изменений, не требующих полной перестройки системы.
В этом руководстве вы узнаете о семи стратегиях снижения затрат, упорядоченных по ROI (возврату инвестиций). Начните сверху и двигайтесь вниз, пока не достигнете целевого бюджета. Каждый раздел содержит конкретные цифры, чтобы вы могли оценить экономию ещё до написания кода.
1. Учёт токенов: знайте, куда уходят деньги
Невозможно оптимизировать то, что не измеряешь. Прежде чем что-либо менять, составьте полную картину того, куда уходит каждый доллар в рабочем процессе вашего агента.
Разбивка входных токенов
Каждый вызов API к Claude включает несколько категорий токенов на входе:
- Системный промпт — инструкции, персона, ограничения. Часто 1 000–5 000 токенов, повторяются при каждом вызове.
- Определения инструментов — JSON-схемы для каждого инструмента, доступного агенту. 10 инструментов могут легко занять 2 000–3 000 токенов.
- История разговора — все предыдущие сообщения в диалоге. Растёт с каждым шагом.
- Результаты инструментов — выходные данные предыдущих вызовов инструментов, добавляемые обратно в контекст. Могут быть огромными (полные веб-страницы, результаты из базы данных).
Разбивка выходных токенов
Выходные токены обходятся в 3–5 раз дороже входных, что делает их критически важной целью для оптимизации:
- Рассуждения агента — внутренняя цепочка мыслей (особенно при расширенном мышлении).
- Генерация вызовов инструментов — JSON для вызовов инструментов.
- Финальный ответ — ответ, который видит пользователь.
Расчёт стоимости одной задачи
Общая стоимость одной задачи агента:
Общая стоимость = Σ (input_tokens × input_price + output_tokens × output_price) для каждого вызова API в задачеПример разбивки стоимости
Вот реалистичная разбивка для задачи исследовательского агента из 10 шагов с использованием Claude Sonnet ($3/M входных, $15/M выходных):
| Шаг | Компонент | Входные токены | Выходные токены | Стоимость входа | Стоимость выхода | Итого |
|---|---|---|---|---|---|---|
| 1 | Первоначальное планирование | 4 200 | 800 | $0.0126 | $0.0120 | $0.025 |
| 2 | Вызов веб-поиска | 4 800 | 200 | $0.0144 | $0.0030 | $0.017 |
| 3 | Обработка результатов поиска | 8 500 | 600 | $0.0255 | $0.0090 | $0.035 |
| 4 | Детальное чтение (стр. 1) | 12 000 | 500 | $0.0360 | $0.0075 | $0.044 |
| 5 | Детальное чтение (стр. 2) | 15 200 | 500 | $0.0456 | $0.0075 | $0.053 |
| 6 | Дополнительный поиск | 16 800 | 200 | $0.0504 | $0.0030 | $0.053 |
| 7 | Обработка результатов | 20 100 | 600 | $0.0603 | $0.0090 | $0.069 |
| 8 | Синтез | 22 500 | 1 200 | $0.0675 | $0.0180 | $0.086 |
| 9 | Проверка | 24 000 | 400 | $0.0720 | $0.0060 | $0.078 |
| 10 | Финальный ответ | 25 500 | 1 500 | $0.0765 | $0.0225 | $0.099 |
| Итого | 153 600 | 6 500 | $0.461 | $0.098 | $0.558 |
Обратите внимание: входные токены доминируют в расходах, и они растут с каждым шагом по мере накопления истории разговора. Шаги 8–10 составляют 47% от общей стоимости, хотя занимают лишь 30% от всех шагов.
Код для отслеживания затрат
Реализуйте обёртку для отслеживания с первого дня:
import anthropicimport timefrom dataclasses import dataclass, fieldfrom typing import Optional
@dataclassclass CostRecord: step: int model: str input_tokens: int output_tokens: int cache_read_tokens: int = 0 cache_creation_tokens: int = 0 input_cost: float = 0.0 output_cost: float = 0.0 total_cost: float = 0.0 duration_ms: float = 0.0
# Pricing per million tokens (as of early 2026)MODEL_PRICING = { "claude-haiku": {"input": 0.25, "output": 1.25, "cache_read": 0.025, "cache_write": 0.30}, "claude-sonnet": {"input": 3.00, "output": 15.00, "cache_read": 0.30, "cache_write": 3.75}, "claude-opus": {"input": 15.00, "output": 75.00, "cache_read": 1.50, "cache_write": 18.75},}
@dataclassclass TaskCostTracker: task_id: str budget_limit: Optional[float] = None records: list = field(default_factory=list) total_cost: float = 0.0
def record_call(self, step: int, model: str, usage) -> CostRecord: pricing = MODEL_PRICING.get(model, MODEL_PRICING["claude-sonnet"])
input_cost = (usage.input_tokens / 1_000_000) * pricing["input"] output_cost = (usage.output_tokens / 1_000_000) * pricing["output"] cache_read_cost = (getattr(usage, 'cache_read_input_tokens', 0) / 1_000_000) * pricing["cache_read"] cache_write_cost = (getattr(usage, 'cache_creation_input_tokens', 0) / 1_000_000) * pricing["cache_write"]
total = input_cost + output_cost + cache_read_cost + cache_write_cost
record = CostRecord( step=step, model=model, input_tokens=usage.input_tokens, output_tokens=usage.output_tokens, cache_read_tokens=getattr(usage, 'cache_read_input_tokens', 0), cache_creation_tokens=getattr(usage, 'cache_creation_input_tokens', 0), input_cost=input_cost + cache_read_cost + cache_write_cost, output_cost=output_cost, total_cost=total, )
self.records.append(record) self.total_cost += total
print(f" Step {step} [{model}]: {usage.input_tokens} in / {usage.output_tokens} out = ${total:.4f} (cumulative: ${self.total_cost:.4f})")
if self.budget_limit and self.total_cost > self.budget_limit: raise BudgetExceededError( f"Task {self.task_id} exceeded budget: ${self.total_cost:.4f} > ${self.budget_limit:.4f}" )
return record
def summary(self) -> dict: return { "task_id": self.task_id, "total_steps": len(self.records), "total_input_tokens": sum(r.input_tokens for r in self.records), "total_output_tokens": sum(r.output_tokens for r in self.records), "total_cost": self.total_cost, "cost_by_model": self._cost_by_model(), }
def _cost_by_model(self) -> dict: by_model = {} for r in self.records: if r.model not in by_model: by_model[r.model] = {"calls": 0, "cost": 0.0} by_model[r.model]["calls"] += 1 by_model[r.model]["cost"] += r.total_cost return by_model
class BudgetExceededError(Exception): passНачните отслеживать уже сегодня, даже до начала оптимизации. Вам нужны базовые показатели, чтобы измерить прогресс.
2. Выбор модели под задачу
Это самый мощный рычаг снижения затрат из доступных вам. Не каждый шаг агента требует самой мощной модели.
Уровни моделей и цены
Используя семейство Claude в качестве ориентира:
| Модель | Входные (за 1M токенов) | Вы
Связанные статьи
- Стратегии кэширования для AI-агентов: снижение затрат без потери качества
- Модели с рассуждением в агентных рабочих процессах: когда расширенное мышление оправдано
- Мультиагентные паттерны: оркестраторы, воркеры и конвейеры
- Отладка и Наблюдаемость в Системах Автономных Агентов