90% экономии на токенах: как ProjectAtlas оптимизирует расходы на кодовых агентах в проде
Я — Денис Шохирев, архитектор агентных AI-систем из Фрайбурга, веду DennisCraft AI Studio и вывожу в прод сложные multi-agent решения для B2B-клиентов DACH на стеке Claude, Supabase, n8n, Doppler и self-hosted Postgres. Счет за токены — реальный, а не теоретический вопрос: в одном из проектов Claude Code в проде за неделю сжигал бюджет, рассчитанный на месяц. Где сливаются токены: три основных источника перерасхода 1. Слишком частые вызовы LLM вместо кэширования В проде обнаружил: 67% запро
Я — Денис Шохирев, архитектор агентных AI-систем из Фрайбурга, веду DennisCraft AI Studio и вывожу в прод сложные multi-agent решения для B2B-клиентов DACH на стеке Claude, Supabase, n8n, Doppler и self-hosted Postgres. Счет за токены — реальный, а не теоретический вопрос: в одном из проектов Claude Code в проде за неделю сжигал бюджет, рассчитанный на месяц.
Где сливаются токены: три основных источника перерасхода
1. Слишком частые вызовы LLM вместо кэширования
В проде обнаружил: 67% запросов к Claude Code повторяют предыдущие сценарии, но выполняются с нуля — без кэширования. Причина — архитектура агентов, которые каждый раз спрашивают модель «с чистого листа». Решение — внедрение слоистого кэша (Supabase + Redis), где результат и промежуточные chain-of-thought шаги сохраняются по ключу задачи и контексту.
import hashlib
import json
from supabase import create_client
def get_cache_key(prompt, context):
return hashlib.sha256((prompt + json.dumps(context)).encode()).hexdigest()
def fetch_or_generate(prompt, context, supabase):
key = get_cache_key(prompt, context)
cache = supabase.table('llm_cache').select('*').eq('key', key).execute()
if cache.data:
return cache.data[0]['result']
# Вызов к Claude Code и запись результата
result = call_claude_code(prompt, context)
supabase.table('llm_cache').insert({'key': key, 'result': result}).execute()
return result
2. Агент разбивает задачи на «микрошаги» (over-decomposition)
В одной промышленной интеграции увидел: агент делит даже простые задачи на 15+ LLM-вызовов. Например, вместо единого end-to-end запроса на генерацию Data Access Layer — цепочка: «определи схему», «напиши функции», «проверь типы», «напиши тесты». В итоге — расход x10 по сравнению с батчевым подходом.
| Подход | Число LLM-вызовов (прод) | Средний расход токенов |
|---|---|---|
| Микрошаги (разделение) | 18 | 150 000 |
| Батчевый (end-to-end) | 2 | 15 000 |
Вывод — минимизировать количество вызовов через агрегацию шагов и batch inference. Помогает explicit prompt engineering: заранее описывать весь pipeline в одном промпте, а не разбивать.
3. Рефлексия и автокоррекция — воруют до 40% бюджета
LLM-агенты часто строятся по паттерну «сделай — проверь — исправь». В реальности, по моим метрикам на 3-х проектах, до 40% токенов уходят на автоматическую рефлексию и самокоррекцию кода. Бонус — это почти не улучшает итоговое качество по сравнению с тщательной pre-prompt валидацией и статическим анализом после генерации.
ProjectAtlas: что реально работает на проде
1. Агент-редуктор: агрегация шагов и batch prompts
Вместо цепочки микрошагов — батчевое задание с явным описанием всей задачи. Пример: генерация CRUD API + тестов + схемы в одном промпте, а не 4 разных. Это снижает число вызовов с 10-15 до 2-3 на задачу.
batch_prompt = (
"Сгенерируй Postgres-схему, CRUD-эндпоинты на FastAPI и unit-тесты для задачи:\n"
f"{task_description}\n"
"Формат ответа: JSON с ключами schema, endpoints, tests."
)
response = call_claude_code(batch_prompt, context)
result = json.loads(response)
2. Декомпозиция: только там, где есть value
Разделяю pipeline на этапы только при интеграции внешних проверок: например, после генерации кода — автозапуск bandit и semgrep, но не обратный вызов LLM для самокоррекции. Это дает прирост безопасности без лишних токенов.
3. Кэш и дедупликация на уровне задачи
Кэш не только на входной prompt, но и на промежуточные артефакты (например, схема БД). Если аналогичная задача запускалась ранее — агент сразу достает результат из Supabase-таблицы.
4. Ограничение «рефлексии» до 1 шага
Вместо бесконечных циклов исправлений — только одна попытка автокоррекции по явному trigger (например, если bandit находит уязвимость). Остальное — в log и на ручной разбор.
5. Технико-экономический мониторинг
В n8n построил трекер, который логирует каждый вызов LLM с расходом токенов, временем и контекстом задачи — это позволяет находить аномалии (например, задачи с x5 расходом) и оптимизировать pipeline.
Реальные результаты и открытая метрика
Мой публичный агент (live.gerdennisai.com) за 3 месяца показал среднее снижение расхода по сравнению с базовым workflow на 89,8%. Данные доступны в live-дашборде. Пример: типовая задача по генерации DAL+API — 14 500 токенов вместо прежних 120 000.
FAQ
Какой кэш использовать для быстрых LLM-запросов?
Supabase Postgres подходит для долгосрочного хранения, Redis — для быстрых lookup-операций. В проде использую оба.
Не ухудшается ли качество кода при агрегации шагов?
Нет, если промпт явно описывает все требования. Дополнительно — статический анализ через semgrep и bandit.
Как не потерять контроль при батчевой генерации?
Сохраняю промежуточные артефакты и логи в Supabase — можно быстро восстановить pipeline, если что-то пошло не так.
Что дает мониторинг расхода токенов?
Позволяет выявить неэффективные агенты и запросы, которые тратят x5/x10 от нормы — и быстро их оптимизировать.
Можно ли выстроить такой подход без n8n?
Да, core-логика реализуется и на Airflow или Prefect, но n8n проще для интеграций и визуального контроля.
На каком этапе ваш агент сжигает больше всего токенов в проде — генерация, автокоррекция или тестирование? Напишите мне — интересно сравнить практики. Провожу бесплатный 30-мин аудит стека для фаундеров и CTO DACH, кто строит AI в регламентированных рынках. Пишите в LinkedIn или @ger_dennis_ai.
Превратить процесс в систему, которая работает
Продакшн-качество, а не демо.