Ранас Мукминов – Оркестрация ИИ-агентов. Claude Opus 4.7 (страница 96)
Глава разделяет две вещи, которые на практике сливают. Первая — модель адресации: на каком основании вообще выбирается получатель (по имени, по роли, по способности, по содержанию, косвенно через общее пространство). Вторая — маршрутизатор как компонент: где в системе физически принимается решение о направлении и какова топология этих решений. Это не та же сущность, что маршрутизатор-роль из главы 19: там маршрутизатор рассматривался как агент со своим контрактом, контекстом и правами; здесь — как механизм доставки, который может быть и агентом, и детерминированным кодом, и таблицей, и свойством среды. Отдельно разбирается content-based routing — направление по содержанию сообщения — как самый гибкий и самый опасный из режимов. Failure modes, по сквозному правилу книги, вынесены явно и привязаны к конкретным режимам адресации.
В одиночном агенте поток управления и поток данных совпадают: контур наблюдение—план—действие—проверка вызывает инструменты напрямую, и «кому передать результат» не существует как вопрос — результат возвращается туда, откуда пришёл вызов. Адресация неявна и тривиальна.
Рой ломает это совпадение. Результат исполнителя должен попасть не обратно к исполнителю, а к ревьюеру, или к агрегатору (см. главу 37), или к следующей стадии конвейера (см. главу 10), или в очередь свободному воркеру (см. главу 33). Кто из них — зависит от типа результата, от состояния системы, от плана. Отправитель в общем случае не обладает этим знанием и не должен им обладать: если каждый исполнитель захардкодит, кому слать результат, рой превращается в жёстко сцепленный граф, который нельзя перестроить, не переписав исполнителей. Развязка отправителя и получателя — это то, ради чего вообще нужен уровень адресации.
Здесь полезна аналогия с распределёнными системами, с честной поправкой. В сетях есть разделение на адресацию (кому, идентификатор узла) и маршрутизацию (как туда добраться, путь). В рое агентов это разделение тоже есть, но получатель часто не узел, а роль или способность, и «путь» — это не последовательность хопов, а последовательность решений о направлении, каждое из которых может приниматься недетерминированной моделью. Законы остаются (развязка через косвенность, опасность петель, риск чёрных дыр), но их проявления специфичны: маршрут может зависеть от смысла сообщения, а не только от его адреса.
Уровень адресации не бесплатен — это, по логике главы 5, ещё один координационный налог. Но отказ от него платится дороже, и платится связанностью. Если отправитель сам решает, кому слать, он обязан знать о существовании, возможностях и текущем состоянии получателя; это знание встроено в отправителя и распространяется по всему рою. Любое изменение состава ролей требует обхода всех отправителей. Это та же топологическая ловушка, что и прямые рёбра «воркер — воркер» в fan-out/fan-in (см. главу 8): без посредника число связей растёт квадратично, и каждая связь — это место, где знание об одном агенте протекло в другого.
Поэтому уровень адресации — это не накладные расходы, а инвестиция в развязку: отправитель знает только, какого рода обработка ему нужна, а не кто её выполнит. Цена инвестиции — задержка и стоимость самого решения о направлении (особенно если его принимает модель) плюс новый компонент, который может ошибаться и который надо наблюдать и защищать. Вся остальная глава — про то, как сделать эту инвестицию управляемой.
Полезно с самого начала различать три отдельных понятия, которые сленг «маршрутизации» смешивает.
Адрес — это идентификатор намеченного получателя: имя агента, имя роли, описание требуемой способности, тема. Адрес отвечает на вопрос «кому по смыслу».
Резолюция — это превращение адреса в конкретного получателя: по имени роли «ревьюер» выбрать конкретный экземпляр ревьюера, способный и свободный. Резолюция отвечает на вопрос «кто именно сейчас».
Доставка — это собственно перемещение сообщения выбранному получателю: постановка в его очередь, синхронный вызов, запись в общее пространство. Доставка отвечает на вопрос «как туда».
Эти три отвечают разные подсистемы, и путать их вредно. Семантика доставки (надёжность, порядок, дублирование) — предмет главы 29; широковещание и подписки как способ доставки многим — предмет главы 28. Эта глава сосредоточена на первых двух: на адресе и резолюции, то есть на решении кому, а не на механике как туда.
Существует небольшой набор оснований, по которым рой выбирает получателя. Они различаются тем, насколько отправитель связан с получателем, насколько решение детерминировано и где сосредоточено знание о топологии. Перечислены в порядке нарастания развязки и нарастания стоимости решения.
Отправитель называет конкретного получателя по уникальному идентификатору — «отправить агенту worker-7». Это вырожденный случай: адрес совпадает с получателем, резолюция тривиальна, решение детерминированно и дёшево.
Прямая адресация уместна там, где топология статична и связь намеренно жёсткая: оркестратор адресует конкретному воркеру, которому он же выдал подзадачу; стадия конвейера адресует строго следующей стадии. Её достоинство — предсказуемость и наблюдаемость: по сообщению сразу видно, куда оно идёт, и причинная цепочка прозрачна (см. главу 78). Её недостаток — максимальная связанность: отправитель знает получателя поимённо, и любое изменение состава требует правки отправителя. Прямую адресацию стоит применять там, где жёсткая связь — это сознательный выбор, а не там, где просто не подумали о развязке.
Отдельный риск прямой адресации в рое — устаревший идентификатор. Агент мог завершиться, перезапуститься под другим идентификатором, быть переназначенным (см. главу 72). Сообщение по жёсткому адресу уходит в никуда — это чёрная дыра, к которой глава вернётся в разделе об отказах.
Отправитель называет не экземпляр, а роль — «отправить ревьюеру», «отправить тестировщику». Резолюция выбирает конкретного носителя этой роли. Это первый уровень развязки: отправитель знает, какого рода обработка нужна, но не кто её выполнит.
Адресация по роли — рабочая лошадь большинства роёв, потому что она совпадает с каталогом канонических ролей (см. главу 19) и с естественной декомпозицией ответственности. Исполнитель отправляет результат «на ревью», не зная и не интересуясь, какой именно ревьюер его примет. Это позволяет иметь несколько носителей одной роли (для параллелизма или отказоустойчивости) и менять их состав, не трогая отправителей.
Резолюция «роль — экземпляр» здесь становится самостоятельным решением и пересекается с диспетчеризацией (см. главу 33): если носителей роли несколько, кого выбрать — свободного, наименее загруженного, любого. Эта глава фиксирует разделение ответственности: модель адресации отвечает на вопрос «какая роль», а выбор конкретного экземпляра внутри роли — это уже балансировка, предмет главы 33. Смешение «по роли» с «по нагрузке» в одном непрозрачном механизме затрудняет и отладку, и рассуждение о справедливости.
Отправитель описывает не роль, а требуемую способность — «нужен агент, умеющий исполнять SQL», «нужен агент с доступом к внешнему API платежей». Резолюция сопоставляет требование с реестром возможностей агентов и выбирает подходящего.
Это более тонкая развязка, чем по роли: способности ортогональны ролям (один агент может обладать несколькими, разные роли — общими способностями), и адресация по способности позволяет составу роя эволюционировать без переименования ролей. Она же — основа рыночных и аукционных моделей (см. главу 12), где агенты объявляют свои возможности, а работа направляется по соответствию.
Цена — реестр возможностей как отдельная сущность, которую надо поддерживать в актуальном состоянии и защищать. Если агент объявляет способность, которой не обладает (по ошибке или злонамеренно), резолюция направит ему работу, которую он не выполнит или выполнит небезопасно. Реестр возможностей — это точка доверия (см. главу 85): запись в нём должна быть проверяемой, а не декларативной.
Получатель определяется содержанием самого сообщения: его смыслом, темой, классификацией. «Сообщение о платеже — финансовому агенту; сообщение о тексте — лингвистическому». Это content-based routing, которому посвящён отдельный раздел ниже, потому что у него своя архитектура и свои отказы. Здесь важно зафиксировать его место в спектре: это самая глубокая развязка (отправитель вообще не задаёт адрес, только производит содержание) и самое дорогое и недетерминированное решение (кто-то должен прочитать и классифицировать содержание).
Предельный случай развязки — отправитель не адресует никому. Он публикует результат в общее пространство (доску, см. главу 11; общую память, см. часть VII), а получатели сами забирают то, что им подходит. Адресации в явном виде нет: есть публикация и подписка по интересу.
Косвенная адресация даёт максимальную развязку (отправитель не знает о получателях вовсе) ценой максимальной потери наблюдаемости: по факту публикации нельзя сказать, кто прочитает и прочитает ли вообще. Это смежная тема с pub/sub и событийной координацией (см. главу 28); здесь она названа как крайняя точка спектра адресации — от «назвал поимённо» до «не адресовал никому». Чем правее по этому спектру, тем меньше связанность и тем меньше предсказуемость доставки.