Думать и делать — разные роли
LLM умеет рассуждать и писать код, но не умеет его выполнять — у неё нет интерпретатора. А без выполнения нельзя узнать, работает ли решение: модель уверенно напишет функцию с багом и не заметит. Нужен кто-то, кто реально запустит код и вернёт результат — тогда автор увидит ошибку и исправит.
AutoGen разводит это на две роли (привет уроку про разделение ответственности):
- AssistantAgent — «мозг». Думает, рассуждает, пишет код. Использует LLM, кода не выполняет.
- UserProxyAgent — «руки» и представитель человека. Выполняет код, возвращает результат, при необходимости спрашивает человека. LLM ему обычно не нужен.
Оба — это ConversableAgent из прошлого урока с предустановленными настройками. AssistantAgent приходит с готовым системным промптом «решай задачи, пиши код в блоках»; UserProxyAgent — с включённым выполнением кода и режимом запроса человека. Их связка через initiate_chat и есть классический паттерн AutoGen.
Имя сбивает с толку: UserProxyAgent — это не «агент-пользователь», а прокси (заместитель) человека в разговоре. Он действует от лица пользователя: выполняет то, что предложил ассистент, и при настройке human_input_mode может в любой момент передать слово реальному человеку. По сути — мост между LLM-ассистентом и реальным миром (код, файлы, человек).
Цикл «решение → выполнение → правка»
Магия паттерна — в их диалоге. UserProxy ставит задачу → Assistant пишет код → UserProxy его выполняет и возвращает вывод (или ошибку) → Assistant, увидев результат, исправляет или подтверждает. Цикл повторяется, пока задача не решена.
Это и есть заземление рассуждений на реальность: ассистент не «думает, что код верный», а узнаёт это из настоящего вывода интерпретатора. По сути — тот же verifier из урока про проверку и критику, только проверка объективная (запуск кода), а не мнение.
AssistantAgent: мозг
AssistantAgent — это ConversableAgent с готовым системным промптом, который велит решать задачи и оформлять код в markdown-блоках. По умолчанию он сам код не выполняет (human_input_mode="NEVER", без code execution) — его дело думать и писать.
from autogen import AssistantAgent
llm_config = {"model": "gpt-4o-mini", "api_key": "sk-..."}
assistant = AssistantAgent(
name="assistant",
llm_config=llm_config,
# системный промпт уже встроен: "решай задачи, код — в блоках,
# в конце ответь TERMINATE". Можно переопределить system_message.
)
UserProxyAgent: руки и человек
UserProxyAgent — тоже ConversableAgent, но настроенный на действие: он умеет выполнять код из сообщений ассистента и представлять человека. LLM ему обычно не нужен (llm_config=False) — он не генерирует текст, а исполняет.
from autogen import UserProxyAgent
user_proxy = UserProxyAgent(
name="user_proxy",
human_input_mode="NEVER", # NEVER — автономно; ALWAYS — спрашивать
max_consecutive_auto_reply=10, # предохранитель: автоответов подряд
is_termination_msg=lambda m: "TERMINATE" in (m.get("content") or ""),
code_execution_config={ # ГДЕ и КАК выполнять код
"work_dir": "coding", # рабочая папка
"use_docker": False, # True — изолированно в Docker (безопаснее)
},
llm_config=False, # ему не нужна модель — он исполнитель
)
Ключевой параметр — code_execution_config: он включает выполнение кода и говорит, где его запускать. Поставь False — и прокси перестанет исполнять код (станет просто мостом к человеку). human_input_mode управляет участием человека: "NEVER" — полностью автономно, "ALWAYS" — спрашивать на каждом ходу, "TERMINATE" — только перед завершением.
UserProxyAgent запускает код, который придумала модель. Без изоляции это опасно: галлюцинированная команда может удалить файлы или утечь данными. На проде включай use_docker=True (выполнение в контейнере) и не давай прокси доступ к чувствительному окружению. Это прямое продолжение урока про approval workflows: опасные действия — под контролем.
Полный пример: пара решает задачу
from autogen import AssistantAgent, UserProxyAgent
llm_config = {"model": "gpt-4o-mini", "api_key": "sk-..."}
assistant = AssistantAgent(name="assistant", llm_config=llm_config)
user_proxy = UserProxyAgent(
name="user_proxy",
human_input_mode="NEVER",
max_consecutive_auto_reply=10,
is_termination_msg=lambda m: "TERMINATE" in (m.get("content") or ""),
code_execution_config={"work_dir": "coding", "use_docker": False},
)
# UserProxy инициирует разговор — ставит задачу ассистенту
user_proxy.initiate_chat(
assistant,
message="Посчитай 10-е число Фибоначчи. Напиши и запусти код.",
)
# Что произойдёт автоматически:
# 1. user_proxy → assistant: задача
# 2. assistant → user_proxy: ```python ...код фибоначчи...```
# 3. user_proxy ВЫПОЛНЯЕТ код, возвращает вывод (например, 55)
# 4. assistant видит результат, проверяет, отвечает "... TERMINATE"
# 5. разговор завершается по is_termination_msg
Заметь: инициирует разговор обычно user_proxy (он представляет пользователя с задачей), а assistant отвечает. Весь цикл код→выполнение→правка крутится сам, без твоего участия, пока ассистент не скажет TERMINATE или не упрётся в max_consecutive_auto_reply.
Человек в цикле через прокси
Поскольку UserProxy представляет человека, через него легко вернуть человека в контур. Достаточно сменить режим — и перед выполнением кода (или вместо автоответа) система спросит реального пользователя.
# Полная автономия — ничего не спрашивает (демо, доверенные задачи)
UserProxyAgent(name="up", human_input_mode="NEVER", ...)
# Человек подтверждает каждый ход — максимум контроля
UserProxyAgent(name="up", human_input_mode="ALWAYS", ...)
# Спросить только перед завершением — компромисс
UserProxyAgent(name="up", human_input_mode="TERMINATE", ...)
human_input_mode="ALWAYS" — прямой аналог interrupt_before из модуля 03: перед действием система отдаёт ход человеку. Для рискованных операций (выполнение кода, обращение к боевым системам) ставь ALWAYS или TERMINATE, для безопасных демо — NEVER. Контур человека встроен в паттерн by design — в этом сила связки с прокси.
Типичные ошибки
Код пишет LLM — он может быть опасен. Без use_docker=True или другой песочницы прокси выполнит что угодно прямо в твоём окружении. На проде — изоляция обязательна.
UserProxy — исполнитель, ему обычно не нужна модель. Лишний llm_config заставит его генерировать текст и тратить токены вместо простого выполнения. Ставь llm_config=False.
Без max_consecutive_auto_reply и условия завершения пара может «чинить код» бесконечно. Задавай оба: лимит как предохранитель и TERMINATE как осмысленный выход.
Обычно разговор начинает user_proxy (он несёт задачу пользователя), а ассистент отвечает. Перепутаешь — поток получится неестественным. Инициатор = тот, у кого задача.
Шпаргалка
from autogen import AssistantAgent, UserProxyAgent
# РАЗДЕЛЕНИЕ РОЛЕЙ:
# AssistantAgent — «мозг»: думает, пишет код (llm_config = {...})
# UserProxyAgent — «руки» + человек: выполняет код (llm_config = False)
assistant = AssistantAgent(name="assistant", llm_config=llm_config)
user_proxy = UserProxyAgent(
name="user_proxy",
human_input_mode="NEVER", # NEVER | ALWAYS | TERMINATE
max_consecutive_auto_reply=10, # предохранитель
is_termination_msg=lambda m: "TERMINATE" in (m.get("content") or ""),
code_execution_config={"work_dir": "coding", "use_docker": True}, # ИЗОЛЯЦИЯ!
llm_config=False,
)
# Прокси (с задачей) инициирует разговор:
user_proxy.initiate_chat(assistant, message="Реши задачу, напиши и запусти код.")
# ЦИКЛ: assistant пишет код → user_proxy выполняет → assistant правит по выводу
# Правила:
# • код от LLM → выполнять В ИЗОЛЯЦИИ (use_docker=True)
# • прокси-исполнителю → llm_config=False
# • ВСЕГДА предел: max_consecutive_auto_reply + is_termination_msg
# • инициирует тот, у кого задача (обычно user_proxy)
# • human_input_mode = AutoGen-версия human-in-the-loop
Практическое задание
Собери классическую пару AutoGen:
Задание: пара «ассистент + прокси» решает задачу с кодом
- Создай
AssistantAgentиUserProxyAgentсcode_execution_config(для учёбы можноuse_docker=False, но осознавай риск). - Запусти через
user_proxy.initiate_chatзадачу, требующую кода: «построй график функции и сохрани в png» или «посчитай статистику по списку чисел». - Проследи по логу цикл: код → выполнение → (ошибка → правка) → результат →
TERMINATE. Найди момент, где ассистент исправился по реальному выводу. - Намеренно усложни задачу так, чтобы первый код упал, и убедись, что ассистент чинит его по сообщению об ошибке от прокси.
- Поменяй
human_input_modeна"ALWAYS"и поучаствуй: подтверждай или правь действия прокси вручную. Сравни с автономным режимом. - Со звёздочкой: включи
use_docker=Trueи объясни, какие риски это снимает; подумай, какие операции ты бы вообще запретил прокси выполнять.
Что дальше
Пара «ассистент + прокси» — это диалог двоих. Но часто нужно больше участников: писатель, критик, исполнитель — все в одном обсуждении. За координацию многих агентов в AutoGen отвечает GroupChat — следующий урок.