Мультиагентные системы: несколько LLM-агентов вместе
Один агент с длинным промптом рано или поздно упирается в потолок: он одновременно должен планировать, выполнять и проверять сам себя — а роль «сам себе критик» у LLM получается плохо. Мультиагентная система решает это не более умной моделью, а разделением труда: разные агенты отвечают за разные части задачи и перепроверяют друг друга. Разберём, когда это оправдано, как устроен базовый паттерн и во что реально обходится такая архитектура.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Зачем несколько агентов вместо одного
Что такое агент вообще и чем он отличается от чат-бота, мы разбирали отдельно в статье ИИ-агенты против чат-ботов: в чём разница на практике — здесь это база, повторять не будем. Вопрос этой статьи другой: зачем вообще плодить несколько агентов, если один и так умеет думать циклами «подумал → сделал → проверил»?
Причина в том, что один агент, который одновременно планирует, исполняет и оценивает собственный результат, склонен повторять свои же ошибки. Модель, только что написавшая код с багом, с высокой вероятностью не увидит этот баг и при самопроверке в том же контексте — она уже «поверила» в своё решение. Это тот же эффект, из-за которого человеку сложно вычитывать собственный текст: свежий взгляд видит то, что автор не видит.
Разделение на роли даёт три практических эффекта:
- Специализация. Планировщик получает промпт под декомпозицию задачи, ему не нужно помнить синтаксис конкретного API. Исполнитель не знает про общую стратегию, зато отлично работает с узким инструментом. Узкий промпт и узкий контекст почти всегда дают более стабильный результат, чем один универсальный промпт на всё.
- Независимая проверка. Когда результат оценивает агент, не участвовавший в его создании, у него нет промптовой инерции защищать это решение — как в код-ревью, где автор PR и ревьюер разные люди не для галочки.
- Изоляция ошибок. Если один агент сходит с ума (зацикливается, галлюцинирует, вызывает не тот инструмент), это видно на границе между агентами. В монолитном агенте тот же сбой размазан по одному потоку рассуждений, и найти, где всё пошло не так, труднее.
Ключевое слово здесь — «снижает ошибки за счёт специализации и перепроверки», а не «делает систему умнее». Каждый агент использует ту же модель и те же ограничения, что и раньше. Выигрыш чисто архитектурный.
Паттерн оркестратор-воркеры
Самая распространённая схема мультиагентной системы — не «рой равноправных агентов, договаривающихся между собой», а иерархия с явным управляющим узлом. Она называется orchestrator-workers (оркестратор-воркеры) и выглядит так:
Пользователь → Оркестратор (план, кто что делает)
│
┌───────────┼───────────┐
▼ ▼ ▼
Воркер 1 Воркер 2 Воркер N
│ │ │
└───────────┼───────────┘
▼
Ревьюер (готово / на доработку)
▼
Финальный ответ
Оркестратор — отдельный вызов LLM (часто на более сильной модели), задача которого не «сделать работу», а составить план: разбить запрос на подзадачи и решить, какому воркеру что отдать. Воркеры — агенты с узкой специализацией: один ищет информацию, другой пишет код, третий работает с конкретным API. Ревьюер (иногда тот же оркестратор, иногда отдельный агент) собирает результаты и решает, достаточно ли этого для ответа, или задачу нужно вернуть на доработку с указанием, что именно не так.
Важный нюанс: воркеры между собой напрямую не общаются, весь обмен идёт через оркестратора — это делает систему предсказуемее ценой некоторой гибкости. Более свободные топологии, где агенты договариваются напрямую, тоже существуют, но для большинства задач хватает иерархии с оркестратором — её проще отлаживать и ограничивать в правах.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть LiteLLMРоли: планировщик, исполнитель, проверяющий
Разберём три роли, которые чаще всего встречаются в мультиагентных пайплайнах, на уровне промптов и границ ответственности.
Планировщик (planner). Получает исходную задачу целиком и превращает её в список конкретных шагов с зависимостями между ними. Хороший системный промпт планировщика явно запрещает ему выполнять шаги самому — только раскладывать. Пример структуры вывода:
{
"steps": [
{"id": 1, "agent": "researcher", "task": "найти цены на GPU-серверы у трёх провайдеров", "depends_on": []},
{"id": 2, "agent": "writer", "task": "составить таблицу по данным шага 1", "depends_on": [1]}
]
}
Исполнитель (worker). Получает только свою подзадачу и минимально необходимый контекст, а не всю историю диалога. Это экономит токены и снижает шанс, что модель отвлечётся на нерелевантную часть контекста. У исполнителя обычно есть доступ к tool calling — вызовам внешних API, поиску, коду.
Проверяющий (reviewer / critic). Получает результат исполнителя и исходное задание, но не видит его рассуждений — только финальный вывод. Это принципиально: проверяющий, который видит цепочку мыслей исполнителя, слишком легко соглашается с логикой, которую сам не выстраивал. Ему стоит явно ставить в промпт вопрос «на что обратить внимание при проверке», а не просто «оцени это» — иначе он либо штампует одобрение, либо придирается к мелочам без системы.
Эти три роли необязательно должны быть тремя разными моделями — иногда это один провайдер с разными промптами и температурой. Но развести их по разным моделям (сильная — для планирования и проверки, дешёвая — для исполнения) — это то место, где в игру вступает шлюз вроде LiteLLM, о нём ниже.
Пример: как это работает на конкретной задаче
Возьмём задачу: «подготовить черновик технического поста по логам инцидента на сервере». Без мультиагентной схемы один агент попытается одновременно прочитать логи, понять причину, написать текст и сам же оценить, хорош ли результат, — и на любом из этих шагов легко потерять нить.
С разделением ролей пайплайн выглядит так:
- Оркестратор получает задачу и логи, решает: нужен агент-аналитик, агент-автор и агент-редактор.
- Аналитик вызывает инструмент парсинга логов, находит временные метки сбоя, отдаёт структурированный вывод — не текст, а факты: время, компонент, тип ошибки.
- Автор получает только эти факты (не сырые логи) и пишет связный текст с объяснением причины и хронологией.
- Редактор сверяет текст с фактами от аналитика — проверяет, что автор не добавил ничего лишнего и не перепутал хронологию.
- Если редактор находит расхождение, он возвращает текст автору с конкретным указанием, что исправить: не «перепиши получше», а «в тексте сказано про сбой БД в 14:02, в логах — про таймаут API в 14:07».
- Оркестратор собирает финальную версию и отдаёт пользователю.
Шаг 5 — это и есть та самая перепроверка, ради которой всё затевалось. Агент, который сам написал текст и сам его же оценивает, крайне редко находит в нём подобные расхождения: он уже «решил», что хронология верна, когда её формулировал.
Честная сложность: стоимость, отладка, когда не начинать
Мультиагентная схема не бесплатна, и об этом стоит говорить прямо, а не только в разделе «недостатки» мелким шрифтом.
Количество вызовов модели растёт нелинейно. Одна задача из примера выше — это минимум пять-шесть обращений к LLM вместо одного: план, аналитик, автор, редактор, возможно повторный проход после правок. Каждый вызов — это токены на вход (весь переданный контекст) и на выход. Как считать реальную стоимость таких запросов, мы отдельно разбирали в статье как считать стоимость LLM-запросов на своём сервере — там видно, насколько быстро растёт счёт, если не разделять модели по стоимости под роли.
Отладка сложнее на порядок. В монолитном агенте у вас один лог рассуждений. В мультиагентной системе — граф из N вызовов, и когда результат неверный, нужно понять: сломался ли план, неверно ли исполнил воркер, или проверяющий пропустил ошибку. Без логирования каждого промежуточного вывода — не только финального ответа, а того, что каждый агент передал следующему — разобраться в инциденте постфактум почти невозможно.
Задержка растёт. Шаги обычно идут последовательно (проверка зависит от результата исполнения), поэтому общее время ответа — сумма времени всех агентов в цепочке, а не время одного вызова.
Не всегда оправдано. Если задача решается одним агентом с одним-двумя вызовами инструментов и результат стабильно приемлемый — не нужно городить оркестратора и ревьюера ради архитектурной красоты. Схема окупается там, где цена ошибки высокая (код в прод, текст для клиентов, данные для решений) или роли объективно разные (поиск, код, финальная проверка). Начинайте с одного агента и одного явного цикла tool calling; переходите на мультиагентную схему, когда конкретно увидите, где агент регулярно ошибается, и сможете сформулировать роль, которая эту ошибку ловит.
LiteLLM: единый шлюз для разных моделей и агентов
Как только ролей больше одной, встаёт вопрос: одна модель для всех агентов — это либо переплата (сильная модель на рутинном исполнителе), либо потеря качества (дешёвая модель на планировании и проверке). Разумная практика — назначать модель под роль: сильную и дорогую — планировщику и проверяющему; дешёвую и быструю — исполнителям на рутинных шагах.
У разных провайдеров разные SDK, форматы ответа и способы аутентификации — переключаться между ними в коде каждого агента неудобно. LiteLLM решает это как прокси-шлюз: модели описываются один раз в конфиге на сервере, а каждый агент обращается к одному OpenAI-совместимому эндпоинту, указывая нужный алиас.
Конфиг шлюза под сценарий из примера выше может выглядеть так:
model_list:
- model_name: planner
litellm_params: {model: anthropic/claude-opus-4, api_key: os.environ/ANTHROPIC_API_KEY}
- model_name: reviewer
litellm_params: {model: anthropic/claude-opus-4, api_key: os.environ/ANTHROPIC_API_KEY}
- model_name: worker-fast
litellm_params: {model: openai/gpt-4o-mini, api_key: os.environ/OPENAI_API_KEY}
general_settings:
master_key: sk-litellm-internal
А код каждого агента после этого одинаковый вне зависимости от того, какая модель у него под алиасом — меняется только строка model:
import openai
client = openai.OpenAI(base_url="http://localhost:4000", api_key="sk-litellm-internal")
response = client.chat.completions.create(
model="worker-fast", # у оркестратора будет model="planner"
messages=[{"role": "user", "content": task_payload}],
)
Практическая выгода для мультиагентной системы — в трёх вещах:
- Один код агента, разные модели. Если появится модель выгоднее для роли исполнителя, меняется одна строка в конфиге шлюза, а не код каждого агента.
- Единый учёт стоимости и лимитов. LiteLLM ведёт биллинг и rate limiting по ключам и алиасам моделей — видно, сколько токенов ушло именно на роль «воркер», а сколько на «планировщик».
- Fallback под контролем. Если провайдер недоступен, в конфиге можно настроить переключение на другую модель без изменения кода агентов.
Пошаговую установку самого шлюза мы разбирали в статье как установить и настроить LiteLLM на VPS. Если вместо голого кода вам ближе агентный фреймворк с оркестрацией из коробки, у нас есть разбор как поднять агента на LangChain на сервере — LiteLLM встраивается туда так же, через смену base_url.
Сам шлюз стоит держать на отдельном сервере, а не рядом с кодом агентов — так проще масштабировать воркеров и не терять доступ к моделям при перезапуске основного приложения.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть LiteLLMОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
С скольки агентов начинается «мультиагентная система»?
Формально с двух, но практический смысл появляется от трёх ролей: кто-то планирует, кто-то исполняет, кто-то проверяет. Два агента без явного разделения «исполнитель / контролёр» чаще всего можно заменить одним с более длинным промптом.
Нужен ли оркестратор, если ролей всего две?
Не обязательно — можно вызывать агентов последовательно прямо из кода. Оркестратор как отдельный вызов модели оправдан, когда набор шагов заранее не фиксирован и подбирается под конкретный запрос.
Можно ли обойтись без LiteLLM и вызывать API моделей напрямую?
Можно, особенно если все агенты сидят на одном провайдере. Шлюз полезен, когда провайдеров несколько, нужен единый учёт стоимости по ролям или хочется менять модель под ролью без правки кода.
Мультиагентная система всегда точнее одного агента?
Нет. Она снижает определённый класс ошибок (самопроверка, смешение ролей в промпте) ценой стоимости и задержки. Если у одного агента и так стабильный результат, добавление ролей может не окупиться и добавить новые точки отказа на стыках между агентами.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.