- BrainTools - https://www.braintools.ru -

Опыт использования субагентов в AI‑агенте для IDE: что реально работает на больших задачах, а что нет

 Архитектура «оркестратор + сабагенты» на одном экране: оркестратор держит план и раздаёт подзадачи сабагентам.

Архитектура «оркестратор + сабагенты» на одном экране: оркестратор держит план и раздаёт подзадачи сабагентам.

Архитектура «оркестратор + субагенты» на одном экране: оркестратор держит план и раздаёт подзадачи субагентам.

Один AI‑агент в чате — это удобно, пока задача помещается в контекст. Как только она начинает разъезжаться по 30 файлам, четырём ролям и циклу «исследуй — реализуй — отревьюй — поправь», единый чат превращается в свалку: модель путает, какой шаг где, тащит решения из первой задачи в третью и стабильно проседает по качеству начиная с заполнения окна примерно наполовину. Схема «оркестратор + субагенты» — это инженерный ответ на проблему: оркестратор держит план и раздаёт подзадачи изолированным субагентам.

Готовы поделиться нашим опытом [1]: как это устроено

Дисклеймер. Сравнений с Claude Code, Junie, Cursor, JetBrains AI Assistant, OpenAI Swarm, LangGraph и другими реализациями оркестратора с субагентами в этой статье нет — это отдельный жанр, требующий одинакового бенча. Цель статьи — показать архитектурные решения и причины, по которым мы к ним пришли. Материал — конспект внутреннего доклада и практики на нашем плагине.

TL;DR

  • Качество ответа LLM падает по мере заполнения контекста. На наших внутренних замерах в JetBrains‑плагине просадка становится заметной после ~50% заполненности и резко обваливается после ~85%. Похожая картина описана в Lost in the Middle (Liu et al., 2023) [2] и в Anthropic Engineering: Effective context engineering [3].

  • Субагент — это не «агент, который зовёт агента». Это изолированный подпроцесс со своими тулами и единственным каналом возврата — report_result(summary). Субагентов вызывает только оркестратор.

  • Оркестратор с субагентами дает выигрыш на трех классах задач: project‑wide read‑only (ревью, триажинг, инвентаризация), сложные пайплайны с явной разбивкой ролей по разным scope (TDD, SDD, итеративная фича), loop‑based задачи (review‑loop, поиск code smells).

  • На задачах, помещающихся в контекст одного агента, оркестратор с субагентами почти всегда проигрывает одиночному агенту. Anthropic в посте «How we built our multi‑agent research system» [4] пишут о 3–10× расходе токенов на эквивалентный результат — на наших задачах цифра близкая.

  • Главный инженерный выбор — где провести границу декомпозиции. Делить по ролям (planner / coder / reviewer на одной фиче) почти всегда плохо: координация съедает больше токенов, чем сама работа. Делить по контекстным границам — хорошо.

  • Промпт «сделай через субагентов» работает плохо, скилл (markdown‑файл с алгоритмом, acceptance criteria и явным списком субагентов) — хорошо.

Почему один чат деградирует на крупных задачах

В презентации внутри команды у нас есть слайд, который мы потом вынесли наружу: «качество ответа = качество контекста». У контекста есть три неприятных свойства, и все три бьют ровно в крупную задачу.

Первое — предвзятое отношение к прошлым ответам. LLM считает свои собственные предыдущие сообщения частью истины. Если в чате вы зацепили неудачное направление и потом передумали, модель будет к нему возвращаться даже после фразы «забудь». Это особенно видно на ревью‑лупах: вторая итерация почти всегда «защищает» решение первой, а не оценивает его заново.

Второе — жесткое ограничение размера. У нас агент по умолчанию читает не целые файлы, а диапазоны строк, предварительно прочитав структуру файла (благо есть возможность получить эту информацию из IDE); даже так окно 200k токенов уходит за 20–30 tool calls на enterprise‑репозитории ~4M LoC. На чтении файлов целиком, как делает большинство grep‑агентов, бюджет кончается ещё быстрее.

Третье — деградация при заполнении. На наших внутренних замерах (актуальные на апрель 2026 модели семейств Claude Opus, Claude Sonnet и GPT — у всех похожая форма кривой) качество держится примерно линейным до 40–50% заполненности окна. На участке 50–85% начинается заметная просадка: модель чаще теряет нить, путает, какой шаг где, начинает «склеивать» куски разных задач. На 95–99% она формально отвечает, но содержательно нет. Эти наблюдения совпадают с описанием в Lost in the Middle [2]: информация в середине длинного контекста используется хуже, чем на краях.

Проблемы:

  • Loop‑based пайплайны (ревью, итеративная разработка, поиск code smells) в одном чате системно искажаются: каждая следующая итерация смотрит на предыдущую как на «уже почти ок».

  • Context‑heavy задачи целиком в один чат не лезут. Суммаризация частично спасает, но теряет детали.

  • Сложные пайплайны нельзя гонять в автоматическом режиме: пользователь вынужден быть оркестратором руками.

  • Стратегичность скатывается в тактику. Модель начинает решать «следующую очевидную подпроблему», а не план целиком.

  • Параллельности нет.

Оркестратор с субагентами решает ровно эти пять проблем, но не бесплатно.

Анатомия субагентов: что есть и чего нет

Субагент в нашей реализации — это не «агент, который умеет звать агента». Это отдельный процесс с пустым контекстом на старте, со своим (часто урезанным) набором тулов, запущенный с общей папкой для обмена данными и с единственным тулом штатного завершения — вызовом report_result(summary).

Если в одной строке: субагент — это изолированный агент‑ассистент, к которому оркестратор обращается как к чёрному ящику.

reportresult

Жизненный цикл одного вызова: оркестратор формирует SubagentCall, сабагент работает в своём контексте, возвращает компактный summary через report_result.

Контракт вызова из оркестратора (упрощенная сигнатура):

data class SubagentCall(
    val shortDescription: String,   // одна фраза для UI и логов
    val fullDescription: String,    // полный промпт задачи для сабагента
    val context: String,            // выжимка релевантного контекста от оркестратора
    val sharedDir: Path,            // папка, через которую идёт обмен файлами
)

Несколько решений в этом контракте, которые на первый взгляд выглядят странно, и причины, по которым мы к ним пришли.

Почему субагент не может звать субагентов — в ранних прототипах мы это разрешали. На второй неделе обнаружили дерево субагентов глубиной 6, в котором листья тратили токены на пересказ задачи родителя бабушке‑родителю, и обратно. Иерархия сворачивается в координационный ад быстрее, чем вы успеваете её отдебажить. Поэтому в текущей версии сабагенты звать сабагентов не могут, и это дисциплинирует декомпозицию у оркестратора.

Почему субагент не общается с пользователем — это by design. Если сабагенту нужно что‑то спросить, он либо отвечает на основе контекста, либо завершает работу с пометкой «не хватает данных». Спрашивать пользователя — задача оркестратора. Иначе у пользователя одновременно живут пять чатов от пяти сабагентов, и никто, включая сам оркестратор, не понимает, кто что делает.

Почему общая папка, а не передача через аргументы — контекст в аргументе тула дорогой и узкий. Если сабагенту нужно отдать обратно дифф на 800 строк или JSON с разметкой 200 issue, он кладёт это в файл в sharedDir, а в report_result возвращает короткую сводку и путь. Все участники, включая оркестратора, могут читать и писать в эту папку, у нас это решено через directory‑bound тулы (read_in_dirwrite_in_dir), которые ограничены ровно этой папкой.

sharedDir

Обмен крупными артефактами идёт через sharedDir (<projectRoot>/.tasks по умолчанию, путь конфигурируется); тулы сабагента ограничены ровно этой папкой.

Почему report_result(summary), а не «верни всё, что наработал» — субагент по построению генерирует много промежуточного шума: тысячи строк grep‑выдачи, прочитанные файлы, чужие классы. Если всё это вернуть в чат оркестратора, мы возвращаемся к проблеме захламлённого контекста, ради ухода от которой всё и затевалось. Поэтому return — это всегда сжатая сводка, а детали через файлы в sharedDir.

Параллельность — оркестратор может запустить несколько субагентов одним шагом и блокируется до завершения всех. Это упрощает синхронизацию (никаких очередей и колбэков на стороне оркестратора), но накладывает естественное ограничение: задача делится на параллельные ветви, у которых нет кросс‑зависимостей. Если зависимости есть, лучше последовательный вызов.

Автономность через «Продолжай» — субагент должен сам решить, что закончил, и вызвать report_result. Если он этого не сделал, мы пинаем его сообщением «Продолжай или вызови report_result» до 10 раз. После — принудительная остановка и возврат с ошибкой [5] в оркестратор. На практике даже на слабых моделях этой эвристики в 10 итераций хватает для завершения задачи.

Когда оркестратор с субагентами реально выигрывает у одиночного агента

Это место, где много маркетинга. Мы у себя сформулировали честно: оркестратор с сабагентами даёт выигрыш на трёх классах задач, и почти везде вне этих трёх классов проигрывает одиночному агенту.

 Пример: пайплайн для end-to-end подготовки домашнего задания для студентов.

Пример: пайплайн для end‑to‑end подготовки домашнего задания для студентов.

Project‑wide read‑only

Задачи, в которых нужно пройти по всему проекту, что‑то посмотреть и вернуть структурированный отчёт. Состояние нигде не меняется, шаги независимы.

Что мы у себя гоняем через субагентов:

  • Прогон ревью‑чеклистов по всему PR / по всему модулю (пакет → сабагент).

  • Триажинг issue из трекера (GitHub / GitLab / YouTrack): воспроизводится / не воспроизводится, severity, дубли (один сабагент на батч issue).

  • Инвентаризация фич продукта (один сабагент на функциональную область).

  • Сборка полной документации проекта (по модулям).

  • Поиск code smells по списку правил (батч связанных правил → один сабагент).

Параллельность тут даёт реальный выигрыш по реальному времени, а изоляция контекста — по precision: субагент, у которого в контексте связанные правила по организации кода по пакетам, не отвлекается на проверку IDE‑специфичных дедлоков.

Сложные пайплайны с явной разбивкой на роли

Когда у задачи действительно есть разные этапы или разные роли, и они работают на разных кусках кода. Не «одна фича + три роли», а именно «разные scope».

Примеры из нашей практики:

  • TDD‑пайплайн:

    • субагент-1 пишет тесты по описанию задачи,

    • субагент-2 пишет реализацию под зелёные тесты,

    • субагент-3 ревьюит. Каждому в контексте лежит ровно его кусок, не больше.

  • SDD + TDD: перед всем этим оркестратор зовёт субагента‑планировщика, который читает issue из трекера или спеку и раскладывает её на task-01.md [6]task-02.md [7], … в sharedDir.

  • Итеративная разработка через спеку: один субагент‑кодер на каждую итерацию, один общий ревьюер в конце каждой итерации, обновление спеки между итерациями, планирование следующей итерации.

  • Автогенерация домашних заданий по шаблону.

Loop‑based пайплайны

Внутри одного агента loop работает плохо: к третьей итерации модель уже «знает», что было в первых двух, и не может посмотреть на свой код свежим глазом. С отдельным сабагентом на каждую итерацию это перестаёт быть проблемой, у каждого свой контекст.

Кейсы, где это даёт самый явный выигрыш:

  • Поиск багов: субагенты ищут параллельно, пока оркестратор собирает агрегированный отчёт.

  • Поиск code smells: один проход — один сабагент, оркестратор склеивает.

  • Параллельный сбор информации о проекте.

Те же задачи можно делать одним чатом с Ralph Wiggum loop (паттерн Geoff Huntley [8]: один и тот же промпт зациклен в while‑true, пока не выполнено условие), но тогда нужно вручную следить за размером контекста. На длинной дистанции это всё равно сваливается в захламление.

Где субагенты строго хуже

Тоже честно. Если задача попадает в этот список, оркестратор с сабагентами дороже и хуже одиночного агента.

 Три типичных анти-паттерна: маленькая задача, связный контекст между подзадачами, обязательная ручная валидация после каждого шага.

Три типичных анти‑паттерна: маленькая задача, связный контекст между подзадачами, обязательная ручная валидация после каждого шага.

Первый случай — задача целиком помещается в контекст. Фикс мелкого бага, мелкое улучшение существующей фичи, рефакторинг до 100 LoC и до 10 файлов. Один чат справится за один шаг, оркестратор будет 4 шага собирать контекст для сабагентов и ещё 2 склеивать ответы.

Второй случай — общий контекст важен и связный. Когда вы решаете несколько связанных задач, и предыдущие решения должны влиять на следующие, оркестратор с сабагентами тут вреден. Каждый сабагент будет переспрашивать и переделывать. Лучше один чат с компрессией.

Третий случай — нужно каждый шаг смотреть глазами. Если задача требует ручной валидации после каждого шага, оркестратор просто добавляет лишний слой между вами и кодом. Все передачи между сабагентами всё равно ложатся на вас.

Эмпирическое правило по объёму, к которому мы пришли:

Объём задачи

LoC

Файлов

Что использовать

Small

до 100

до 10

Одиночный агент

Medium

100–300

10–20

Одиночный агент

Large

300

20

Оркестратор + сабагенты

Сложный пайплайн

любой

любой

Оркестратор + сабагенты

Граница «medium / large» наша. У вас она может проходить иначе: зависит от того, насколько связан код в проекте.

Как мы декомпозируем и почему по ролям почти всегда плохо

Самая дорогая ошибка при работе с оркестратором и субагентами: «давайте у нас будет субагент‑планировщик, субагент‑кодер, субагент‑тестировщик и субагент‑ревьюер на каждой задаче». На бумаге логично [9], на практике эти четверо проводят 70% токенов на пересказ друг другу того, что предыдущий уже сделал.

То же самое формулирует Anthropic в своих заметках по оркестратору с субагентами: при разделении работы по ролям внутри одной задачи субагенты тратят больше токенов на координацию, чем на саму работу. По нашим замерам, на задачах, помещающихся в контекст одного агента, оркестратор с субагентами съедает в 3–10 раз больше токенов на эквивалентный результат.

Правильный критерий декомпозиции — не «какие роли в команде разработки», а где можно изолировать контекст.

Опыт использования субагентов в AI‑агенте для IDE: что реально работает на больших задачах, а что нет - 6

Хорошие границы для разделения:

  • Независимые исследовательские области (исследование разных модулей, разных issue, разных правил ревью).

  • Слабо связанные модули с чистым интерфейсом (фронт и бэк по контракту).

  • Чёрный ящик‑проверка: тесты, прогон линтера, прогон бенчмарка, не нужен контекст реализации.

Плохие границы:

  • Последовательные фазы одной фичи (план → код → тест), слишком много общего контекста.

  • Сильно связанные компоненты, которым нужно много синхронизироваться.

  • Задачи, требующие общего разделяемого состояния.

 Хороший случай: разбиение по слабо связанным модулям с чистым интерфейсом.

Хороший случай: разбиение по слабо связанным модулям с чистым интерфейсом.

В таблице ниже — что мы у себя пробовали и к чему пришли:

Стратегия разбивки

Подход

Итог

По ролям (planner/coder/reviewer) на одной фиче

Каноничная схема разбивки по ролям

Плохо. Дорого, медленно, теряется контекст между ролями

По участкам кода: пакет / класс → сабагент

На каждый класс свой сабагент

Плохо. Слишком долго, оверхэд на координацию

По модулям, если модули слабо связаны

Один сабагент на модуль

Ок

По мини‑подзадачам

Каждый таск — сабагент

Плохо. Слишком долго

По группам связанных подзадач

Несколько связанных тасков рядом

Ок

По итерациям loop‑а

Каждая итерация — свой сабагент

Хорошо

По группам правил для ревью

Группа правил → сабагент

Хорошо

Скиллы вместо промпта в чате

Когда мы только запустили оркестратор, типичный пользовательский опыт выглядел так: человек писал в чат «сделай ревью этого PR через сабагентов», оркестратор раскладывал задачу как умел, и каждый раз по‑новому. Качество прыгало.

Решение оказалось не в «более умном оркестраторе», а в скиллах — markdown‑файлах, которые описывают конкретный пайплайн.

 Скилл – это просто markdown-файл: вход, шаги, какие сабагенты вызывать, acceptance criteria, лимит итераций.

Скилл — это просто markdown‑файл: вход, шаги, какие сабагенты вызывать, acceptance criteria, лимит итераций.

Что мы кладём в скилл оркестратора:

  • Какие субагенты вызывать и в каком порядке.

  • Какой возвращаемый результат ожидается от каждого.

  • Сколько итераций в loop‑е (мы не уходим выше 4 для ревью и 5 для генерации, после этого качество перестаёт расти, а токенов жжёт всё больше).

  • Acceptance criteria и checklists для итогового результата.

  • Всю необходимую инфу в начале скилла, чтобы оркестратору не пришлось «исследовать» задачу самому.

Чего не кладём:

  • Слишком сложной логики. LLM‑модели всё ещё тупят, и скилл из 12 ветвлений ломается на пятой задаче.

Ключевой эффект: скилл легко дебажить (это просто файл), переиспользовать (между задачами и проектами) и расшарить (через репозиторий команды). Свободный промпт в чате не даёт ни одного из этих свойств.

 Несколько скиллов в общем доступе у команды: пайплайны воспроизводятся, не надо переписывать промпт каждый раз.

Несколько скиллов в общем доступе у команды: пайплайны воспроизводятся, не надо переписывать промпт каждый раз.

Скиллы, которые у нас закрепились в общем доступе:

  • Скилл поиска всех фич в проекте.

  • Скилл итеративной разработки через спеку.

  • Скилл поиска code smells.

  • Скилл написания/исправления других скиллов (мета).

Что мы наблюдали под капотом

Расход токенов

На задачах, где оркестратор с субагентами обоснован, мы видим 1.5–2× больше токенов по сравнению с одиночным агентом — это плата за параллельность и изоляцию. На задачах, где он не обоснован, расход уходит в 3–10×. Цифры — наш замер на 24 задачах внутреннего бенчмарка (старшая модель Claude Opus, апрель 2026; 6 задач на каждый класс: ревью PR, триажинг issue, TDD‑пайплайн, поиск code smells), методологию опубликуем отдельно (скоро в отдельной статье).

Время выполнения

Параллельный шаг оркестратора с N сабагентами идёт дольше самого медленного из N. На review‑loop с 5 сабагентами на PR ~10k LoC у нас выходит около 70 минут реального времени (старшая модель Claude Opus, ~180 tool calls суммарно по всем сабагентам, в основном чтение PSI и файлов). Дорого, но один человек руками это делал бы день.

Что LLM пытается хакнуть

Реальные кейсы, которые мы ловили:

  • Claude в роли субагента просил оркестратора «верни мне содержимое всех изменённых файлов», попытка обойти контракт на компактный summary через social‑engineering оркестратора.

  • Субагент‑ревьюер периодически решал, что задача не «отревьюить», а «исправить и отревьюить», и начинал писать в файлы.

  • Оркестратор иногда не понимал, какую задачу кому делегировать, и запускал двух субагентов с одинаковыми описаниями. Это вопрос промпта оркестратора и скилла, мы это лечим.

sharedDir накапливается

Папка .tasks (по умолчанию <projectRoot>/.tasks, путь конфигурируется) копит артефакты, которые нужны были на минуту: дифф, который уже применён, отчёт, который уже сведён. У нас она в .gitignore и периодически чистится скриптом.

Известные ограничения

В субагентах приходится заново собирать контекст для каждого вызова. Это ровно та цена, которую вы платите за изоляцию. Часть контекста (AGENTS.md [10], правила проекта, общие скиллы) кэшируется автоматически, но «релевантные файлы под эту задачу» сабагенту приходится искать заново.

Координационный оверхэд тоже значимый. На каждом вызове сабагента вы тратите токены на обязательные тулы: report_progress для апдейтов, report_result для возврата. На задачах, где сама работа измеряется минутами, это терпимо. На быстрых задачах это и есть основной расход.

Важно:

  • Контекст — главный ограничитель LLM‑агента. Не промпт, не модель, не RAG. Если контекст захламлён, деградация модели становится существенной.

  • Оркестратор с субагентами — это инженерное решение проблемы контекста, а не «более умный AI». Поэтому такая схема помогает только там, где проблема контекста реально есть.

  • Делите по контекстным границам, не по ролям. Planner / coder / reviewer на одной фиче — это анти‑паттерн. Но роль reviewer в любом виде важна: без отдельного ревью‑шага (в виде субагента‑ревьюера, отдельной итерации в loop’е или по группам правил) результат не выверить.

  • На малых задачах (≤100 LoC, ≤10 файлов) одиночный агент дешевле и часто лучше. Не зовите оркестратор на каждый чих.

  • Используйте скиллы (markdown‑файлы с алгоритмом), а не свободные промпты. Это единственный способ получить воспроизводимый пайплайн.

  • 3–10× по токенам и заметно дольше по реальному времени — нормальная цена за оркестратор с субагентами. Если выигрыша по качеству нет, вы платите впустую.

А у вас как? Если использовали субагентов, по каким границам декомпозиция реально окупилась? Любопытно сверить наш «делите по контексту, не по ролям» с вашим опытом, пишите в комментариях.

Workshop / вебинар через 2 недели

Через две недели после публикации соберём вопросы из комментариев под этой статьёй и закроем их вживую: разберём ваши кейсы, покажем настройку оркестратора и сабагентов на реальных проектах, ответим на всё, что не влезло в текст.

Вопросы, на которые ответим вживую

По архитектуре из статьи

  1. Как понять, что в моём чате контекст уже «захламлён» и пора создавать новый чат?

  2. Как быть, если есть одна большая задача, связанная с одним компонентом?

  3. Граница Medium/Large — ваш эмпирический порог. Как найти свой?

По сабагентам в продукте Veai

  1. Чем субагент Veai отличается от sub‑agents в Claude Code и task‑agent в Cursor?

  2. Как выглядит UI оркестратора: видно ли, какой сабагент работает, можно ли его остановить

  3. Как субагенты Veai используют PSI‑индекс IntelliJ вместо grep, и почему это выигрывает в токенах?

  4. Как запустить свой скилл и расшарить его внутри команды?

По продукту Veai — безопасность, модели, enterprise

  1. Какие модели поддерживает плагин и можно ли подключить свой LLM‑эндпоинт (on‑prem / vLLM / российские провайдеры)?

  2. Что уходит в провайдера модели при работе субагента, а что остаётся локально?

  3. Как Veai ведёт себя на monorepo 4M+ LoC и можно ли запустить оркестратор из CI?

  4. Чем Veai отличается от Claude Code, Junie, JetBrains AI Assistant и Cursor именно на больших задачах?

По цифрам и экономике

  1. Какие реальные ценники по токенам на ревью PR ~10k LoC и на поиск code smells по модулю?

  2. Как вы считаете 1.5–2× и 3–10× на внутреннем бенчмарке 24 задач? Какая методология?

  3. Когда экономически не окупается звать оркестратор, даже если задача Large?

Как участвовать

Чтобы понять формат, который будет полезен большинству, проголосуйте в коротком опросе:

Что хотите увидеть на воркшопе в первую очередь?

  1. Живой разбор кейсов из комментариев под статьёй

  2. Пошаговая настройка оркестратора и сабагентов в JetBrains IDE

  3. Сравнение «одиночный агент vs оркестратор с сабагентами» на одной и той же задаче

  4. Скиллы (markdown‑алгоритмы) и как их писать под свой проект

  5. Замеры: токены, время, качество — методология и цифры

  6. Q&A с разработчиками плагина без сценария

Свой вопрос для разбора — пишите в комментариях или в наш чат: https://t.me/veai_devs [11]. Ссылку на регистрацию опубликуем там же.

Автор: dirvika

Источник [12]


Сайт-источник BrainTools: https://www.braintools.ru

Путь до страницы источника: https://www.braintools.ru/article/30171

URLs in this post:

[1] опытом: http://www.braintools.ru/article/6952

[2] Lost in the Middle (Liu et al., 2023): https://arxiv.org/abs/2307.03172

[3] Anthropic Engineering: Effective context engineering: https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents

[4] «How we built our multi‑agent research system»: https://www.anthropic.com/engineering/built-multi-agent-research-system

[5] ошибкой: http://www.braintools.ru/article/4192

[6] task-01.md: http://task-01.md

[7] task-02.md: http://task-02.md

[8] паттерн Geoff Huntley: https://ghuntley.com/ralph/

[9] логично: http://www.braintools.ru/article/7640

[10] AGENTS.md: http://AGENTS.md

[11] https://t.me/veai_devs: https://t.me/veai_devs

[12] Источник: https://habr.com/ru/companies/veai/articles/1034208/?utm_campaign=1034208&utm_source=habrahabr&utm_medium=rss

www.BrainTools.ru

Rambler's Top100