Команда собирала ответ на тендер. Один «агент» искал требования, второй писал решение, третий критиковал, четвёртый изображал руководителя. На демо они спорили двенадцать минут и выдали текст без обязательного срока поставки. Срок лежал в таблице на странице 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, даже если на двух этапах используются разные модели и промпты. Название не важно. Важно, что оркестратор владеет состоянием и переходами.
Когда несколько агентов оправданы
Разделение имеет смысл, если у исполнителей действительно разные границы: отдельные права и секреты, независимые контексты, разные владельцы или параллельные задачи, результаты которых можно свести детерминированно. Например, агент закупок читает внутренние цены, но не имеет доступа к почте; агент коммуникаций готовит письмо, но видит только утверждённую сумму. Граница безопасности здесь настоящая.
Полезен и параллельный поиск по независимым источникам, если reducer удаляет дубликаты, сохраняет provenance и умеет сообщить о конфликте. «Исследователь», «аналитик» и «критик» с одной моделью, одним контекстом и общими правами обычно являются дорогими именами для трёх prompt templates.
Цена координации
При последовательных шагах растут latency и вероятность отказа. Если каждый из пяти вызовов успешен с вероятностью 0,98, успех всей обязательной цепочки уже ниже успеха одного вызова. Параллельность сокращает время, но добавляет конфликты, повторную работу и задачу сведения ответов. Считать следует весь run: токены, tool calls, retries и время до проверенного результата.
Перед добавлением агента запишите:
- какой отдельный контракт он исполняет;
- какими правами обладает и почему;
- какой артефакт отдаёт;
- кто разрешает конфликт;
- как измеряется улучшение против простого workflow.
Если на эти вопросы нет ответов, новый участник пока нужен презентации, а не production.
Failure modes
Совещание моделей. Агенты пересылают прозу и постепенно теряют исходные данные. Передавайте структуры и ссылки на источники.
Общий контекст под разными именами. Роли коррелируют в ошибках, поэтому «критик» подтверждает выдумку автора. Для проверки нужны независимые evidence и критерии.
Нет владельца side effect. Два агента отправляют письмо или создают заявку. Назначьте одного исполнителя, idempotency key и policy check.
Reducer тоже модель без контракта. Он выбирает приятный ответ и выбрасывает конфликт. Reducer должен сохранять происхождение фактов и поднимать неразрешимые расхождения.
Нельзя воспроизвести run. Версии промптов, модели и входов не записаны. Тогда разбор превращается в чтение красивых логов задним числом.
Правило главы
Начинайте с явного workflow и одного владельца состояния. Делите систему на нескольких агентов только по реальной границе прав, контекста или независимой работы, а пользу подтверждайте eval-набором и полной стоимостью запуска.
Практикум
Возьмите pipeline подготовки ответа на тендер. Реализуйте вариант A как последовательный workflow и вариант B с тремя агентами: extractor, writer, reviewer. На 20 документах измерьте покрытие обязательных требований, долю утверждений без ссылки, p95 latency, число вызовов и стоимость.
Вариант B принимается только в том случае, если заранее выбранная метрика улучшается без нарушения лимита стоимости. Отдельно внесите требование, которое противоречит другому разделу PDF, и проверьте, что система сохраняет обе ссылки и передаёт конфликт человеку, а не устраивает голосование моделей.