Ранас Мукминов – Оркестрация ИИ-агентов. Claude Opus 4.7 (страница 22)
Коммуникация — уровень, где теория распределённых систем применима почти без поправок, и где недооценка этой теории дороже всего обходится. Сообщение между агентами может потеряться, продублироваться, прийти не в том порядке или с задержкой — ровно как пакет в сети. Разница в том, что получатель здесь — недетерминированная модель, которая на дубликат сообщения может отреагировать непредсказуемо, а не просто отбросить его. Поэтому семантика доставки и идемпотентность (см. главу 43) на этом уровне — не академическая роскошь, а условие корректности.
Главный failure mode — молчаливая потеря или искажение в канале естественного языка. В отличие от бинарного протокола, где искажённое сообщение не пройдёт проверку контрольной суммы, искажённое сообщение на естественном языке выглядит правдоподобно и принимается получателем. Агент может «дополучить» смысл, которого не было, или потерять важную деталь, и это не вызовет ошибки парсинга — вызовет неверное действие ниже по потоку. Защита — структурированные схемы и валидация на стыках (часть IV).
Если первые три уровня описывают статическую структуру, то следующие два — декомпозиция и координация — описывают динамику: как работа разбивается и как параллельные действия согласуются во времени. Это уровни, на которых проявляется большая часть специфических трудностей оркестрации.
Декомпозиция отвечает на вопрос: как одна задача разбивается на части, которые можно вести параллельно, и как эти части назначаются исполнителям.
Сюда входят: разбиение задачи на подзадачи с осмысленными границами; граф зависимостей между подзадачами (частичный порядок, критический путь); диспетчеризация и балансировка нагрузки между воркерами; динамическое порождение работы (подзадачи, рождающиеся в ходе исполнения); приоритеты и очереди; спекулятивное и избыточное исполнение; и сборка результатов обратно (fan-in, агрегация, верификация итога). Этому посвящена часть V.
Декомпозиция — уровень, на котором определяется потенциал параллелизма, а значит, и предел ускорения. Граф зависимостей подзадач задаёт критический путь — последовательную цепочку, которую нельзя распараллелить никаким числом агентов. Длина критического пути относительно общего объёма работы определяет, насколько вообще осмысленно множить исполнителей; это прямое следствие закона Амдала, к которому возвращается глава 56. У агентных систем последовательная доля велика — многие шаги по природе зависят от результатов предыдущих, — и это ограничивает выгоду от роя сильнее, чем кажется на старте.
Главный failure mode — декомпозиция, порождающая ложный параллелизм. Задача разбита на десять «независимых» частей, но при исполнении выясняется, что они делят общий ресурс или общий контекст, и параллельное исполнение либо сериализуется на узком месте (см. главу 57), либо приводит к конфликтам на уровне координации. Второй сбой — взрыв динамически порождаемой работы: агент-исполнитель сам создаёт подзадачи, те создают свои, и без ограничения рой генерирует экспоненциально растущее дерево работы, исчерпывая бюджет (см. главу 34).
Координация отвечает на вопрос: как согласовать параллельные действия многих агентов, чтобы они не противоречили друг другу. Это уровень, на котором живут самые трудные проблемы распределённых систем в применении к рою.
Сюда входят: проблема согласования распределённого состояния как таковая; консенсус и голосование агентов (кворум, majority); конфликты изменений и их разрешение (параллельные правки пересекающегося, merge); гонки за ресурсы и блокировки (single-writer); транзакции и атомарность многоагентных изменений (saga, компенсации); идемпотентность и безопасные повторы; противопоставление оркестрованной координации (явный дирижёр) и эмерджентной (самоорганизация); тупики и livelock. Этому посвящена часть VI.
Координация — это, по сути, и есть тот самый координационный налог из главы 5, выраженный на уровне механизмов. Каждый механизм согласования стоит: голосование требует запустить несколько агентов на одну задачу и сравнить результаты; блокировка сериализует доступ и убивает параллелизм; транзакция с компенсациями требует уметь откатывать уже сделанное. Чем сильнее гарантия согласованности, тем дороже координация. Значительная часть инженерного искусства здесь — выбрать минимальную достаточную гарантию, а не максимальную.
Координация неотделима от уровня состояния (следующего): согласовывать имеет смысл только то, что разделяется. Если агенты работают в полной изоляции (share-nothing, см. главу 54), координация на этапе исполнения почти не нужна — она сводится к сборке результатов в конце. Чем больше общего изменяемого состояния, тем тяжелее координация. Это ключевая связка двух уровней: проектирование состояния напрямую определяет цену координации.
Главные failure modes уровня — классические: гонки (два агента читают-меняют-пишут одно состояние, и одно изменение теряется), тупики (агенты взаимно ждут ресурсов друг друга), livelock (агенты непрерывно реагируют друг на друга, но не продвигаются — например, бесконечно передают задачу по кругу, каждый считая её чужой). Livelock у агентов опаснее, чем в обычных системах, потому что внешне выглядит как активность: рой что-то делает, тратит токены, но не сходится к результату (см. главы 45 и 74).
Состояние отвечает на вопрос: где живёт информация, которую система помнит, и как она согласована между агентами. Этот уровень стоит особняком, потому что он одновременно фундамент для координации сверху и для надёжности снизу.
Сюда входят: где физически живёт состояние (у каждого агента, в общем хранилище, в артефактах); передача контекста между агентами (handoff) и потери при ней; общая память против изолированной (shared против share-nothing); модели согласованности общего состояния (eventual против strong); эпизодическая и долговременная память роя; накопление и переиспользование знания между запусками; компрессия и дистилляция контекста; и отравление общей памяти. Этому посвящена часть VII.
Состояние — уровень, на котором решается, будет ли система надёжной в принципе. Распределённое изменяемое состояние — главный источник трудностей в любой распределённой системе, и рой агентов не исключение. Чем больше состояния разделяется и чем слабее его согласованность, тем больше путей у системы прийти в противоречивое положение. Обратная сторона: полная изоляция (каждый агент со своим контекстом, никакого общего изменяемого состояния) делает систему надёжной, но требует явной передачи контекста через handoff, а каждый handoff — это точка потери. Между этими полюсами лежит весь спектр инженерных компромиссов части VII.
Handoff — передача контекста от одного агента другому — заслуживает отдельного внимания как операция, которой у одного агента не было вовсе. Когда агент А завершает работу и передаёт её агенту Б, он должен упаковать в передачу всё, что Б нужно знать. Что-то неизбежно теряется: часть контекста осталась в «голове» А (в его истории рассуждений), но не попала в handoff. Б начинает с неполной картиной и не знает об этом. Накопление таких потерь по цепочке передач — характерный системный сбой, невидимый на уровне отдельной передачи и проявляющийся только на длинной цепочке (см. главу 47).
Главный failure mode уровня — отравление общего состояния. Один агент записал в общую память неверный факт (галлюцинацию, устаревшие данные, результат prompt injection), и этот факт распространяется: другие агенты читают его как истину и строят на нём свои действия. Поскольку агенты доверяют общему состоянию по умолчанию, ошибка не локализуется, а размножается. Это пересечение уровня состояния с уровнем безопасности: отравление может быть случайным (галлюцинация) или злонамеренным (инъекция), и защита в обоих случаях — локализация и проверка происхождения данных (см. главы 53 и 86).
Последние перед человеком три уровня — надёжность, наблюдаемость, безопасность — не добавляют системе новых функций, но определяют, выживет ли она в реальной эксплуатации. Это сквозные свойства, которые нельзя «прикрутить» в конце: они должны быть заложены в решения верхних уровней.
Надёжность отвечает на вопрос: что происходит, когда часть системы отказывает, и как ограничить последствия. У одного агента отказ означает просто неудачу задачи; у роя отказ одного узла может каскадом обрушить остальные или, наоборот, быть поглощён без последствий — в зависимости от того, как спроектирована надёжность.
Сюда входят: модель отказов роя (таксономия того, что и как ломается); последствия отказа отдельного агента и их локализация; паттерны устойчивости из распределённых систем (тайм-ауты, повторы, circuit breaker применительно к агентам); изоляция отказов (bulkhead — отсеки, ограничивающие распространение); восстановление и переподхват зависшей работы (перезапуск, lease, переназначение); частичные результаты и graceful degradation; зацикливание на уровне роя; и надёжность оркестратора как single point of failure. Этому посвящена часть X.
Надёжность роя строится из тех же паттернов, что и надёжность любой распределённой системы, но с двумя поправками на природу агентов. Первая: агент может отказать не явно (упасть, перестать отвечать), а тихо — продолжать работать, но выдавать неверные результаты. Тайм-аут ловит явный отказ; тихий отказ ловится только проверкой результата, то есть уходит на уровни ролей (ревьюер, критик) и координации (голосование). Вторая поправка: повтор у агента не идемпотентен по умолчанию — недетерминированная модель на повторный запрос может выдать другой ответ, и это одновременно проблема (нельзя просто «повторить и получить то же») и возможность (повтор может исправить случайную ошибку).