AutoGen: диалог агентов и когда он выходит из-под контроля
Вы дали одному агенту задачу — он выдал решение с первого раза, и оно посредственное: пропустил edge-case, не учёл ограничение, написал код без обработки ошибок. AutoGen предлагает другой подход: пусть агенты обсудят решение между собой, один покритикует другого, тот доработает — и на выходе получится результат лучше, чем с одного захода. Это работает, но у свободного диалога агентов есть обратная сторона: без жёстких ограничений он не гарантированно завершается, и на собственном железе это означает не абстрактный риск, а вполне конкретный счёт за электричество и часы простоя сервера.
Содержание
- Что такое AutoGen и чем он отличается от простого запроса
- Модель диалога: генерация — критика — доработка
- Минимальный пример: два агента и одна задача
- Главный риск: диалог, который не сходится
- Практические меры защиты от зацикливания
- Развёртывание на сервере: на что смотреть
- С чего начать: тестируйте на простых задачах прежде чем доверять автономный запуск
Что такое AutoGen и чем он отличается от простого запроса
AutoGen — фреймворк для организации диалога между несколькими ИИ-агентами, изначально разработанный в Microsoft Research и позже развившийся в отдельный открытый проект с активным сообществом. Базовая идея простая: вместо одного запроса к одной модели вы создаёте несколько агентов с разными ролями (например, «исполнитель» и «критик») и запускаете их в цикл обмена сообщениями. Один агент генерирует ответ, второй его разбирает и указывает на слабые места, первый учитывает замечания и выдаёт новую версию — и так по кругу, пока задача не будет решена или пока не сработает ограничение.
Ключевое отличие от паттерна «оркестратор — фиксированные роли — воркеры» (по этому принципу строятся многие мультиагентные системы, где каждый агент отвечает за свой чётко очерченный участок работы) в том, что в AutoGen акцент сделан именно на свободной модели диалога: агенты не просто передают задачу по цепочке от одного к другому, а ведут содержательное обсуждение с возможностью многократно возвращаться к одному и тому же вопросу, спорить, уточнять и поправлять друг друга. Про общий принцип разделения агентов на роли и оркестрацию воркеров можно почитать в статье про мультиагентные системы с несколькими LLM-агентами — там разобран более структурированный подход, тогда как AutoGen ближе к модели «сядьте и договоритесь».
Технически AutoGen построен вокруг понятия conversable agent — агента, который умеет отправлять и принимать сообщения в общем чате. Есть несколько готовых типов: AssistantAgent (на базе LLM, выполняет содержательную работу), UserProxyAgent (может представлять человека или выполнять код от его имени, в том числе автоматически исполнять сгенерированный код и возвращать результат в диалог), и GroupChat с GroupChatManager — для сценариев с более чем двумя участниками, где менеджер решает, кто говорит следующим.
Модель диалога: генерация — критика — доработка
Практический сценарий, ради которого чаще всего разворачивают AutoGen, выглядит так:
- Агент А получает задачу (написать функцию, составить план, сформулировать текст) и выдаёт первую версию решения.
- Агент Б (критик) разбирает решение построчно и формулирует конкретные замечания: «здесь не обработана пустая строка на входе», «этот план не учитывает откат при сбое на шаге 3», «формулировка двусмысленная — уточните единицы измерения».
- Агент А получает замечания в виде очередного сообщения в диалоге и выдаёт исправленную версию, отталкиваясь именно от указанных проблем, а не начиная с нуля.
- Цикл повторяется: критик снова проверяет, теперь уже доработанную версию, находит новые (или те же оставшиеся) проблемы, агент А снова правит.
Идея в том, что качество итогового результата — версии решения после нескольких раундов правок — в среднем выше, чем качество единственного ответа без возможности итерации. Модель как бы проверяет сама себя дважды разными «ролями»: одна оптимизирована на генерацию, вторая — на придирчивую проверку. Особенно это заметно там, где ошибка первого прохода носит структурный характер (пропущенный сценарий, забытое ограничение) — критик такие вещи ловит охотнее, чем модель сама у себя при повторном чтении собственного текста в рамках одного запроса.
Важная оговорка: это не гарантия качества, а вероятностное улучшение. Диалог может как довести решение до годного состояния за 2-3 раунда, так и застрять — и вот тут начинается тема, вынесенная в заголовок статьи.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть ИИ на сервереМинимальный пример: два агента и одна задача
Ниже — упрощённый скелет диалога на Python (без реальных ключей API, только структура):
import autogen
config_list = [
{
"model": "gpt-4", # или локальная модель через совместимый endpoint
"api_key": "ВАШ_КЛЮЧ",
}
]
assistant = autogen.AssistantAgent(
name="исполнитель",
llm_config={"config_list": config_list},
system_message="Ты пишешь код по задаче. Учитывай замечания критика."
)
critic = autogen.AssistantAgent(
name="критик",
llm_config={"config_list": config_list},
system_message=(
"Ты придирчиво проверяешь код на ошибки, edge-case и производительность. "
"Если код полностью решает задачу без замечаний — напиши ЗАВЕРШЕНО и ничего больше."
)
)
user_proxy = autogen.UserProxyAgent(
name="proxy",
human_input_mode="NEVER",
max_consecutive_auto_reply=10, # жёсткий потолок раундов — см. следующую секцию
code_execution_config={"work_dir": "coding", "use_docker": False},
is_termination_msg=lambda msg: "ЗАВЕРШЕНО" in msg.get("content", "")
)
user_proxy.initiate_chat(
assistant,
message="Напиши функцию, которая парсит CSV с датами в разных форматах."
)
Обратите внимание на два параметра в примере — max_consecutive_auto_reply и is_termination_msg. Это не второстепенные детали, а именно те два рычага, без которых диалог может не остановиться сам.
Главный риск: диалог, который не сходится
Вот в чём суть проблемы, ради которой стоит читать эту статью до конца, а не только смотреть на пример кода выше. Свободный диалог между агентами — в отличие от одного запроса с одним ответом — не имеет встроенной точки завершения. Люди в реальном обсуждении интуитивно чувствуют, когда пора остановиться («ладно, вроде договорились»), у языковой модели этого чувства нет — есть только текст предыдущих сообщений и вероятностная генерация следующего.
Конкретный паттерн, который реально встречается на практике: агент-критик просит уточнить формулировку задачи или указывает на неоднозначность, агент-исполнитель отвечает почти тем же самым уточнением, которое уже давал раньше (модель «забыла» или не восприняла ответ как достаточный), критик снова просит уточнить — почти теми же словами, — и так далее. Реального прогресса нет: сообщения меняются лексически, но по сути диалог топчется на месте. Без внешнего ограничителя такой обмен репликами может продолжаться десятками раундов, а в худшем случае — пока не кончится контекстное окно модели или бюджет на API-вызовы.
Почему это не абстрактная теоретическая проблема, а практический риск именно при развёртывании на своём железе: каждый раунд диалога — это минимум два полных вызова модели (исполнитель и критик), и каждый вызов передаёт всю историю диалога целиком — по мере роста числа раундов растёт не только их количество, но и объём данных, обрабатываемых на каждом шаге. На VPS с ограниченной пропускной способностью и на локальной модели с ограниченными ресурсами GPU/CPU это означает, что зациклившийся диалог агентов буквально держит сервер загруженным без пользы. Похожий сценарий — только с одним автономным агентом вместо диалога двух — уже разбирался в статье «ИИ-агент зациклился и сжёг лимиты за ночь»: тот же общий принцип — автономный процесс без жёсткого потолка шагов способен расходовать ресурсы гораздо дольше, чем предполагалось при запуске, и обнаруживается это обычно постфактум, по счёту или по нагрузке.
Практические меры защиты от зацикливания
Ниже — набор мер, которые стоит закладывать в дизайн диалога агентов с самого начала, а не добавлять постфактум после первого инцидента.
1. Обязательный жёсткий потолок числа раундов. Это не рекомендация, а требование к любому production-развёртыванию диалога агентов. В AutoGen для этого есть параметр max_consecutive_auto_reply у ConversableAgent/UserProxyAgent — при достижении лимита диалог принудительно прерывается независимо от того, «договорились» агенты между собой или нет:
user_proxy = autogen.UserProxyAgent(
name="proxy",
max_consecutive_auto_reply=8,
human_input_mode="NEVER",
)
Конкретное число зависит от задачи — для простых правок хватает 3-5 раундов, для сложных многошаговых задач может понадобиться 10-15. Начинайте с меньшего значения и увеличивайте по мере накопления данных о реальных потребностях, а не наоборот.
2. Явные критерии завершения для самих агентов. Помимо технического потолка раундов, дайте агентам понятный сигнал «задача решена, продолжать не нужно». В примере выше это функция is_termination_msg, которая проверяет наличие ключевого слова (например, «ЗАВЕРШЕНО») в сообщении критика — и системный промпт критика прямо инструктирует: если замечаний нет, написать это слово и ничего больше. Без такой явной инструкции критик может по инерции продолжать искать всё более мелкие и надуманные придирки просто потому, что диалог продолжается, а модели «положено» отвечать содержательно.
3. Мониторинг реального числа итераций в продакшене. Не полагайтесь только на то, что лимит есть — собирайте метрику фактического числа раундов до завершения диалога по каждой задаче. Если заметная доля диалогов регулярно упирается именно в максимальный лимит (а не завершается раньше по критерию «задача решена») — это тревожный сигнал: либо лимит подобран слишком консервативно для реальной сложности задач, либо (что чаще) сама постановка задачи для агентов сформулирована нечётко, и агенты физически не могут договориться, потому что не знают, что именно считается «готово». Второй случай не лечится увеличением лимита — там нужно переформулировать задачу и/или системные промпты агентов.
4. Ограничение по времени и токенам как второй рубеж. Жёсткий потолок раундов — обязательный минимум, но полезно дублировать его ограничением по суммарному числу токенов диалога или по времени выполнения (например, через timeout на уровне процесса или обёртку с asyncio.wait_for), особенно если один раунд может неожиданно оказаться очень длинным (агент генерирует избыточно подробный ответ).
Таблица ниже суммирует, какой параметр за что отвечает:
| Механизм | Что ограничивает | Где настраивается |
|---|---|---|
max_consecutive_auto_reply | Число раундов диалога | На уровне агента (ConversableAgent) |
is_termination_msg | Досрочное завершение по смысловому критерию | Функция-предикат при создании агента |
| Лимит токенов на диалог | Совокупный объём переданных данных | Обёртка вокруг вызова API / логика в коде |
| Таймаут по времени | Общее время выполнения задачи | Уровень процесса / оркестратора |
Развёртывание на сервере: на что смотреть
Диалог агентов удобно тестировать локально, но production-запуск на своём железе требует внимания к нескольким практическим вещам:
- Изоляция выполнения кода. Если используете
UserProxyAgentсcode_execution_configи разрешаете агентам выполнять сгенерированный код, обязательно указывайтеuse_docker=True(или эквивалентную изоляцию) — агент может сгенерировать код, который случайно удалит файлы или займёт все ресурсы процесса. На production-сервере это обязательное требование, а не опция. - Логирование каждого сообщения диалога в постоянное хранилище, а не только в консоль — при разборе инцидента с зацикливанием нужна будет полная история, кто что сказал и на каком раунде.
- Отдельный процесс/контейнер под каждую задачу, если задач параллельно много — чтобы один зациклившийся диалог не забирал ресурсы у остальных.
- Ограничение параллельных диалогов на уровне очереди задач — суммарная нагрузка на сервер растёт нелинейно, если каждый из многих одновременных диалогов сам по себе умножает число вызовов модели на число раундов.
Если модель разворачивается локально (а не через облачный API), стоит заранее прикинуть требования к ресурсам — про это в целом можно почитать в статье про настройку агента на LangChain на сервере, где разбираются похожие вопросы по ресурсам и подключению модели, хотя сам фреймворк там другой.
С чего начать: тестируйте на простых задачах прежде чем доверять автономный запуск
Самая практичная рекомендация перед тем, как отдавать диалог агентов на реальную production-нагрузку без присмотра: начните с простых, контролируемых задач с заведомо понятным и проверяемым результатом. Например, попросите пару агентов сгенерировать и раскритиковать реализацию одной небольшой функции с чёткими тест-кейсами — вы сможете вручную проверить, сколько раундов реально потребовалось, где критик давал полезные замечания, а где начинал повторяться, и подобрать разумный max_consecutive_auto_reply на основе наблюдаемого поведения, а не на глаз.
Только после того как вы своими глазами увидели десяток-другой завершённых диалогов на контролируемых задачах — и убедились, что лимиты срабатывают адекватно, а критерий завершения формулируется агентами корректно, — имеет смысл подключать production-задачи и, тем более, оставлять систему работать без присмотра. Пропуск этого шага — самый частый источник историй вида «запустили диалог агентов на ночь, а утром обнаружили сожжённый бюджет и диалог, который двадцать раз пересказал одну и ту же мысль другими словами».
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть ИИ на сервереНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Чем AutoGen принципиально отличается от простого чата с двумя системными промптами?
Формально можно эмулировать похожее поведение вручную, но AutoGen даёт готовую инфраструктуру: управление ролями, автоматическое исполнение кода агентом, встроенные механизмы ограничения раундов (max_consecutive_auto_reply) и завершения (is_termination_msg), поддержку групповых чатов с несколькими участниками через GroupChat. Для одноразового эксперимента разница невелика, для регулярного production-использования — существенна, потому что не нужно писать эту инфраструктуру самому.
Можно ли использовать AutoGen с локальной моделью вместо облачного API?
Да, AutoGen поддерживает подключение к любому OpenAI-совместимому endpoint, включая локально развёрнутые модели через инструменты вроде vLLM или совместимые обёртки. Именно в этом сценарии риск зацикливания ощущается острее всего — на своём железе с ограниченной производительностью зациклившийся диалог не абстрактно «стоит денег», а физически занимает ресурсы, которые могли бы обслуживать другие задачи.
Сколько раундов диалога нормально для типовой задачи?
Точных универсальных цифр никто не даст — сильно зависит от сложности задачи и качества системных промптов, поэтому воспринимайте любые конкретные числа как ориентир, а не норматив. На практике простые задачи (правка одной функции, короткий текст) обычно укладываются в 3-6 раундов; если у вас систематически уходит 15+ раундов на простую задачу — это чаще признак нечёткого критерия завершения, чем сложности самой задачи.
Что делать, если лимит раундов постоянно достигается, но задача не решена?
Не увеличивайте лимит первым делом. Сначала проверьте системные промпты обоих агентов на предмет чёткости критерия «задача решена» — часто выясняется, что критик и исполнитель по-разному понимают требования, и увеличение числа раундов эту разницу не устранит.
Нужен ли Docker для выполнения кода агентами обязательно, или можно без него в тестах?
В локальных экспериментах на своей машине можно временно обойтись без Docker (параметр use_docker=False), но на production-сервере, тем более при автономном запуске без присмотра, изоляция выполнения кода — обязательная мера безопасности, а не опциональная.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →