Мультиагентная система - не цель, а дорогой способ декомпозиции

Несколько агентов добавляют новые модельные вызовы, сетевые переходы, состояние, права доступа и точки отказа. Они оправданы не потому, что роли выглядят правдоподобно, а когда декомпозиция улучшает измеримый результат. Сначала соберите сильный single-agent baseline с качественными tools, инструкциями и eval-набором.

Если один агент решает задачу в допустимом контексте, времени и бюджете, многоагентность обычно усложнит эксплуатацию. Если же отдельные домены требуют разных данных, политик, моделей или могут безопасно выполняться параллельно, разбиение становится инженерным инструментом.

1
baseline до декомпозиции
4
причины: специализация, изоляция, параллельность, ownership
0
агентов без измеримой пользы

Когда несколько агентов действительно нужны

СигналПольза разделенияПроверка
Разные доменыУзкие инструкции и toolsМеньше ошибок routing и tool selection
Чувствительные данныеИзоляция контекста и правСпециалист не видит лишние данные
Независимые подзадачиПараллельное выполнениеСнижается end-to-end latency
Разные команды-владельцыВерсионирование по доменамИзменения имеют независимый rollout
Разные моделиЦена и качество под подзадачуНиже стоимость успешного результата

Формулировка «исследователь, критик и автор» сама по себе ничего не доказывает. Проверьте, обладает ли каждая роль уникальными данными, инструментами, политикой или критерием качества.

Два базовых паттерна: supervisor и handoff

OpenAI Agents SDK выделяет два распространённых варианта. В manager-паттерне главный агент вызывает специалистов как tools и сохраняет контроль над разговором и финальным ответом. При handoff маршрутизатор передаёт управление специалисту, который становится активным агентом. Эти варианты можно сочетать.

Supervisor

Планирует, делегирует, проверяет и собирает один ответ.

Handoff

Меняет активного владельца задачи и его инструкции.

Hybrid

Маршрутизация между доменами плюс локальные подагенты.

Выбор паттерна по владению результатом

ВопросSupervisorHandoff
Кто отвечает пользователюОдин managerАктивный специалист
Кто объединяет выводыManagerНе требуется либо отдельный шаг
Единая политикаПроще централизоватьНужна на каждом переходе
Изоляция инструкцийСпециалист вызывается как подзадачаПолная смена активного контекста
Риск bottleneckВыше у managerВыше риск потерять общий контроль

Если финальный ответ должен объединять расчёты, юридические ограничения и факты, удобнее manager. Если пользователь после первичной классификации должен работать напрямую с отделом возвратов, handoff естественнее.

Детерминированный workflow часто надёжнее свободного роутинга

Не каждое решение о следующем шаге нужно отдавать модели. Код может классифицировать структурированный результат, запустить независимые задачи параллельно, дождаться обязательных зависимостей и завершить workflow по явным условиям. Официальный гайд OpenAI прямо допускает сочетание orchestration через LLM и через код.

  • Жёсткие compliance-переходы задавайте state machine.
  • Независимые read-only исследования запускайте fan-out/fan-in.
  • Свободное планирование оставляйте внутри безопасного участка.
  • Для evaluator loop задайте максимальное число итераций.
  • Недопустимый переход отклоняет runtime.

Карта агентов начинается с доменных границ

Опишите каждого агента как сервисный контракт, а не как характер. Нужны цель, входы, выходы, источники истины, разрешённые tools, запрещённые действия, владелец и SLO. Пересекающиеся обязанности приводят к гонкам и спору о том, кто должен завершить работу.

Agent ID: billing_refund_v2
Goal: prepare a refund eligibility decision, not execute payment.
Accepts: case_id, reason_code, requested_amount.
Reads: order ledger, refund policy.
Writes: immutable decision proposal.
Tools: get_order, get_policy, propose_refund.
Forbidden: direct payment, policy editing, cross-tenant search.
Output schema: RefundDecisionV2.
Owner: Billing Platform.
Timeout: 20 s. Max tool calls: 6.

Handoff должен быть типизированным конвертом

Передача полного диалога без пояснения заставляет следующего агента заново угадывать задачу. Создайте явный envelope: идентификаторы, цель, проверенные факты, ссылки на артефакты, критерии готовности, ограничения, бюджет и причину маршрутизации. Свободный текст можно приложить, но не использовать как единственный контракт.

{
  "task_id": "t_...",
  "parent_id": "t_...",
  "from_agent": "triage_v3",
  "to_agent": "billing_refund_v2",
  "objective": "Decide refund eligibility",
  "verified_facts": [{"field": "order_id", "value": "...", "source": "ledger://..."}],
  "artifact_refs": [],
  "definition_of_done": ["valid RefundDecisionV2", "policy clause cited"],
  "remaining_budget": {"deadline_ms": 15000, "tool_calls": 6},
  "trace_id": "tr_..."
}

Не смешивайте транскрипт, рабочее состояние и память

СлойЧто хранитСрок и контроль
TranscriptСообщения и tool eventsСессия, фильтрация перед передачей
Workflow stateСтатусы, зависимости, бюджеты, approvalsТранзакционно до завершения
ArtifactsОтчёты, таблицы, документыВерсии и immutable references
Long-term memoryРазрешённые устойчивые фактыTTL, provenance, удаление и consent

Shared state не означает, что каждый агент получает всё. Runtime формирует минимальное представление по роли, tenant и data classification. Изменение критичного состояния проходит через compare-and-set или транзакцию.

Источник истины не должен жить в ответе модели

Статус заказа, баланс, права и решение об approval читаются из authoritative systems. Сообщение агента является предложением или ссылкой на проверенный артефакт. В shared state сохраняйте не только значение, но и источник, время, версию и уровень доверия.

  • Не копируйте большие документы между агентами - передавайте immutable reference.
  • Не повышайте непроверенный вывод до verified fact.
  • При конфликте повторно читайте источник истины.
  • Логируйте, какой агент создал каждое утверждение.
  • Персональные данные редактируйте до передачи.

Бюджет наследуется вниз, но не расширяется

Родительская задача задаёт общий deadline, лимит токенов, денег, tool calls, глубины и числа параллельных ветвей. Дочерний агент получает часть остатка. Он не может сам увеличить лимит или запустить неограниченное количество потомков.

global deadline = 60 s
max depth = 3
max fan-out = 4
max total model calls = 12
max total tool calls = 30
max retries per operation = 2
child budget <= unallocated parent remainder
stop on: deadline, exhausted budget, repeated state, cancellation, policy denial
return: partial_result + missing_items + reason

Права делегируются уже выданного scope

Handoff не должен превращаться в повышение привилегий. Специалист получает пересечение прав пользователя, workflow, вызывающего агента, политики tenant и текущего состояния. Credentials модели не видны; runtime выдаёт короткоживущий capability token для конкретной операции.

пересечение scopes
TTL
короткая жизнь capability
1
цель на approval

Prompt injection распространяется по цепочке

Если исследователь прочитал вредоносную инструкцию на странице и передал её как «вывод», supervisor может довериться ей. Tool output, документы, память и сообщения других агентов остаются недоверенными данными. Они не могут менять system policy или выдавать права.

  • Отделяйте инструкции от данных структурой сообщения.
  • Передавайте цитату и provenance, а не скрытую команду.
  • Фильтруйте историю при handoff.
  • Повторно авторизуйте каждый side effect.
  • Сканируйте артефакты до записи в общую память.
  • Тестируйте indirect injection через каждого специалиста.

Deadlock, livelock и ping-pong - разные сбои

СбойПримерЗащита
DeadlockА ждёт B, B ждёт ADAG зависимостей, timeout, запрет циклического wait
LivelockАгенты меняют план, но не приближаются к целиProgress invariant и max iterations
Ping-pongДва специалиста возвращают задачу друг другуHandoff history и запрет повторного ребра
Duplicate workДве ветви создают один объектDedup key, lease, idempotency
Fan-out explosionКаждый агент создаёт несколько детейГлобальный лимит ветвей и depth

Определите прогресс как проверяемое изменение

Фраза агента «продолжаю анализ» не является прогрессом. Оркестратор сравнивает состояние: появился новый подтверждённый факт, закрыта зависимость, создан валидный артефакт или уменьшился список неизвестного. Повтор того же состояния фиксируется fingerprint и останавливает ветвь.

Loop guard
  1. Сохранить fingerprint входа и состояния.
  2. Проверить повторный маршрут.
  3. Ограничить глубину и итерации.
  4. Проверить изменение progress metric.
  5. Остановить ветвь по deadline.
  6. Вернуть partial result вместо бесконечного retry.
  7. Поднять alert при систематическом цикле.

Параллельность требует политики слияния

Fan-out ускоряет независимые задачи, но fan-in должен понимать, какие результаты обязательны, как разрешать конфликт и что делать с опоздавшей ветвью. Не просите модель произвольно «усреднить» противоречия.

  • Для факта выберите authoritative source.
  • Для расчёта сравните входы и версию формулы.
  • Для текста сохраните замечания как отдельные proposals.
  • Для записи используйте optimistic locking.
  • Для обязательной ветви завершайте с явным incomplete.
  • После cancel запрещайте поздний side effect.

Ошибки, отмена и частичный результат проектируются заранее

Каждый агент возвращает typed status: completed, incomplete, denied, failed или cancelled. Ошибка содержит code, retryability, безопасное описание и ссылки на уже созданные артефакты. Оркестратор решает retry, fallback, human escalation или завершение с неполным результатом.

СобытиеРеакцияЗапрет
Transient timeoutОграниченный retry в общем deadlineБесконечный локальный retry
Policy deniedОбъяснение и эскалацияОбход другим агентом
Child failedFallback или partial resultСкрывать незавершённость
User cancelledРаспространить cancel tokenНовые side effects

Human-in-the-loop ставится перед необратимым действием

Подтверждение относится не к «работе агента вообще», а к неизменяемому proposal: получатели, сумма, ресурсы, diff, риск и срок. После любого изменения proposal approval теряет силу. Проверяющий видит происхождение данных и альтернативы.

Preview

Точный diff и последствия.

Approve

Scope, actor, expiry и hash.

Execute

Idempotency и audit event.

Trace должен показывать граф, а не только чат

Один trace_id связывает запрос пользователя, решение маршрутизатора, handoffs, model calls, tools, approvals, артефакты и итог. Для каждого span записывайте agent/version, prompt/config version, модель, входные references, токены, стоимость, latency, status и policy decisions. Чувствительные payload храните отдельно или редактируйте.

trace_id, task_id, parent_task_id
agent_id, agent_version, route_reason
model, prompt_version, tool_schema_version
input_refs, output_refs, handoff_target
start_time, latency, tokens, estimated_cost
policy_decisions, approval_id
status, error_code, retry_count
progress_before, progress_after

Метрики координации важнее числа сообщений

МетрикаЧто показываетПлохой сигнал
Task successВыполнен критерий готовностиКрасивый ответ без результата
Cost per successЦена успешной задачиСредняя цена без учёта провалов
Unnecessary handoff rateЛишняя маршрутизацияРост переходов без качества
Loop rateПовторные состояния и ребраPing-pong
Coordination overheadДоля времени и токенов на передачуСпециалисты дешевле, система дороже
Human escalationГде автономность заканчиваетсяСкрытые ручные исправления

Evals сравнивают архитектуры на одинаковых задачах

Соберите датасет из обычных, пограничных, неоднозначных и враждебных сценариев. На одинаковых входах сравните один агент, supervisor и handoff-вариант. Проверяйте не только финальный текст, но и маршрут, права, вызовы tools, side effects, стоимость и восстановление после сбоя.

Eval suite
  1. Правильный выбор владельца.
  2. Отказ от ненужного handoff.
  3. Валидный envelope.
  4. Сохранение provenance.
  5. Запрет повышения прав.
  6. Остановка циклов и fan-out.
  7. Корректная отмена.
  8. Partial result при отказе ветви.
  9. Injection через tool output.
  10. Сравнение cost per success с baseline.

План внедрения без big bang

  1. Зафиксируйте baseline. Один агент, датасет, качество, p95 latency и стоимость успешной задачи.
  2. Выделите одну границу. Например, отдельный read-only специалист по политике.
  3. Введите контракт. Typed inputs, output, provenance и error taxonomy.
  4. Добавьте runtime limits. Depth, fan-out, deadline, токены и tools.
  5. Запустите shadow. Новый граф не выполняет side effects.
  6. Сравните evals. Выигрыш должен покрывать coordination overhead.
  7. Откройте малый трафик. Canary с kill switch.
  8. Расширяйте по одной границе. Не добавляйте сразу сеть из десятков ролей.

Production-чек-лист мультиагентной системы

Перед запуском
  1. Есть измеримый single-agent baseline.
  2. Каждый агент имеет непересекающийся контракт и владельца.
  3. Граф допустимых переходов задан runtime.
  4. Handoff envelope типизирован и версионируется.
  5. Transcript, state, artifacts и memory разделены.
  6. Права только сужаются при делегировании.
  7. Настроены depth, fan-out, deadline, token и cost limits.
  8. Есть loop detection, deduplication и idempotency.
  9. Cancel распространяется на все дочерние операции.
  10. Prompt injection не может менять policy.
  11. Trace связывает весь граф и версии.
  12. Evals проверяют маршруты, side effects и отказоустойчивость.
  13. Есть canary, kill switch и single-agent fallback.
Что такое мультиагентная система?
Это приложение, где несколько специализированных агентов координируются через оркестратор, вызовы друг друга или handoffs. Production-система также включает контракты, состояние, права, лимиты, трассировку и обработку ошибок.
Чем supervisor отличается от handoff?
Supervisor сохраняет контроль, вызывает специалистов и формирует итог. При handoff активное управление и ответ переходят выбранному специалисту. Выбор зависит прежде всего от того, кто должен владеть конечным результатом.
Всегда ли несколько агентов лучше одного?
Нет. Они добавляют задержку, стоимость и точки отказа. Начинайте с одного агента и добавляйте декомпозицию только при измеримом выигрыше от специализации, изоляции контекста, параллельности или отдельных политик.
Как передавать контекст между агентами?
Через минимальный типизированный envelope с целью, проверенными фактами, ссылками на артефакты, критериями готовности, ограничениями, бюджетом и provenance. Полный транскрипт передавайте только после фильтрации и когда он действительно нужен.
Как остановить бесконечные циклы агентов?
Ограничьте глубину, fan-out, число переходов и deadline; храните историю рёбер и fingerprint состояния; определите проверяемый прогресс; запрещайте повторный маршрут без новых данных; завершайте ветвь с partial result.
Можно ли делиться одной памятью между всеми агентами?
Технически можно, но безопаснее давать минимальное представление по роли и задаче. Отделяйте рабочее состояние от транскрипта и долговременной памяти, сохраняйте provenance, TTL и правила доступа.
Какие метрики нужны для мультиагентной системы?
Task success, cost per success, p95 latency, unnecessary handoff rate, loop rate, coordination overhead, число side effects, policy violations и human escalation. Сравнивайте их с single-agent baseline.
Как безопасно запустить мультиагентную архитектуру?
Сначала evals и shadow-режим без side effects, затем canary на малой доле трафика. Нужны жёсткие runtime-лимиты, повторная авторизация действий, наблюдаемость, kill switch и понятный fallback.
← Все статьи блога