- BrainTools - https://www.braintools.ru -
Архитектура «оркестратор + субагенты» на одном экране: оркестратор держит план и раздаёт подзадачи субагентам.
Один AI‑агент в чате — это удобно, пока задача помещается в контекст. Как только она начинает разъезжаться по 30 файлам, четырём ролям и циклу «исследуй — реализуй — отревьюй — поправь», единый чат превращается в свалку: модель путает, какой шаг где, тащит решения из первой задачи в третью и стабильно проседает по качеству начиная с заполнения окна примерно наполовину. Схема «оркестратор + субагенты» — это инженерный ответ на проблему: оркестратор держит план и раздаёт подзадачи изолированным субагентам.
Готовы поделиться нашим опытом [1]: как это устроено
Дисклеймер. Сравнений с Claude Code, Junie, Cursor, JetBrains AI Assistant, OpenAI Swarm, LangGraph и другими реализациями оркестратора с субагентами в этой статье нет — это отдельный жанр, требующий одинакового бенча. Цель статьи — показать архитектурные решения и причины, по которым мы к ним пришли. Материал — конспект внутреннего доклада и практики на нашем плагине.
Качество ответа 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).
Если в одной строке: субагент — это изолированный агент‑ассистент, к которому оркестратор обращается как к чёрному ящику.
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_dir, write_in_dir), которые ограничены ровно этой папкой.
sharedDir (<projectRoot>/.tasks по умолчанию, путь конфигурируется); тулы сабагента ограничены ровно этой папкой.Почему report_result(summary), а не «верни всё, что наработал» — субагент по построению генерирует много промежуточного шума: тысячи строк grep‑выдачи, прочитанные файлы, чужие классы. Если всё это вернуть в чат оркестратора, мы возвращаемся к проблеме захламлённого контекста, ради ухода от которой всё и затевалось. Поэтому return — это всегда сжатая сводка, а детали через файлы в sharedDir.
Параллельность — оркестратор может запустить несколько субагентов одним шагом и блокируется до завершения всех. Это упрощает синхронизацию (никаких очередей и колбэков на стороне оркестратора), но накладывает естественное ограничение: задача делится на параллельные ветви, у которых нет кросс‑зависимостей. Если зависимости есть, лучше последовательный вызов.
Автономность через «Продолжай» — субагент должен сам решить, что закончил, и вызвать report_result. Если он этого не сделал, мы пинаем его сообщением «Продолжай или вызови report_result» до 10 раз. После — принудительная остановка и возврат с ошибкой [5] в оркестратор. На практике даже на слабых моделях этой эвристики в 10 итераций хватает для завершения задачи.
Это место, где много маркетинга. Мы у себя сформулировали честно: оркестратор с сабагентами даёт выигрыш на трёх классах задач, и почти везде вне этих трёх классов проигрывает одиночному агенту.
Задачи, в которых нужно пройти по всему проекту, что‑то посмотреть и вернуть структурированный отчёт. Состояние нигде не меняется, шаги независимы.
Что мы у себя гоняем через субагентов:
Прогон ревью‑чеклистов по всему 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 работает плохо: к третьей итерации модель уже «знает», что было в первых двух, и не может посмотреть на свой код свежим глазом. С отдельным сабагентом на каждую итерацию это перестаёт быть проблемой, у каждого свой контекст.
Кейсы, где это даёт самый явный выигрыш:
Поиск багов: субагенты ищут параллельно, пока оркестратор собирает агрегированный отчёт.
Поиск 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 раз больше токенов на эквивалентный результат.
Правильный критерий декомпозиции — не «какие роли в команде разработки», а где можно изолировать контекст.

Хорошие границы для разделения:
Независимые исследовательские области (исследование разных модулей, разных issue, разных правил ревью).
Слабо связанные модули с чистым интерфейсом (фронт и бэк по контракту).
Чёрный ящик‑проверка: тесты, прогон линтера, прогон бенчмарка, не нужен контекст реализации.
Плохие границы:
Последовательные фазы одной фичи (план → код → тест), слишком много общего контекста.
Сильно связанные компоненты, которым нужно много синхронизироваться.
Задачи, требующие общего разделяемого состояния.
В таблице ниже — что мы у себя пробовали и к чему пришли:
|
Стратегия разбивки |
Подход |
Итог |
|---|---|---|
|
По ролям (planner/coder/reviewer) на одной фиче |
Каноничная схема разбивки по ролям |
Плохо. Дорого, медленно, теряется контекст между ролями |
|
По участкам кода: пакет / класс → сабагент |
На каждый класс свой сабагент |
Плохо. Слишком долго, оверхэд на координацию |
|
По модулям, если модули слабо связаны |
Один сабагент на модуль |
Ок |
|
По мини‑подзадачам |
Каждый таск — сабагент |
Плохо. Слишком долго |
|
По группам связанных подзадач |
Несколько связанных тасков рядом |
Ок |
|
По итерациям loop‑а |
Каждая итерация — свой сабагент |
Хорошо |
|
По группам правил для ревью |
Группа правил → сабагент |
Хорошо |
Когда мы только запустили оркестратор, типичный пользовательский опыт выглядел так: человек писал в чат «сделай ревью этого PR через сабагентов», оркестратор раскладывал задачу как умел, и каждый раз по‑новому. Качество прыгало.
Решение оказалось не в «более умном оркестраторе», а в скиллах — markdown‑файлах, которые описывают конкретный пайплайн.
Что мы кладём в скилл оркестратора:
Какие субагенты вызывать и в каком порядке.
Какой возвращаемый результат ожидается от каждого.
Сколько итераций в 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 и файлов). Дорого, но один человек руками это делал бы день.
Реальные кейсы, которые мы ловили:
Claude в роли субагента просил оркестратора «верни мне содержимое всех изменённых файлов», попытка обойти контракт на компактный summary через social‑engineering оркестратора.
Субагент‑ревьюер периодически решал, что задача не «отревьюить», а «исправить и отревьюить», и начинал писать в файлы.
Оркестратор иногда не понимал, какую задачу кому делегировать, и запускал двух субагентов с одинаковыми описаниями. Это вопрос промпта оркестратора и скилла, мы это лечим.
Папка .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× по токенам и заметно дольше по реальному времени — нормальная цена за оркестратор с субагентами. Если выигрыша по качеству нет, вы платите впустую.
А у вас как? Если использовали субагентов, по каким границам декомпозиция реально окупилась? Любопытно сверить наш «делите по контексту, не по ролям» с вашим опытом, пишите в комментариях.
Через две недели после публикации соберём вопросы из комментариев под этой статьёй и закроем их вживую: разберём ваши кейсы, покажем настройку оркестратора и сабагентов на реальных проектах, ответим на всё, что не влезло в текст.
По архитектуре из статьи
Как понять, что в моём чате контекст уже «захламлён» и пора создавать новый чат?
Как быть, если есть одна большая задача, связанная с одним компонентом?
Граница Medium/Large — ваш эмпирический порог. Как найти свой?
По сабагентам в продукте Veai
Чем субагент Veai отличается от sub‑agents в Claude Code и task‑agent в Cursor?
Как выглядит UI оркестратора: видно ли, какой сабагент работает, можно ли его остановить
Как субагенты Veai используют PSI‑индекс IntelliJ вместо grep, и почему это выигрывает в токенах?
Как запустить свой скилл и расшарить его внутри команды?
По продукту Veai — безопасность, модели, enterprise
Какие модели поддерживает плагин и можно ли подключить свой LLM‑эндпоинт (on‑prem / vLLM / российские провайдеры)?
Что уходит в провайдера модели при работе субагента, а что остаётся локально?
Как Veai ведёт себя на monorepo 4M+ LoC и можно ли запустить оркестратор из CI?
Чем Veai отличается от Claude Code, Junie, JetBrains AI Assistant и Cursor именно на больших задачах?
По цифрам и экономике
Какие реальные ценники по токенам на ревью PR ~10k LoC и на поиск code smells по модулю?
Как вы считаете 1.5–2× и 3–10× на внутреннем бенчмарке 24 задач? Какая методология?
Когда экономически не окупается звать оркестратор, даже если задача Large?
Чтобы понять формат, который будет полезен большинству, проголосуйте в коротком опросе:
Что хотите увидеть на воркшопе в первую очередь?
Живой разбор кейсов из комментариев под статьёй
Пошаговая настройка оркестратора и сабагентов в JetBrains IDE
Сравнение «одиночный агент vs оркестратор с сабагентами» на одной и той же задаче
Скиллы (markdown‑алгоритмы) и как их писать под свой проект
Замеры: токены, время, качество — методология и цифры
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
Нажмите здесь для печати.