Собрать команду агентов несложно. Сложно сделать так, чтобы она пережила первую неделю под нагрузкой. Ниже — как выбирать шаблон по его уязвимости, где кончается польза от дробления задачи и почему изоляция исполнения повышает цену атаки, но ничего не гарантирует.
1. Что меняется при выходе в прод
Мультиагентная система ломается часто, и это измерено: систематический разбор MAST — 1600 с лишним размеченных трейсов с семи популярных open-source фреймворков — даёт частоту отказа 41–86,7%. Рядом стоит вторая цифра, не менее важная: при неизменных задаче и модели смена топологии координации сдвигает оценку качества более чем на 30 пунктов и удваивает время работы (MSEval, 100 прогонов на 10 топологиях), то есть организация команды весит примерно столько же, сколько выбор модели.
Вопрос «а нужна ли тут вообще команда» — отдельная тема, и отвечать на него надо до всего остального. По данным Anthropic, агент расходует примерно вчетверо больше токенов, чем чат, а мультиагентная система — примерно в пятнадцать раз больше; расход токенов сам по себе объясняет 80% разброса результата. Их же связка orchestrator-worker (Opus 4 ведущим, Sonnet 4 исполнителями) обошла одиночную модель на 90,2% во внутреннем тесте на исследовательских задачах. Дальше считаем, что решение принято и система уже собрана.
2. Паспорт паттерна: суть, домен, уязвимость, приём
Шаблон удобнее описывать четвёркой «суть — домен — уязвимость — приём против неё», чем схемой на слайде. Решающий здесь третий пункт: паттерн выбирают не по красоте схемы, а по тому, готовы ли вы платить за его слабое место.
Один агент с набором инструментов. Домен — простые ассистенты. Уязвимость — эффект свалки: точность падает по гиперболе с ростом каталога, перелом наступает примерно после семи инструментов. Дальше не «чуть хуже», а заметно хуже. Лечится дроблением на специализированных агентов, а не уговорами в промпте.
Последовательный пайплайн. Каждый агент решает одну задачу, выход предыдущего — вход следующего. Домен — комплаенс, скоринг, юридические проверки. Уязвимость — накопление ошибок: ложный контекст на старте отравляет всё, что ниже. Приём — детерминированные парсеры на стыках: Pydantic-схема работает щитом до вызова следующей модели, а не проверкой в конце. Шаблон недооценён: в замерах MSEval именно структурированные пайплайны сходятся быстрее всех и с лучшим качеством, а тяжёлый управляющий слой качество ухудшает.
Координатор с динамической маршрутизацией. Диспетчер раскидывает запросы по изолированным исполнителям, у каждого чистый системный промпт до 500 токенов. Ломается он предсказуемо: координатор — единая точка отказа, и ошибка классификации уводит пользователя в тупиковую ветку. Приёмы: не тратить на маршрутизацию тяжёлую генерацию (лёгкая модель со строгим JSON или семантический поиск по эмбеддингам) и обязательно ставить температуру в ноль. Маршрутизатор не должен творить.
Рефлексия с обратной связью от среды. Оценку даёт не другая модель, а компилятор, линтер, тесты; лог ошибок и удачных исправлений копится и подаётся в следующую попытку. Домен — конвейеры переноса данных (ETL: извлечь, преобразовать, загрузить), генерация SQL под меняющуюся схему. Уязвимость тут не про качество: без песочницы паттерн означает исполнение произвольного сгенерированного кода на хосте.
Параллельная агрегация. Выглядит бесплатной — запустили независимые проверки разом и синтезировали, — но упирается в пропускную способность инференса: независимы здесь агенты, железо под ними общее. Лимит одновременных запросов задают в инфраструктуре. Иначе выигрыш по времени съедает очередь в пуле.
3. Иерархическая декомпозиция: арифметика ветвления
Самый дорогой шаблон. Топология Root Planner → Workers → Synthesizer: планировщик дробит задачу, воркеры не знают об общей цели, синтезатор собирает ответ. Опасен он рекурсивностью — воркер, получив слишком крупную подзадачу, сам становится планировщиком. Один запуск порождает 20–30 внутренних вызовов модели, и это порядок величины из практики, а не константа.
глубина дерево при ветвлении по 5 узлов
D=0 [planner] 1
D=1 [w] [w] [w] [w] [w] 5
D=2 [.....] x5 25
D=3 [.........................] x5 125
лимит глубины ставит оркестратор, не промпт:
LangGraph 1.2.10 recursion_limit = 10007 -> не ограничивает
OpenAI Agents SDK max_turns = 10 -> витки агента,
а не уровни делегированияОтсюда практическая эвристика: глубина не больше трёх, и держит её не промпт («не углубляйся сильно»), а счётчик в коде оркестратора — модель не умеет надёжно оценивать собственную глубину рекурсии. Само число 3 за пределами этого материала не встречается, а вот направление подтверждают измерения: OrchBench формулирует вывод как «сохранить критичную для задачи информацию важнее, чем нарастить число агентов, а польза от параллелизма тает по мере накопления координационных отказов».
Дефолты SDK — аргумент весомее любой эвристики. Историческая планка LangGraph в 25 итераций больше не действует — актуальный релиз ставит DEFAULT_RECURSION_LIMIT в 10 007 и выносит порог в переменную окружения. У OpenAI Agents SDK лимит есть, но считает он не то: витки одного агента, а не уровни вложенности делегирования. Безопасного дефолта по глубине не даёт ни один из двух фреймворков. К лимиту добавляются тайм-ауты на каждый узел: без них зависший воркер держит всё дерево, а планировщик не знает, ждать ему или считать ветку провалившейся.
Отдельная контрпозиция от команды Devin: архитектуру «разбить → раздать субагентам → склеить» там называют хрупкой, потому что субагенты принимают несогласованные неявные решения, не видя трейса друг друга. Рецепт оттуда простой: субагент отвечает на хорошо поставленный вопрос и не пишет кусок системы.
4. Событийная архитектура: агенты на шине событий
Главного агента здесь нет вообще. Реактивные агенты подписаны на шину событий (Kafka, RabbitMQ), каждый слушает свои типы событий и сам решает, вмешиваться или нет; результат работы — тоже событие. Выигрыш — нет единой точки отказа, и новый агент добавляется подпиской, а не переписыванием графа. Домен узкий: мониторинг безопасности в реальном времени, выявление мошеннических транзакций — задачи, где момент срабатывания неизвестен заранее.
Два требования жёсткие, без них паттерн разваливается.
- Идемпотентность — повторная обработка того же события не должна менять результат. Шина гарантирует доставку «хотя бы один раз», повтор придёт обязательно; если обработчик списывает деньги без ключа идемпотентности, дубликат превращается в инцидент.
- Карантинная очередь (dead-letter queue) — отдельная очередь для событий, на которых обработка сломалась, чаще всего на парсинге ответа модели. Без неё битое событие либо теряется молча, либо бесконечно возвращается в основной поток и отравляет его.
Слабое место — потеря трассировки. В синхронной цепочке идентификатор трейса едет HTTP-заголовком почти бесплатно; в шине его никто не прокидывает автоматически, и traceparent приходится класть в метаданные сообщения и восстанавливать на стороне подписчика — руками, в каждом агенте. Пренебрегли — и разбор инцидента превращается в сопоставление меток времени из разных логов.
5. Гибридная оркестрация: вероятностный слой над детерминированным
Спор «агент или хардкод» обычно ведут как выбор одного из двух, хотя это распределение ответственности. Гибридная оркестрация снимает сам спор: вероятностный слой садится поверх детерминированного, и у каждого своя зона. Граница проходит так: всё, что трогает деньги, доступы и внешние API, выполняет строгий код; агентам остаётся когнитивная работа.
вероятностный слой интерпретация запроса, выбор стратегии,
(LLM-агенты) подготовка данных, формулировка ответа
─────────────────────────────────────────────────────────────
контракт типизированный объект (Pydantic),
валидация до передачи вниз
─────────────────────────────────────────────────────────────
детерминированный транзакции, права, вызовы API,
слой (код, автомат) переходы состояний, аудитНижний слой — конечный автомат (FSM, finite state machine: фиксированный набор состояний и разрешённых переходов). Плата за такой детерминизм приходит через год, и автомат превращается в спагетти: бизнес-правила меняются, граф обрастает ветками, и разобраться в нём уже нельзя. Хуже того, часть логики живёт в промптах, часть в коде, и граница между ними размывается. Приём — вынести граф переходов в декларативную конфигурацию, отдельную от исполняемого кода:
states:
triage: { "on": { classified: risk_check, unclear: human_review } }
risk_check: { "on": { low: auto_reply, high: human_review } }
human_review: { terminal: true }
Тогда правка бизнес-правила проходит ревью и версионируется отдельно от логики исполнения. Второй контур защиты на стыках — контракты инструментов: плоские схемы аргументов вместо вложенных объектов (модели до 14B параметров ошибаются на глубокой вложенности), явные type, enum и регулярные выражения. Битый JSON чинит библиотека восстановления, а не повторный запрос к модели — так дешевле.
6. Режимы отказа и запасной путь
Агентная система ломается, оставаясь зелёной в мониторинге: код 200, метрики в норме, результат негодный. Для алертов удобен короткий чек-лист из трёх сигнатур: бесконечные петли (нет условия выхода, счёт за токены растёт), порча памяти (в долговременное состояние попал невалидный JSON), каскадный коллапс (один неверный шаг отравил контекст, дальше вся генерация от ложной предпосылки).
Оценку «на эти три приходится около 80% сбоев» стоит держать как эвристику из практики, а не как измеренный факт. Академическая картина шире и устроена иначе: MAST раскладывает поведение систем на 14 режимов отказа в трёх категориях — дефекты проектирования системы, рассогласование между агентами, провалы верификации. Универсальную пропорцию работа прямо отрицает: распределение отказов заметно различается между системами и отражает их архитектуру. Практический вывод: чек-лист берите, а долю проверяйте на своих трейсах.
Отдельно — деградация внешнего провайдера. Ретраи спасают от всплеска, но не от долгой недоступности; там ставят предохранитель (circuit breaker), который перестаёт слать запросы в упавший сервис.
Closed ──── >15% ошибок 5xx за 30 с ────> Open <──┐
^ │ │
│ тайм-аут │ провал пробы
успех v │
└──────────── проба ──────────────── Half-Open ─┘
Open -> трафик уходит на запасной путь (локальный vLLM)Всё это опирается на трассировку. Консольные логи бесполезны, когда сессия длится пятнадцать минут и состоит из полусотни автономных шагов: нужны сквозные идентификаторы сессии и трейса, точный промпт каждого узла, сырые аргументы вызовов и расход токенов на шаг. Без такого следа предохранитель нечем питать: долю ошибок и порог срабатывания берут именно оттуда. Как этот след ложится на состояние графа — тема оркестрации графом, и закладывать трассировку надо сразу: дописать её в живую систему выйдет дороже.
7. Память долгоживущего агента: три слоя
Оркестрация без памяти — это деньги на ветер и лишние ретраи. У долгоживущей системы память агента ложится слоями по роду знания, и дисциплина у каждого слоя своя.
| Слой | Что хранит | Отвечает на вопрос | Дисциплина очистки |
|---|---|---|---|
| Эпизодическая (векторный поиск) | прошлые сессии и диалоги | было ли уже такое | чистится по времени |
| Семантическая (граф) | факты и связи сущностей | что мы точно знаем | не чистится, только растёт |
| Процедурная (системные промпты) | правила и ограничения работы | как мы это делаем | меняется через ревью |
Связи вроде User_102 → предпочитает → Python_Async живут в графе не для красоты: по вектору связь не ищется. Релевантность при извлечении считают не по одной близости, а по сумме трёх слагаемых: векторное сходство, экспоненциальное затухание по времени и частота обращений. Забывание встроено в формулу ранжирования: предпочтение полугодичной давности формально останется в базе, но перестанет попадать в контекст. Настраивают поведение соотношением коэффициентов — подняли вес свежести, получили агента, живущего последними неделями.
Жёсткое ограничение поверх всех трёх слоёв: персональные данные, ключи и временные переменные в долговременную память не пишутся. Фильтр здесь детерминированный и стоит до записи в хранилище, а не при чтении.
8. Изоляция исполнения: что реально даёт песочница
Правило одно: никогда не запускать exec() в хост-процессе приложения. Дальше начинается градиент, и думать надо о том, где на нём встать.
контейнер ──> gVisor ──> микро-VM
общее ядро перехват своё ядро
хоста системных через KVM
вызовов
────────────────────────────────────────────>
изоляция сильнее, накладные расходы выше
общий page cache протекает на всех трёх уровняхЗамер 2026 года на одном стенде подтверждает градиент, и бинарной гарантии там нет: виртуализация добавляет задержку и шум. Утечка меняет форму, а зависимость от общего железа и состояния кеша никуда не девается. Формулировку «выйти за периметр невозможно» стоит считать рекламной — речь про стоимость атаки.
Практика подтверждает, что оба конца градиента живые. Modal исполняет сгенерированный моделями код на gVisor — той же технологии, что лежит под Google Cloud Run и GKE. Anthropic для песочницы своего кодинг-агента обошлась без микро-VM и взяла средства операционной системы: bubblewrap на Linux и WSL2, Seatbelt на macOS; сетевой трафик идёт через прокси. Линия микро-VM при этом никуда не делась и уместна там, где песочница живёт долго и права внутри широкие. Для цикла рефлексии, где короткое исполнение повторяется десятки раз, решающими становятся накладные расходы на старт — и выигрывает WASM-песочница, исполняющая Python внутри WebAssembly: среда исполнения физически не видит файловой системы и сети без явного проброса.
Поверх изоляции — ограничения на инструменты, которые ходят в чужие системы: доступ к базе только через учётные записи с правами на чтение, тайм-аут и лимит вывода порядка полусотни строк, любые операции изменения данных — через подтверждение оператором.
Итог
- Уязвимость шаблона — главный критерий выбора: эффект свалки у одиночного агента, накопление ошибок у пайплайна, единая точка отказа у координатора, риск исполнения кода у рефлексии.
- Глубину декомпозиции держит счётчик в оркестраторе; промптом это не лечится. Дефолты фреймворков либо запредельны (10 007 у LangGraph), либо меряют не то (витки агента у OpenAI Agents SDK).
- Событийная модель покупает отсутствие единой точки отказа ценой ручного проброса трассировки; идемпотентность и карантинная очередь — не опции.
- Всё, что трогает деньги и права, живёт в детерминированном слое, а граф переходов — в конфиге, иначе через год машина состояний нечитаема.
- Изоляция поднимает цену атаки, но гарантий не даёт. Долю «80% сбоев на три сигнатуры» проверяйте на своих трейсах: распределение отказов зависит от архитектуры системы.
FAQ
Как выбрать архитектурный паттерн для мультиагентной системы?
По уязвимости, а не по схеме. У каждого шаблона есть известное слабое место: у одиночного агента с инструментами — падение точности после семи инструментов, у последовательного пайплайна — накопление ошибок, у координатора — единая точка отказа, у иерархии — стоимость и задержка ответа. Выбирайте тот, чью цену вы готовы платить и чей приём защиты можете реализовать.
Насколько глубоко можно дробить задачу на подзадачи?
Практический ориентир — не больше трёх уровней вложенности, с лимитом в коде оркестратора и тайм-аутами на каждый узел. Один запуск иерархии обходится в 20–30 вызовов модели: оценка из практики, не константа. Уже при ветвлении по пять третий уровень даёт 125 листьев. Измерения OrchBench показывают, что польза от параллелизма тает по мере накопления координационных отказов, поэтому сохранение критичной информации важнее числа агентов.
Что обязательно нужно для событийной архитектуры агентов?
Идемпотентная обработка и карантинная очередь для сбойных событий. Шина гарантирует доставку «хотя бы один раз», поэтому дубликат придёт обязательно, а событие, на котором сломался парсинг ответа модели, должно уходить в отдельную очередь и не крутиться в основном потоке. Третье, о чём забывают, — идентификатор трейса нужно класть в метаданные сообщения вручную в каждом агенте.
Что должен делать код, а не агент?
Всё, что трогает деньги, доступы, права и внешние транзакции. Агент интерпретирует запрос и возвращает валидированный типизированный объект с параметрами, а выполняет операцию детерминированный слой. Это даёт воспроизводимость и аудит: на вопрос регулятора «почему система так решила» ответ «так решила модель» не работает.
Чем заменить Docker для исполнения сгенерированного агентом кода?
Однозначного ответа нет — есть градиент: контейнер, gVisor с перехватом системных вызовов, микро-VM со своим ядром. Для коротких повторяющихся исполнений выигрывает лёгкий вариант, вплоть до WASM-песочницы; для долгих сессий с широкими правами — микро-VM. При этом ни один уровень не снимает побочный канал через общий страничный кеш, так что изоляция снижает вероятность и повышает цену атаки, но не даёт гарантии.
Когда стоит ставить предохранитель на вызовы модели?
Когда у вас есть запасной путь. Типовой порог срабатывания — свыше 15% ошибок 5xx за 30 секунд, дальше цепь размыкается и после тайм-аута пропускает пробный запрос. Без запасного пути (например, на локальный инференс) размыкание цепи просто превращает недоступность провайдера в ошибки вашего сервиса.
Источники
- Anthropic — How we built our multi-agent research system — кратность расхода токенов, доля дисперсии и эффект связки orchestrator-worker.
- Why Do Multi-Agent LLM Systems Fail? (MAST) — arXiv:2503.13657 — 14 режимов отказа в трёх категориях и частота отказа 41–86,7% на семи фреймворках.
- OrchBench — arXiv:2607.25656 — оценка планов оркестрации симуляцией: предел полезного ветвления и накопление координационных отказов.
- MSEval — arXiv:2607.27877 — топология координации против качества и времени: сдвиг оценки на 30+ пунктов при неизменной модели.
- LangGraph
_config.py· OpenAI Agents SDKrun_config.py— дефолтные лимиты рекурсии и витков — как они есть в исходниках. - gVisor — Security · Modal — Security — механика перехвата системных вызовов и её эксплуатация на агентных нагрузках.
- Claude Code sandboxing — изоляция файловой системы и сети средствами ОС вместо микро-VM.
- Isolation Failure From Shared Storage — arXiv:2607.17518 — замер градиента изоляции на одном стенде и общий побочный канал через страничный кеш.
- Cognition — Don't Build Multi-Agents — контрпозиция к иерархической декомпозиции.
Числовые ориентиры в тексте получены на конкретных корпусах и профилях нагрузки: кратность токенов лаборатория мерила на своём наборе задач и своём поколении моделей, частоту отказов считали на open-source фреймворках, а пороги предохранителя и лимит глубины взяты из практики — калибруйте их на своих трейсах.