Команда собирала ответ на тендер. Один «агент» искал требования, второй писал решение, третий критиковал, четвёртый изображал руководителя. На демо они спорили двенадцать минут и выдали текст без обязательного срока поставки. Срок лежал в таблице на странице 47. Никто не отвечал за то, чтобы извлечь его и проверить итоговый документ.
Несколько ролей в промптах ещё не образуют систему. Чаще это несколько LLM-вызовов, между которыми потерялся контракт.
Двенадцать минут спора выглядели убедительно именно потому, что были похожи на работу. Так же убедительно выглядит совещание, где семь человек обсуждают повестку и ни один не открыл вложение. Разница в том, что совещание хотя бы заканчивается обедом, а здесь заканчивается счётом за токены.
Сначала workflow
Если этапы известны заранее, их следует записать обычным графом:
PDF → extract requirements → normalize → draft → validate → human approval
│ ↑
└──── source citations ────────┘Каждый узел получает типизированный вход и возвращает проверяемый результат. Модель можно заменить на другом узле, повторить только упавший этап и увидеть, где исчез срок поставки.
class Requirement(BaseModel):
id: str
text: str
source_page: int
mandatory: bool
class Proposal(BaseModel):
sections: dict[str, str]
covered_requirement_ids: set[str]
async def build_proposal(pdf: bytes) -> Proposal:
requirements = await extract_requirements(pdf)
normalized = validate_requirements(requirements)
draft = await write_draft(normalized)
missing = {r.id for r in normalized if r.mandatory} - draft.covered_requirement_ids
if missing:
raise ValueError(f"Не покрыты требования: {sorted(missing)}")
return draftЭто single-agent workflow, даже если на двух этапах используются разные модели и промпты. Название не важно. Важно, что оркестратор владеет состоянием и переходами.
Проверка missing в конце — это ровно то место, которого не было в истории с тендером. Она стоит четыре строки, не требует ни одной модели и ловит именно тот класс ошибки, ради которого нанимали четвёртого «агента-руководителя».
Когда несколько агентов оправданы
Разделение имеет смысл, если у исполнителей действительно разные границы: отдельные права и секреты, независимые контексты, разные владельцы или параллельные задачи, результаты которых можно свести детерминированно. Например, агент закупок читает внутренние цены, но не имеет доступа к почте; агент коммуникаций готовит письмо, но видит только утверждённую сумму. Граница безопасности здесь настоящая.
Полезен и параллельный поиск по независимым источникам, если reducer удаляет дубликаты, сохраняет provenance и умеет сообщить о конфликте. «Исследователь», «аналитик» и «критик» с одной моделью, одним контекстом и общими правами обычно являются дорогими именами для трёх prompt templates.
Цена координации
При последовательных шагах растут latency и вероятность отказа. Если каждый из пяти вызовов успешен с вероятностью 0,98, успех всей обязательной цепочки уже ниже успеха одного вызова. Параллельность сокращает время, но добавляет конфликты, повторную работу и задачу сведения ответов. Считать следует весь run: токены, tool calls, retries и время до проверенного результата.
Перед добавлением агента запишите:
- какой отдельный контракт он исполняет;
- какими правами обладает и почему;
- какой артефакт отдаёт;
- кто разрешает конфликт;
- как измеряется улучшение против простого workflow.
Если на эти вопросы нет ответов, новый участник пока нужен презентации, а не production.
Полезно помнить, откуда взялась мода. Multi-agent красиво выглядит на схеме: кружочки, стрелочки, роли с человеческими названиями. Схема из четырёх кружков продаётся руководству лучше, чем граф из четырёх функций, хотя в проде это один и тот же граф, только у второго есть типы.
Failure modes
Совещание моделей. Агенты пересылают прозу и постепенно теряют исходные данные. Передавайте структуры и ссылки на источники.
Общий контекст под разными именами. Роли коррелируют в ошибках, поэтому «критик» подтверждает выдумку автора. Для проверки нужны независимые evidence и критерии.
Нет владельца side effect. Два агента отправляют письмо или создают заявку. Назначьте одного исполнителя, idempotency key и policy check.
Reducer тоже модель без контракта. Он выбирает приятный ответ и выбрасывает конфликт. Reducer должен сохранять происхождение фактов и поднимать неразрешимые расхождения.
Нельзя воспроизвести run. Версии промптов, модели и входов не записаны. Тогда разбор превращается в чтение красивых логов задним числом.
Как измерять разницу
Спор «один агент или несколько» решается не аргументами, а таблицей на одном наборе документов:
| Метрика | Зачем |
|---|---|
| покрытие обязательных требований | главное качество; в истории с тендером именно оно было нулевым |
| доля утверждений без ссылки на источник | видно, где проза заменила данные |
| p95 задержки | multi-agent обычно проигрывает здесь в разы |
| число вызовов модели и tool calls | прямая стоимость |
| стоимость одного проверенного результата | итог, по которому принимается решение |
Если multi-agent выигрывает по качеству и проигрывает по стоимости, это нормальный разговор с продуктом. Если он проигрывает по обеим осям, а команда всё равно за него — это разговор не про архитектуру.
Правило главы
Начинайте с явного workflow и одного владельца состояния. Делите систему на нескольких агентов только по реальной границе прав, контекста или независимой работы, а пользу подтверждайте eval-набором и полной стоимостью запуска.
Чеклист главы
Практикум
Задача 34.1 — A против B на одном наборе. ⭑⭑⭑
Возьмите pipeline подготовки ответа на тендер. Реализуйте вариант A как последовательный workflow и вариант B с тремя агентами: extractor, writer, reviewer. На 20 документах измерьте обе системы.
Критерии приёмки:
Подсказки:
- Двадцать документов достаточно, если в них есть неудобные случаи: таблицы, сканы, требования в сносках.
- Голосование моделей при конфликте — не решение, а способ спрятать конфликт. Проверьте, что ваш reducer этого не делает.
Задача 34.2 — граница прав вместо ролей в промпте. ⭑⭑
Постройте сценарий, где разделение на двух агентов действительно оправдано: у исполнителей разные права и разные секреты.
Критерии приёмки:
Подсказки:
- Хороший признак настоящей границы: объединение агентов требует выдать одному процессу оба набора секретов.
- Если такой сценарий в вашей системе не находится, это ответ: multi-agent вам пока не нужен.