Почему один агент — это как программист-одиночка, а мультиагент — это целая студия
Представьте: вы даете задачу одной LLM. Она пишет код, иногда хорошо, иногда криво. Вы проверяете, исправляете, снова запускаете. Цикл повторяется. Это как работать с junior-разработчиком, который никогда не становится senior.
Теперь представьте другую картину: одна модель разбивает задачу на подзадачи. Другие модели параллельно пишут код для каждой части. Третьи проверяют результат. Четвертые тестируют. Это уже не junior, это распределенная команда экспертов.
Вот в чем проблема большинства AI-кодинговых систем на начало 2026 года: они используют одну модель для всего. Даже если это мощная модель вроде Claude 3.7 Sonnet или GPT-4.5 Turbo, она все равно ограничена одним контекстом, одним подходом, одним стилем мышления.
Ключевое заблуждение: «Чем мощнее модель, тем лучше код». На практике три средние модели, работающие в правильной архитектуре, часто дают результат лучше, чем одна супермодель.
Архитектура, которая не сломается после первого же сложного проекта
Давайте сразу отбросим наивные схемы. Нет, просто запустить несколько агентов параллельно — не решение. Они начнут конфликтовать, дублировать код, писать несовместимые интерфейсы.
Нужна иерархия. Нужны четкие роли. Нужен контроль качества на каждом этапе.
Вот архитектура, которая работает в продакшене:
| Компонент | Роль | Модель (пример на 2026) |
|---|---|---|
| Оркестратор | Разбивает задачу, распределяет, контролирует выполнение | Claude 3.7 Sonnet (высокий контекст, стратегическое мышление) |
| Spawn Worker | Создает экземпляры воркеров под конкретные подзадачи | GPT-4.5 Turbo (быстрое выполнение стандартных задач) |
| Кодеры (воркеры) | Пишут конкретные модули кода | DeepSeek Coder V3, CodeLlama 70B, WizardCoder 34B |
| Ревьюеры | Проверяют качество, стиль, безопасность | Sonnet для архитектуры, GPT для безопасности, локальная модель для стиля |
| Тестеры | Пишут и запускают тесты | Специализированные coding-модели с фокусом на тестирование |
Звучит сложно? Это потому, что это действительно сложно. Но настраивается один раз, а работает годами.
1 Ставим Opencode и готовим инфраструктуру
Opencode — не самый популярный фреймворк, и в этом его плюс. Он не перегружен абстракциями, как некоторые оркестраторы кода, но дает достаточно контроля.
Первая ошибка, которую делают 90% разработчиков: пытаются запустить все на одной машине. Даже если у вас RTX 6000 Pro Blackwell 96GB (о выборе моделей для таких карт я писал в отдельном гайде), разделяйте нагрузки.
# Установка Opencode (версия 2.3.1 на январь 2026)
git clone https://github.com/opencode-ml/opencode.git
cd opencode
pip install -e .
# Отдельный сервер для оркестратора
docker run -d --name opencode-orchestrator \
-p 8000:8000 \
-v /path/to/models:/models \
opencode/orchestrator:2.3
# Сервер для воркеров (можно несколько инстансов)
docker run -d --name opencode-workers \
-p 8001:8001 \
--gpus all \
-v /path/to/worker-models:/models \
opencode/worker:2.3
2 Пишем оркестратор, который не тупит на сложных задачах
Оркестратор — мозг системы. Если он глупый, вся система будет глупой.
Вот как НЕ надо делать:
# ПЛОХО: наивный оркестратор
async def handle_task(task):
# Просто отправляем задачу всем воркерам
workers = get_all_workers()
results = await asyncio.gather(*[w.process(task) for w in workers])
return random.choice(results) # 🤦♂️
А вот минимальный рабочий оркестратор:
# ХОРОШО: умное распределение задач
class SmartOrchestrator:
def __init__(self):
self.llm = OpenAI(model="claude-3.7-sonnet") # Или локальная модель
self.worker_pool = WorkerPool()
self.task_history = []
async def decompose_task(self, task_description):
"""Разбивает задачу на подзадачи с учетом зависимостей"""
prompt = f"""
Задача: {task_description}
Разбей на подзадачи, которые можно выполнять параллельно или последовательно.
Укажи зависимости между подзадачами.
Для каждой подзадачи определи:
1. Тип (API, база данных, UI, бизнес-логика и т.д.)
2. Сложность (1-5)
3. Ожидаемый объем кода
4. Подходящий тип воркера
"""
decomposition = await self.llm.complete(prompt)
return self._parse_decomposition(decomposition)
async def assign_subtasks(self, subtasks):
"""Распределяет подзадачи по воркерам"""
assignments = []
for subtask in subtasks:
# Выбираем воркера не просто по очереди, а по компетенциям
suitable_workers = await self.find_suitable_workers(subtask)
if not suitable_workers:
# Создаем нового воркера через spawn worker
new_worker = await self.spawn_worker_for_subtask(subtask)
suitable_workers = [new_worker]
# Балансировка нагрузки
worker = self.select_least_busy(suitable_workers)
assignments.append((subtask, worker))
return assignments
Ключевой момент: оркестратор должен понимать зависимости между задачами. Нельзя начать писать клиент, пока не готов API. Нельзя тестировать, пока нет кода.
3 Spawn Worker: фабрика воркеров по требованию
Spawn Worker — это отдельный сервис, который создает специализированных воркеров под конкретные задачи. Не нужно держать 100 воркеров в памяти, создаем когда нужно.
Архитектура похожа на то, как Джефф Эмануэль управляет 20+ агентами, но адаптирована для кодирования.
class SpawnWorker:
"""Создает воркеров с нужными моделями и конфигурациями"""
MODEL_MAP = {
"api": "gpt-4.5-turbo", # Для API хорошо подходит GPT
"database": "claude-3.7-haiku", # Для схем БД — Claude
"frontend": "codellama-70b", # Для фронтенда — CodeLlama
"testing": "wizardcoder-34b", # Для тестов — WizardCoder
"security": "gpt-4.5-turbo", # Для проверки безопасности
}
async def spawn(self, task_type, complexity):
"""Создает воркера под задачу"""
# Выбираем модель по типу задачи
model_name = self.MODEL_MAP.get(task_type, "gpt-4-turbo")
# Настраиваем параметры генерации в зависимости от сложности
generation_config = {
"temperature": 0.7 if complexity > 3 else 0.3,
"max_tokens": 4000 if complexity > 3 else 2000,
"top_p": 0.95,
}
# Создаем промпт-шаблон для этого типа задач
system_prompt = self._create_system_prompt(task_type)
# Запускаем контейнер с воркером
worker_id = await self._start_worker_container(
model_name=model_name,
config=generation_config,
system_prompt=system_prompt
)
# Регистрируем воркера в оркестраторе
await self._register_worker(worker_id, task_type)
return worker_id
def _create_system_prompt(self, task_type):
"""Создает специализированный системный промпт"""
prompts = {
"api": "Ты — senior backend разработчик...",
"database": "Ты — эксперт по проектированию БД...",
"testing": "Ты пишешь тесты с coverage > 90%...",
}
return prompts.get(task_type, "Ты — опытный разработчик...")
Не создавайте воркеров с одинаковыми промптами для разных задач. Frontend-разработчик и database-архитектор думают по-разному. Их системные промпты должны отражать эту разницу.
4 Система ревью: три уровня проверки вместо «авось сойдет»
Большинство мультиагентных систем падают на качестве кода. Воркеры пишут, оркестратор собирает — получается каша.
Нужна многоуровневая система ревью:
- Архитектурный ревью — проверяет, что все модули стыкуются, интерфейсы совместимы, нет циклических зависимостей. Используем модель с большим контекстом (Claude 3.7 Sonnet).
- Code style ревью — проверяет соответствие PEP8, соглашениям именования, структуре проекта. Можно использовать легкую локальную модель.
- Security ревью — ищет уязвимости, инъекции, проблемы с безопасностью. Специализированная модель или статический анализатор.
class ReviewSystem:
"""Координирует проверки кода"""
async def review_code(self, code_chunks, task_description):
"""Проводит многоуровневый ревью"""
results = {
"architectural": None,
"style": None,
"security": None,
}
# Параллельные проверки
async with asyncio.TaskGroup() as tg:
# Архитектурный ревью
arch_task = tg.create_task(
self.architectural_review(code_chunks, task_description)
)
# Code style ревью
style_task = tg.create_task(
self.style_review(code_chunks)
)
# Security ревью
security_task = tg.create_task(
self.security_review(code_chunks)
)
# Собираем результаты
results["architectural"] = arch_task.result()
results["style"] = style_task.result()
results["security"] = security_task.result()
# Принимаем решение
return self._make_decision(results)
async def architectural_review(self, code_chunks, task_description):
"""Проверяет архитектурную целостность"""
# Объединяем весь код для анализа
full_code = "\n\n".join(code_chunks)
prompt = f"""
Задача: {task_description}
Код:
{full_code}
Проверь:
1. Все ли модули стыкуются по интерфейсам?
2. Есть ли циклические зависимости?
3. Соответствует ли архитектура изначальным требованиям?
4. Можно ли улучшить структуру?
"""
# Используем модель с большим контекстом
reviewer = OpenAI(model="claude-3.7-sonnet", max_tokens=2000)
return await reviewer.complete(prompt)
Важный нюанс: ревьюеры не должны быть теми же моделями, что и воркеры. Иначе получится «сам себя не осудишь».
5 Собираем все вместе: конфигурация для продакшена
Теперь нужно связать все компоненты. Вот docker-compose.yml для полноценной системы:
version: '3.8'
services:
# Оркестратор
orchestrator:
image: opencode/orchestrator:2.3
ports:
- "8000:8000"
volumes:
- ./orchestrator-config.yaml:/config.yaml
- ./models:/models
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
# Spawn Worker
spawn-worker:
image: opencode/spawn-worker:2.3
ports:
- "8001:8001"
volumes:
- ./worker-models:/models
environment:
- ORCHESTRATOR_URL=http://orchestrator:8000
depends_on:
- orchestrator
# Репозиторий для кода
code-repo:
image: gitea/gitea:latest
ports:
- "3000:3000"
volumes:
- ./code-data:/data
# Мониторинг
monitoring:
image: grafana/grafana:latest
ports:
- "3001:3000"
depends_on:
- prometheus
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
И конфигурация оркестратора:
# orchestrator-config.yaml
models:
orchestrator: "claude-3.7-sonnet"
spawn_decider: "gpt-4.5-turbo"
worker_types:
api:
model: "gpt-4.5-turbo"
max_instances: 5
timeout: 300
frontend:
model: "codellama-70b"
max_instances: 3
timeout: 400
testing:
model: "wizardcoder-34b"
max_instances: 4
timeout: 200
review:
architectural:
model: "claude-3.7-sonnet"
required: true
style:
model: "llama-3.1-8b" # Легкая локальная модель
required: true
security:
model: "gpt-4.5-turbo"
required: true
logging:
level: "INFO"
file: "/var/log/opencode/orchestrator.log"
metrics:
prometheus: true
port: 9090
Ошибки, которые сломают вашу систему (и как их избежать)
За 2 года работы с мультиагентными системами я видел одни и те же ошибки снова и снова.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Все воркеры используют одну модель | Система теряет разнообразие подходов. Как команда из клонов. | Специализируйте модели под задачи. Для API — одна модель, для БД — другая. |
| Нет обратной связи от ревью к воркерам | Воркеры повторяют одни и те же ошибки. | Сохраняйте ошибки в базу знаний. Корректируйте системные промпты. |
| Оркестратор становится bottleneck | Все ждут, пока оркестратор подумает. | Кэшируйте решения. Используйте легкие модели для простых задач распределения. |
| Воркеры пишут в одно место | Конфликты файлов, потеря изменений. | Используйте Git. Каждый воркер в своей ветке. Автоматический мерж. |
Что дальше? Эволюция мультиагентных систем
На 2026 год эта архитектура — продвинутый уровень. Но через год она будет считаться базовой.
Куда двигаться:
- Самообучение системы — воркеры анализируют свои успехи и неудачи, адаптируют промпты. Как в Agent Zero, но для кодирования.
- Динамическое создание новых типов воркеров — система сама понимает, что ей не хватает специалиста по WebSocket, и создает его.
- Интеграция с человеческим ревью — сложные моменты автоматически отправляются человеку, система учится на его правках.
Самая большая иллюзия: «Вот настрою систему, и она будет писать код за меня». Не будет. Она будет писать код с вами. Вы — архитектор, она — команда разработчиков. Вы ставите задачи, она их выполняет. Вы проверяете сложные моменты, она учится.
И последний совет: начните с малого. Не пытайтесь сразу построить систему на 20 агентов. Возьмите оркестратор, двух воркеров и одного ревьюера. Добейтесь, чтобы они написали простой микросервис. Потом масштабируйте.
Потому что в мультиагентных системах сложность растет не линейно, а экспоненциально. Десять агентов — не в десять раз сложнее, чем один. Это другая лига.