Привет, дорогой читатель. Если тебя хоть раз тревожило то, почему так быстро улетают лимиты Claude Code или любого другого ИИ-тула для кодинга, ты пришел по адресу. Буквально пара правок, и хоба дневной лимит исчерпан, а баланс API показывает дно. Вся эта боль в статье про экономию токенов на инструментах сборки контекста.

Написано для комьюнити AI Enginees Guild https://t.me/ai_engineers_guild
Обычно мы не сильно задумываемся об оптимизации процесса: либо кодят с ИИ как есть (копипастя файлы вручную), либо пихают в контекст всю папку проекта целиком, либо на авось подрубают самые разные тулы в надежде, что «и так сойдет». А под капот умным агентам разработчики пихают всё подряд: вот тебе ripgrep, вот AST-парсер, вот чтение файлов целиком, развлекайся. Но я задался вопросом: какой конкретно поисковый тул реально помогает агенту решать задачи и экономить токены, а какой — только заставляет его блуждать по репозиторию и беспощадно жрать контекст?
Чтобы это выяснить, я собрал подобие бенчмарка (исходники выложил в letya999/tools-token-economy) и прогнал 21 конфигурацию тулов на реальных задачах разной сложности. Думал, что навороченный семантический поиск раскатает дедовский grep в сухую, но результаты оказались куда интереснее. А по пути я еще и словил критический баг в LLM-судье.
Ниже — честный технический разбор без воды, реальные данные и мысли вслух за кружкой сидра.

1. Проблема: как агенту ходить по файлам?
Когда разработчик пытается затащить ИИ в свой рабочий процесс, обычно всё сводится к трем сценариям:
Кодят с ИИ как есть — копипастят файлы в окно чата вручную и надеются, что модель угадает контекст.
Пихают всю папку проекта целиком — скармливают LLM весь репозиторий со всеми конфигами и доками, сжигая тонны токенов за один запрос.
На авось подрубают все доступные тулы — дают агенту карт-бланш на использование
ripgrep, AST-парсеров, LSP и векторного поиска одновременно, надеясь, что «и так сойдет».
Знакомая картина? Агент начинает судорожно вычитывать файлы один за другим, надеясь наткнуться на нужный кусок:

Но когда агент пытается починить реальный баг в незнакомой кодовой базе, его работа делится на две фазы:
Навигация (поиск): найти нужные файлы, понять зависимости, структуры и вызовы.
Исполнение (редактирование): применить патч и запустить тесты.
С редактированием всё понятно, а вот с навигацией беда. Я выдвинул простую гипотезу: избыток инструментов навигации вредит агенту не меньше, чем их недостаток.
Когда у модели разбегаются глаза от обилия возможностей, она либо бесконечно переключается между стратегиями поиска (context waste), либо затягивает в контекст столько мусора, что забывает изначальную задачу (эффект context explosion).
Мне было интересно нащупать, какой конкретно тул дает самый чистый контекст. В качестве метрики я взял SPT (Success Per Token) — количество успешных решений на каждую тысячу потраченных токенов.
2. Дизайн песочницы
Для экспериментов я поднял изолированную среду на Python 3.13 и WSL2 Ubuntu. Я виндов-вод, а хотелось чуть более чистый эксперимент. В целом в проекте есть скрипты под linux/macos/windows, на любой вкус. В роли агента выступал фреймворк Agno https://github.com/agno-agi/agno с gpt-4.1-mini. Почему Агно? Причины 3: я устал настраивать opencode, задолбался настраивать opencode и я хотел померить без костылей тулов, который скрыто для пользователя оптимизируют работу.
Все параметры (температура, промпты) зафиксированы, менял только доступные агенту инструменты поиска.
Получился 21 конфиг, которые я разбил на 6 категорий:
1. Семейство Grep-инструментов (Ablation-тесты)
Оставляем только классический текстовый поиск:
07_grep: дефолтный POSIX
grep.08_git_grep: поиск по индексу git.
09_rg: реактивный
ripgrep.10_ugrep: расширенный поиск с нечеткими совпадениями.
11_ast_grep: поиск по синтаксическому дереву.
2. Чтение контекста (Read-стратегии)
05_read_only: агент ищет только по glob-паттернам и читает файлы.
06_read_all: насильно закидываем в контекст вообще все файлы проекта со старта.
3. Семантическая навигация (Semantic)
Инструменты, строящие граф кода:
16_serena_only: доступ к MCP-серверу Serena, который дает символьный граф (кто кого вызывает, где лежат типы).
17_semble_only: поиск по локальным векторным эмбеддингам.
20_serena_semble: гибрид графа Serena и векторов Semble (⭐ спойлер: пушка-гонка).
4. Структурный поиск
12_tree_sitter: разбор файлов через AST.
13_lsp: плоский список символов по протоколу LSP.
5. Интегрированные архетипы
01_cursor_like: смесь
repo_mapи RAG (как под капотом Cursor).02_claude_code_like: гибрид
glob,ripgrepи чтения файлов.03_gemini_like: экстремальная солянка (
read_all+repo_map+rg).18_rg_repo_map:
ripgrepплюс карта репозитория.
6. Минимализм
21_bash_only: голый терминал. Выживай как хочешь.
Чтобы эта банда конфигураций не оставалась просто набором букв в коде, я завёл реестр в дашборде. Вот как выглядит этот зоопарк под капотом (разбил на две части, чтобы не ломать вам глаза мелким шрифтом):


Сценарии
Взял две задачи из реальной кодовой базы:
Medium: поправить регистрозависимость Bearer-токена в middleware. Найти функцию, поправить строку.
Hard: фича
aging_staleв пайплайне Polars. Надо прокинуть новое поле, обновить логику в 3 файлах и дописать тесты.
Оценка качества
Просто прогнать pytest недостаточно. Я натравил на результаты LLM-судью (gpt-5.4-nano), который ревьюил код по 7 критериям (качество, лаконичность, следование паттернам). Ну и считал токены и процент context waste (когда файл прочитан, но не использован).
3. Анатомия LLM-судьи: веса, эвалы и фильтр Неймана
В нашем бенчмарке LLM-судья не просто ставит лайк/дизлайк. Он оценивает код по 7 независимым метрикам ивалам: task_solved, correctness, tool_correctness, context_quality, minimality, pattern_adherence, tool_sequence. Каждому критерию назначен свой вес, а итоговая оценка (Eval Score) считается как взвешенное среднее.

Но и этого мало. Возникла проблема: если агент ломает бизнес-логику (0 за correctness), но при этом пишет красивый минималистичный код (1 за minimality), линейное среднее даст ему завышенный балл. Поэтому я использую геометрический показатель качества, где критические метрики выступают множителями: если correctness равна нулю, обнуляется весь скор.
А чтобы убрать шум от случайных галлюцинаций судьи на гигантских контекстах, я применил пару научных приколов:

Фильтр Неймана: статистический механизм, который отсекает выбросы (outliers) в оценках судьи, опираясь на дисперсию соседних прогонов. Если судья внезапно ставит 1.0 за решение, где ломается синтаксис, фильтр сглаживает эту галлюцинацию.
Поправка Демискар (Demiscar 2006): математический штраф за избыточное чтение. Этот алгоритм нелинейно понижает итоговый Eval Score, если параметр Waste% (прочитанные, но неиспользованные токены) превышает здоровый порог для данной задачи.
Именно этот строгий аппарат позволил отсеять хитрецов, которые ломали тесты, чтобы пройти их на шару.
4. Средняя задача: триумф дедовских методов
Для начала размялись на простой задаче — исправлении регистрозависимости Bearer-токена. Вот как выглядят параметры запуска и описание таски в интерфейсе дашборда:


На простой задаче (Bearer-токен) я прогнал 20 конфигов. 14 из них справились (70% pass rate).
И вот тут случилось первое открытие. Посмотрите на топ самых экономных:
Конфиг |
Инструменты |
Токены |
Тесты |
Примечание |
|---|---|---|---|---|
10_ugrep |
ugrep + edit |
2,697 |
✅ PASS |
⭐ Абсолютный чемпион |
18_rg_repo_map |
rg + repo_map |
3,003 |
✅ PASS |
Очень близко |
05_read_only |
glob + read |
3,276 |
✅ PASS |
|
07_grep |
grep + edit |
3,439 |
✅ PASS |
|
02_claude_code_like |
glob + rg + edit |
3,559 |
✅ PASS |
|
13_lsp |
lsp + edit |
9,994 |
✅ PASS |
Начало усложнения |
20_serena_semble |
serena + semble |
32,747 |
✅ PASS |
Тяжелая артиллерия |
03_gemini_like |
read_all + repo_map |
175,208 |
❌ FAIL |
Context explosion |
⭐ Главный вывод фазы Medium: на простых, точечных задачах легковесные утилиты типа grep, ugrep или ripgrep рвут всех. Агенту нужен ровно один шаг: найти строку Bearer, прочитать этот кусок, заменить. Копеечный расход (меньше 3 тысяч токенов) и моментальный патч.
А вот стратегия gemini_like (закинь в контекст всё) предсказуемо свалилась. Агент наглотался кода, запутался, слил 175 тысяч токенов в унитаз и выдал нерабочий мусор.
5. Сложная задача: когда Grep заводит в тупик
Для сложной задачи (добавление поля в Polars-пайплайн) я прогнал каждый конфиг по 6 раз для надежности. И тут картина перевернулась с ног на голову.
Лидерборд (отсортирован по оценке судьи p75):
Конфиг |
Инструменты |
Успех (pytest) |
Оценка судьи (p75) |
Средние токены |
|---|---|---|---|---|
04_codex_like |
grep + read + edit |
6/6 (100%) |
0.85 |
861,000 |
20_serena_semble |
serena + semble |
5/6 (83%) |
0.79 |
120,000 |
14_repo_map |
repo_map + edit |
4/6 (67%) |
0.76 |
97,000 |
16_serena_only |
serena |
6/6 (100%) |
0.68 |
79,000 |
17_semble_only |
semble |
5/6 (83%) |
0.58 |
84,000 |
10_ugrep |
ugrep + edit |
4/6 (67%) |
0.62 |
1,224,000 |
19_rg_lsp |
rg + lsp |
4/6 (67%) |
0.37 |
425,000 |
18_rg_repo_map |
rg + repo_map |
0/6 (0%) |
0.49 |
79,000 |
03_gemini_like |
read_all + repo_map |
0/6 (0%) |
0.00 |
419,000 |
21_bash_only |
bash |
0/6 (0%) |
0.10 |
85,000 |
А вот как эти результаты выглядят в интерфейсе нашего дашборда со всеми деталями (включая Net SPT и стоимость в центах):

И для любителей сырого терминального вывода — ловите скриншот финального отчёта прямо из консоли после завершения всех 126 раундов:

⚠️ Что мы тут видим:
Serena Only (16_serena_only) творит чудеса: 100% успех при средних затратах всего 79,000 токенов на раунд!
Codex-like (04_codex_like) тоже выдал 100% успех, но ценой чудовищного обжорства — 861,000 токенов. В 11 раз прожорливее Серены!
6. Инсайт: почему так происходит
Всё упирается в когнитивную глубину задачи.
На средней сложности нужно просто найти и заменить. Грепы тут идеальны. Сложные графы (Serena) для этого как микроскоп для забивания гвоздей.
На высокой сложности агенту нужно распутать клубок: понять, откуда вызывается функция в aging.py, посмотреть маппинг в commitment_resolver.py, чекнуть схему валидации.
С одним только grep агент начинает слепо блуждать. Ищет age, получает 150 совпадений по всему проекту и читает их все, раздувая контекст до 1.2 млн токенов (привет, ugrep).
А вот тулы вроде Serena дают семантику. Агент дергает find_symbol("calculate_work_item_aging_facts") и мгновенно получает граф вызовов. Он скачет по цепочке, читая только то, что нужно.
Вывод: Не пихайте в агента один универсальный тулсет. Для малых проектов вам ничего не надо, край давайте
ripgrep. Для сложного рефакторинга забирайтеgrepи давайте LSP/MCP тулы (а лучше просто ставьте Serena MCP https://github.com/oraios/serena, иначе агент сожрет весь лимит токенов на чтение мусора.
7. Эпик фейл с LLM-судьей (и как я спас данные)
Ну и вишенка на торте. Запустил я пачку ранов, открываю логи, а там... у всех запусков оценка судьи 0.0. При этом pytest зеленый.
Полез дебажить и нашел баг в моем llm_judge.py:
# Старый код, который всё сломал: try: itok = int(getattr(resp.metrics, "input_tokens", 0) or 0) except (TypeError, ValueError): itok = 0
Оказалось, в свежей версии Agno у ModelResponse пропал атрибут .metrics (всё переехало в resp.response_usage). Падал AttributeError, который я не ловил. Ошибка летела выше и ломала весь скоринг.
# Фикс здорового человека: try: usage = getattr(resp, "response_usage", None) if usage is not None: itok = int(getattr(usage, "input_tokens", 0) or 0) else: itok = int(getattr(resp, "input_tokens", 0) or 0) except (TypeError, ValueError, AttributeError): # Добавил AttributeError! itok = 0
Перезапускать все раны с нуля было бы больно. Но меня спасло простое правило: я всегда логирую сырые транзакции (agent_messages.json)..
9. Итоги

Если вы собираете свой Agent Harness, вот выжимка:
Grep для простых задач, семантика для сложных.
ripgrepидеален для локальных фиксов. Для рефакторинга нужны LSP-серверы и графы, иначе агент захлебнется в поиске. Serena MCP!;Прочитай всё (read_all) зло. Заливать все файлы репо в контекст со старта — верный путь к context explosion;
А какие тулы вы даете своим агентам под капот? Оставляете им свободу терминала или жестко ограничиваете MCP-серверами? Пишите в комменты, буду рад обсудить!
P.S. Исходный код харнесса и все сырые метрики лежат в репозитории letya999/tools-token-economy. Забирайте, ковыряйте, снижайте энтропию в своих агентах!
Комментарии (5)

ArkadiyShuvaev
03.06.2026 08:43Спасибо за статью и вывод, касающийся Serena MCP.
В качестве эксперимента тестирую LightRAG, индексируя репозитории и статьи базы знаний, чтобы построить граф зависимостей по коду.
Однако, здесь я ставлю несколько иную задачу: я хочу использовать LightRAG через MCP для большего круга задач. Например, в CI pipeline мы можем понять, что удаление/изменение какого-то endpoint может сломать фронтенд.
Renewal_Studio Автор
03.06.2026 08:43Ну те по сути вы хотите ast code graph бахнуть и видеть зависимости на лету?

ArkadiyShuvaev
03.06.2026 08:43Да, примерно так. Раз-два в сутки обходить инкрементальным индексом 100+ репозиториев (мое решение здесь: https://github.com/ArkadiyShuvaev/ligth-rag-ingestion-pipeline) и использовать LightRAG MCP для разных задач, требующих принятия решения по кодовой базе.
Для непосредственного программирования, как оказалось, это не совсем удобно. Я сделал skill для Claude Code и в skill явно попросил использовать LightRAG MCP.
Так как все 100+ репозиториев у меня были локально, Claude Code ни в какую не хотел использовать LightRAG MCP, он использовал grep. Когда я напрямую спросил у него о причинах, он мне ответил, что при наличии всех репозиториев локально на диске ему гораздо удобнее парсить все "налету", чем лезть в LightRAG MCP.
Я допускаю, что я то-то сделал неправильно. Но, в моем конкретном случае, кроме непосредственной помощи при разработке, я пытаюсь найти применение этому подходу и в задачах CI pipeline.
liknenS
Я пробовал разные варианты repo context: grep/ripgrep, индексы, tree-sitter, LSP-подобные подходы. Устойчиво лучше дефолтного Claude Code у меня не получилось.Мне кажется, тут важно сначала разделить тип задач. Если это работа по папке с документами/knowledge base — тогда логичнее строить RAG/индекс и оценивать качество поиска. Если это coding agent в репозитории — он работает иначе: ищет, сужает контекст, читает постепенно и может запускать сабагентов.Почти любой нормальный agent harness уже позволяет попросить модель запустить сабагента, который отдельно сделает ресёрч по коду дешёвой моделью. Тогда дорогая модель не тратит токены на блуждание по файлам, а получает уже сжатый результат. Это выглядит практичнее, чем вручную жонглировать “сейчас включить rg, сейчас Serena, сейчас LSP”.Поэтому если grep-like конфиг сжигает 800k–1.2M токенов, для меня это скорее вопрос к harness/policy агента: лимиты чтения, stopping condition, планирование поиска, сабагенты. Не факт, что проблема именно в grep как инструменте.
Renewal_Studio Автор
Поэтому по умолчанию я рекомендую серену