Ранас Мукминов – Оркестрация ИИ-агентов. Claude Opus 4.7 (страница 53)
Третий шаг — явно перечислить границы между фрагментами и для каждой определить способ комбинирования (вложение, последовательное, наложение) и контракт границы. Это самый ответственный шаг: именно здесь решается, где меняется протокол, модель координации и носитель состояния, и что происходит на стыке при нарушении контракта.
Четвёртый шаг — протянуть сквозные требования через все границы. Если системе в целом нужна определённая семантика доставки результата, определённый уровень изоляции отказов или сквозная трассируемость (см. главу 77), эти требования проверяются на каждой границе отдельно, потому что граница — место, где они теряются. Сквозное свойство держится, только если его держат все звенья и все стыки.
Пятый шаг — проверить, что гибрид не воспроизводит антипаттерны композиции, разобранные ниже. Многие гибриды выглядят разумно фрагмент за фрагментом и оказываются нерабочими именно на стыках.
Этот порядок устроен так, что границы фиксируются раньше внутренностей. Причина в стабильности: внутренняя топология фрагмента — самый изменчивый элемент системы, её часто переделывают по мере того, как проясняется задача и накапливается опыт эксплуатации. Контракт границы, напротив, должен быть стабильным, потому что от него зависят соседи. Если проектировать в обратном порядке — сначала внутренности, потом границы, — контракт границы оказывается слепком случайного устройства фрагмента на момент проектирования, и любая переделка внутренности тянет за собой смену контракта и каскад правок у соседей. Фиксируя контракт первым, мы получаем точки разреза, которые переживают переделку любой из соединяемых топологий: внутренность можно заменить целиком, лишь бы новая реализация соблюдала прежний контракт границы.
Полезная эвристика для размещения границ: граница должна проходить там, где естественно меняется форма работы, а не там, где удобно разделить ответственность между людьми или командами. Организационные границы и топологические границы — разные оси, и их совмещение по привычке плодит лишние стыки. Если два соседних фрагмента имеют одну и ту же форму координации и обмениваются состоянием на каждом шаге, граница между ними, скорее всего, искусственна, и фрагменты стоит слить в одну топологию, убрав стык вместе с его налогом и его отказами.
Гибридизация добавляет класс ошибок, которых нет в чистых топологиях. Все они связаны с границами.
Самый частый антипаттерн — гибрид, полученный наращиванием без проектирования стыков. Каждый фрагмент добавлялся под локальную потребность, границы возникали как побочный эффект, контрактов у них нет. Система работает, пока работают неписаные предпосылки на стыках, и ломается непредсказуемо, когда одна из сторон границы меняется. Симптом — отказы, локализующиеся «между компонентами», которые ни один владелец фрагмента не признаёт своими. Лечение — ретроспективно специфицировать границы и сделать их контракты проверяемыми; это дорого, но дешевле, чем продолжать платить отладкой стыков.
Вложение обещает, что внешняя топология не обязана знать о внутренней. Антипаттерн — когда внутренняя топология протекает наружу: оркестратор вынужден знать, что воркер внутри конвейер, чтобы корректно обработать его промежуточные состояния или специфические отказы. Протекающая абстракция сводит на нет главную выгоду вложения — локализацию отказа границей узла — и делает внешнюю топологию заложником внутренней. Причина почти всегда одна: дырявый или неполный контракт узла, не покрывающий все исходы, включая отказы. Лечение — достроить контракт так, чтобы любой внутренний исход выражался через объявленный внешний интерфейс.
Антипаттерн возникает, когда оркестрированная топология соединяется с эмерджентной без переходного звена. Оркестратор отдаёт работу в рыночную или peer-to-peer-подсистему и ждёт результата с гарантией завершения, которой эмерджентная часть не даёт. Возникает зазор ответственности: оркестратор уверен, что работа будет сделана, эмерджентная часть никому завершение не обещала. Система зависает в ожидании результата, который не гарантирован. Лечение — вставить на границе адаптер с явной семантикой завершения: тайм-аут, фиксированный дедлайн, или агент-наблюдатель, превращающий эмерджентный исход в детерминированный сигнал «готово или нет» (см. главы 70 и 72).
При наложении функциональной и инфраструктурной топологий антипаттерн — когда обе пытаются управлять одним и тем же. Содержательная иерархия задаёт порядок шагов, и одновременно инфраструктурная шина переупорядочивает сообщения; или оба слоя независимо решают, какому агенту достанется задача. Слои расходятся, и поведение системы определяется их недокументированным взаимодействием. Это худший для отладки класс отказов, потому что каждый слой по отдельности корректен (см. главу 80). Лечение — провести чёткую границу ответственности между слоями: что решает функциональный слой, что — инфраструктурный, и зафиксировать, что они не пересекаются в управлении.
Каждая топология тяготеет к своему носителю состояния, и в гибриде их оказывается несколько: контекст оркестратора, сообщения конвейера, общая доска, очередь. Антипаттерн — когда одно и то же состояние дублируется на нескольких носителях и расходится: на доске одно значение, в контексте оркестратора другое, в сообщении третье. Распределённое состояние без единого источника истины — фундаментальный риск (см. главу 46), и гибрид его усиливает, потому что границы между топологиями плодят копии. Лечение — для каждого элемента состояния назначить единственный авторитетный носитель, а остальные копии считать кэшем, который может устареть и не является истиной.
Зеркало антипаттерна «мультиагентность ради мультиагентности» (см. главу 4): топологии комбинируются не потому, что этого требует структура задачи, а потому что каждый паттерн по отдельности кажется уместным. Результат — система со множеством границ, каждая из которых добавляет координационный налог и поверхность отказа, без соразмерной выгоды. Признак — границы, которые можно убрать слиянием фрагментов без потери функциональности. Лечение — стремиться к минимальному числу границ: каждый стык должен быть оправдан тем, что соединяемые части действительно требуют разных топологий, а не привычкой делить.
Гибридная топология меняет все три сквозные характеристики системы, и почти всегда в сторону усложнения.
По стоимости гибрид добавляет координационный налог на каждой границе. Пересечение границы — это handoff, сериализация и десериализация состояния, иногда дополнительный агент-адаптер. Чем больше границ, тем выше налог, не связанный с содержательной работой. С другой стороны, грамотный гибрид снижает стоимость там, где применяет дешёвую топологию вместо дорогой — маршрутизатор перед разнородными подсистемами окупает свои границы экономией на простых запросах. Баланс зависит от того, оправданы ли границы; бесполезные границы — чистый налог (см. главу 5).
По надёжности гибрид опаснее любой из своих частей по умолчанию, потому что добавляет отказы на стыках к отказам внутри топологий. Но он же может быть надёжнее, если границы используются для изоляции: каждая топология в отсеке (см. главу 71), и отказ одной не распространяется на другие через строгий контракт границы. То есть граница — одновременно источник новых отказов и средство изоляции существующих; что перевесит, зависит от того, спроектирована ли граница как барьер или как тихий канал протекания.
Особый случай — взаимодействие границ с повторами. Повтор при отказе — базовый приём устойчивости (см. главу 70), но в гибриде он осложняется тем, что неясно, где перезапускать работу при отказе на стыке. Перезапуск всей цепочки от начала переплачивает координационный налог уже выполненных топологий и в дорогих роях недопустим по стоимости. Перезапуск только с границы требует, чтобы пройденная часть была восстанавливаема, а целевая сторона границы — идемпотентна по повторному приёму одного и того же состояния. Если граница не идемпотентна, повтор после частичного отказа на стыке вызывает дублирование работы или двойное применение результата — отказ, которого внутри любой из топологий по отдельности не было бы. Поэтому границы, через которые проходят повторы, нужно проектировать с ключами идемпотентности (см. главу 43), а точки, до которых откатывается повтор, — делать восстановимыми контрольными точками состояния (см. главу 72). Без этого устойчивость, которую каждая топология обеспечивает внутри себя, не складывается в устойчивость гибрида.
По наблюдаемости гибрид сложнее на порядок. Трассировка должна пересекать границы топологий, сохраняя сквозной идентификатор через смену протокола и носителя состояния (см. главу 77); без этого след обрывается на каждом стыке, и причинную цепочку посмертно не восстановить (см. главу 78). Метрики уровня системы должны измерять не только работу внутри топологий, но и стоимость пересечения границ — задержку на стыках, долю отказов, локализующихся на границах (см. главу 79). Наблюдаемость гибрида нужно проектировать вместе с самим гибридом: границы, через которые не проходит трассировка, становятся слепыми зонами, в которых отказы невидимы до постмортема (см. главу 82).