Ранас Мукминов – Оркестрация ИИ-агентов. Claude Opus 4.7 (страница 98)
Отдельная ось топологии адресации — радиус: скольким получателям предназначено сообщение. Один (unicast) — обычный случай, разобранный выше. Подмножество (multicast) и все (broadcast) — это уже не адресация одного получателя, а доставка многим, со своей семантикой; она вынесена в главу 28 целиком. Здесь важно зафиксировать связь: расширение радиуса доставки умножает все риски маршрутизации. Неверная классификация при unicast задевает одного получателя; та же ошибка при broadcast рассылает сообщение всем, и если сообщение чувствительное, ошибка превращается в массовую утечку. Поэтому радиус доставки — это решение безопасности не меньше, чем решение об эффективности, и расширять его по умолчанию опасно.
Направление по содержанию заслуживает отдельного разбора, потому что это самый мощный режим адресации и одновременно концентрат всех её рисков. Здесь отправитель не задаёт адрес вообще — он производит содержание, а система сама решает, кому оно предназначено, прочитав и осмыслив это содержание.
Content-based router состоит из трёх частей: извлечение признаков (что в сообщении считать основанием для направления — тип, тема, ключевые поля, смысл), классификация (отнесение сообщения к одному из известных классов) и отображение класса на получателя (маршрутная таблица «класс — роль или экземпляр»).
Извлечение и отображение могут быть детерминированными даже при content-based routing: если класс однозначно определяется полем схемы (тип = «платёж»), то «классификация» сводится к чтению поля, и недетерминизма нет. Это, строго говоря, маршрутизация по структуре, а не по смыслу, — и её стоит предпочитать, когда содержание самоописательно. Подлинный content-based routing начинается там, где класс не выводится из структуры и требует осмысления: свободный текст, неоднозначный запрос, смешанное сообщение. Именно здесь в дело вступает классификатор, и именно здесь появляется недетерминизм и стоимость.
Из этой архитектуры следует практический принцип проектирования. Если отправитель в состоянии пометить сообщение классифицирующим полем при отправке (а чаще всего в состоянии, потому что он знает, что произвёл), то классификацию стоит сдвинуть к отправителю в виде структурного признака, а не выполнять её на стороне маршрутизатора чтением смысла. Это превращает дорогой недетерминированный content-based routing в дешёвую детерминированную маршрутизацию по схеме.
Здесь нет противоречия с развязкой. Отправитель проставляет не адрес (кому), а классифицирующий признак (что это за сообщение) — он по-прежнему не знает получателя. Развязка сохраняется, но решение о направлении становится дешёвым и воспроизводимым. Content-based routing по смыслу остаётся оправданным только там, где отправитель действительно не может классифицировать собственное сообщение: внешний вход неизвестной природы, агрегированный поток из разных источников, сообщение, чья принадлежность к классу зависит от контекста, которого у отправителя нет.
Content-based routing наследует все отказы маршрутизации и добавляет свои, связанные с классификацией.
— Неверная классификация. Классификатор относит сообщение не к тому классу и направляет не туда. В отличие от структурной маршрутизации, ошибка здесь — это ошибка осмысления, она правдоподобна и не ловится проверкой формата. Сообщение о платеже, классифицированное как текстовый запрос, уйдёт не туда и будет обработано как текст. Защита — поведение по умолчанию для низкоуверенной классификации (карантин, эскалация человеку), а не молчаливое направление по лучшей догадке.
— Дрейф классификатора. Распределение входящих сообщений со временем меняется, и классификатор, настроенный на прежнее распределение, начинает ошибаться чаще. Это не разовый сбой, а медленная деградация, видимая только в метриках доли неуверенных и переадресованных сообщений (см. главу 79).
— Инъекция через содержание. Поскольку направление зависит от содержания, противник, контролирующий содержание, управляет направлением. Сообщение, составленное так, чтобы классификатор отнёс его к привилегированному классу, попадёт к роли с большими правами. Это прямой канал prompt injection в маршрутизатор (см. главу 86) и центральный риск режима — ему посвящён следующий раздел.
— Стоимость на масштабе. Классификация каждого сообщения моделью — это вызов модели на каждое сообщение. На потоке это доминирующая статья расходов роя (см. главу 59), часто незаметная, потому что спрятана в маршрутизаторе, а не в исполнителях.
— Неклассифицируемое сообщение. Сообщение не подходит ни под один известный класс. Без явного класса «прочее» с определённым обработчиком такое сообщение либо отбрасывается (чёрная дыра), либо застревает. Полный набор классов с обязательным умолчанием — требование, а не опция.
Адресация определяет, кто что увидит и кто что выполнит. Поэтому контроль над маршрутизацией — это контроль над потоками доверия в рое, и маршрутизатор — приоритетная цель. Это связка с частью XII, и здесь фиксируются именно маршрутные аспекты.
Решение «кому направить» эквивалентно решению «кому дать доступ к этому сообщению». Если сообщение содержит чувствительные данные или инициирует привилегированное действие, маршрутизатор, направивший его не туда, совершил утечку или эскалацию — даже без злого умысла, просто ошибившись. Поэтому маршрутные правила сами по себе являются политикой безопасности и должны находиться под тем же контролем, что и права ролей (см. главу 88): кто может менять маршрутную таблицу, тот может перенаправить потоки доверия.
Особо опасно, когда маршрутизатор способен направить сообщение к роли с большими правами или во внешний контур (эгресс). Ошибочное или скомпрометированное направление в этом случае — это путь латерального движения (см. главу 84): данные из низкопривилегированного контура утекают в высокопривилегированный или наружу через неверный маршрут. Канон — маршруты к привилегированным получателям и к эгрессу должны быть детерминированными, явными и неизменяемыми в рантайме, а не зависеть от осмысления содержания.
Content-based router читает содержание, чтобы решить направление, — значит, содержание есть его вход, а вход агента есть канал инъекции. Сообщение можно составить так, чтобы оно было классифицировано в нужный противнику класс и доставлено нужной противнику роли. Если классы различаются по привилегиям (один класс идёт к роли с доступом к данным, другой — к роли без него), инъекция в классификатор — это эскалация привилегий через маршрутизацию.
Защита — те же принципы, что и для любого агента, читающего недоверенный вход (см. главу 86), плюс специфичные для маршрутизации: разделять данные и управляющие признаки (направление не должно определяться текстом, который контролирует противник, если за этим направлением стоит привилегия); ограничивать множество классов, к которым может привести классификация недоверенного входа; и никогда не давать классификатору, читающему внешний вход, права направлять в привилегированный контур без последующей независимой проверки.
Маршрутизатор, чьи решения не записываются, — это слепое пятно в потоках доверия. Каждое решение о направлении (что пришло, как классифицировано, куда направлено, с какой уверенностью) должно быть наблюдаемым событием (см. главу 89), иначе ни неверная классификация, ни дрейф, ни инъекция не обнаруживаются до последствий. Это особенно важно для маршрутизатора на модели: его решения недетерминированы, и без записи их невозможно воспроизвести при разборе инцидента (см. главу 82). Наблюдаемость маршрутизации — это не отладочная роскошь, а условие того, что потоками доверия вообще можно управлять.
Часть отказов привязана к конкретным моделям адресации и разобрана выше. Здесь собраны отказы самого механизма направления — общие для всех режимов, кроме вырожденной прямой адресации.
Сообщение направлено получателю, для которого не предназначено. Источники различны: неверная классификация в content-based router, устаревшая маршрутная таблица, рассогласование между копиями таблицы у разных маршрутизаторов, ошибка резолюции «роль — экземпляр». Последствие — от безобидного (получатель отвергает чужое сообщение) до тяжёлого (привилегированный получатель выполняет неуместное действие, или чувствительные данные утекают не в тот контур). Защита многоуровневая: проверка получателем, что сообщение ему адресовано (получатель не доверяет факту доставки слепо); поведение по умолчанию для неуверенных решений; и наблюдаемость, позволяющая увидеть misrouting в метриках, а не по последствиям.
Сообщение возвращается в маршрутизатор, тот направляет его снова, и оно ходит по кругу — livelock на уровне доставки (см. главу 74). Типичный сценарий: получатель не может обработать сообщение и возвращает его «на перемаршрутизацию», маршрутизатор по тем же признакам направляет его тому же получателю. Это особенно коварно в content-based routing, где признаки направления стабильны (содержание не меняется), а значит, и решение стабильно повторяется. Канонические защиты прямые: счётчик переадресаций в сообщении (метаданные маршрутизации, см. главу 25) с жёстким пределом; обнаружение циклов в графе маршрутов; и явный обработчик «не удалось доставить после N попыток», направляющий сообщение в очередь разбора или человеку, а не обратно в петлю.