18+
реклама
18+
Бургер менюБургер меню

Ранас Мукминов – Оркестрация ИИ-агентов. Claude Opus 4.7 (страница 73)

18

— Кто обязан действовать? Какая роль активируется в этой ситуации по контракту.

— Кто отвечает за результат? Чей выход считается итогом обработки этой ситуации.

— К кому обращаться при отказе? Куда эскалируется ситуация, если назначенная роль не справилась.

Хорошо спроектированная система даёт на все три вопроса ровно один ответ для каждой ситуации. Перекрытие — это два ответа на первый вопрос. Зазор — ноль ответов. Размытая ответственность — несовпадение ответов на первый и второй вопросы: действует одна роль, а отвечает другая или никто.

В терминах множеств идеальное распределение ответственности — это разбиение пространства ситуаций: объединение зон всех ролей покрывает всё пространство (полнота), а попарные пересечения зон пусты (непересекаемость). Полнота гарантирует отсутствие зазоров; непересекаемость гарантирует отсутствие перекрытий.

На практике ни то ни другое не достигается полностью, и важно понимать почему. Пространство ситуаций для агентной системы не перечислимо заранее: агенты работают с естественным языком и открытым миром, поэтому всегда возникают ситуации, которых не было ни в одном контракте. Это значит, что полное покрытие нельзя обеспечить статически — его нужно достраивать в рантайме через роль-перехватчик (об этом ниже). А непересекаемость конфликтует с отказоустойчивостью: иногда перекрытие вводят намеренно, чтобы ситуацию обработал хотя бы кто-то, если одна из ролей откажет. То есть и полнота, и непересекаемость — не абсолютные требования, а оси, по которым принимается осознанный компромисс.

Естественное состояние роя без проектирования границ — не чистое разбиение, а смесь перекрытий и зазоров одновременно. Причина в том, как обычно растут роли. Роль формулируется через её задачу («ты пишешь код», «ты проверяешь код»), а не через границу её зоны. Две роли, описанные через задачи, почти неизбежно пересекаются в формулировках («проверь, что код корректен» есть и у исполнителя как самопроверка, и у ревьюера как основная функция) и одновременно оставляют дыры (никто не описан как отвечающий за случай «код корректен, но не соответствует исходному запросу»). Граница — это то, что приходится проводить отдельно, поверх задач, и она требует явного решения для каждого стыка.

Рассмотрим обобщённый конвейер из четырёх ролей: планировщик разбивает запрос на подзадачи, исполнитель выполняет подзадачу, тестировщик проверяет результат, оркестратор собирает итог (пример иллюстративный, любые совпадения с конкретными системами случайны). На первый взгляд роли непересекающиеся и покрытие полное: каждая стадия передаёт следующей. Но если применить три вопроса о зоне ответственности к каждому стыку, картина меняется.

Стык «планировщик — исполнитель»: кто отвечает, что план выполним? Планировщик отвечает за то, что план составлен; исполнитель — за то, что подзадача выполнена. Выполнимость плана — между ними, в зазоре. Стык «исполнитель — тестировщик»: кто отвечает, что проверяется именно текущий результат исполнителя, а не устаревший? Это межролевой инвариант, и он ничей. Стык «тестировщик — оркестратор»: если тест не прошёл, кто решает — переделывать, эскалировать или отбросить подзадачу? Если это не закреплено, исход проваливается в зазор отказа. И сквозной вопрос: за то, что собранный итог соответствует исходному запросу (а не сумме корректно выполненных подзадач), формально не отвечает никто — планировщик уже забыл запрос, оркестратор видит только части.

Этот разбор показывает закономерность: роли, выглядящие как чистый конвейер, на деле оставляют зазоры ровно на стыках и на инвариантах, охватывающих несколько стадий. Ни один из этих зазоров не виден при проверке любой роли по отдельности — каждая корректна по своему контракту. Они видны только при взгляде на стыки, и именно туда направлена диагностика далее в главе.

Перекрытие — это участок пространства ситуаций, за который по контракту отвечают две роли или более. Перекрытия делятся на непреднамеренные (дефект проектирования) и преднамеренные (введённые ради надёжности). Различать их обязательно: лечить надо только первые, а вторые надо защищать от случайного устранения.

Двойная работа. Две роли выполняют одно и то же действие независимо. Планировщик декомпозирует задачу, и исполнитель, получив подзадачу, декомпозирует её повторно по-своему. Результат — потраченные токены и, что хуже, две несовпадающие декомпозиции, которые дальше расходятся. Двойная работа — самый дешёвый из вредов перекрытия: она лишь стоит денег и латентности, но не нарушает корректность напрямую.

Конфликт изменений. Две роли изменяют один и тот же ресурс. Это уже не просто трата: это гонка, исход которой зависит от порядка и тайминга (см. главу 41 о гонках за ресурсы и главу 40 о конфликтах изменений). Если исполнитель и роль-исправитель оба правят один файл, итог зависит от того, чей результат записался последним. Перекрытие по зоне записи — самый опасный класс перекрытия, потому что он напрямую ведёт к потере консистентности.

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

Циклы взаимной коррекции. Две роли с перекрывающейся зоной правки могут войти в цикл: роль A исправляет то, что считает дефектом, роль B возвращает обратно, считая дефектом исправление A. Это частный случай livelock на уровне роя (см. главу 74): система активна, тратит ресурсы, но не сходится. Перекрытие зон оценки («что считать правильным») — питательная среда для таких циклов.

Не всякое перекрытие — дефект. Иногда зоны намеренно пересекают, чтобы повысить вероятность, что ситуация будет обработана. Это плата за надёжность, и она оправдана в трёх случаях.

Первый — дублирование ради отказоустойчивости. Если отказ роли дорог, а ситуация критична, две роли могут независимо обрабатывать одну зону, чтобы хотя бы одна справилась. Это прямой аналог избыточного исполнения (см. главу 36): мы сознательно платим двойной работой за устойчивость к отказу одного исполнителя.

Второй — перекрытие как взаимная проверка. Ревьюер намеренно вторгается в зону исполнителя — перечитывает его работу. Это перекрытие по зоне чтения и оценки, но не по зоне записи. Ключ к безопасному преднамеренному перекрытию: пересекать можно зоны наблюдения и оценки, но не зоны изменения. Двое могут смотреть на один участок; писать в него должен один (принцип single-writer, см. главу 41).

Третий — эшелонированная защита. Несколько ролей проверяют одно и то же инвариантное условие на разных стадиях (исполнитель — при записи, тестировщик — после, оркестратор — перед сборкой). Перекрытие по проверке инварианта оправдано тем, что отказ любой одной проверки не пропускает нарушение. Здесь перекрытие — это глубина обороны, а не дефект.

Граница между вредным и полезным перекрытием проходит по двум осям: пересекаются ли зоны записи (опасно) или только зоны чтения и оценки (приемлемо), и введено ли перекрытие осознанно с назначенным арбитром (полезно) или возникло само из небрежной нарезки ролей (вредно).

Тип перекрытия | Что пересекается | Основной вред или польза | Проектное решение

Двойная декомпозиция/работа | Зона действия | Трата токенов, расходящиеся результаты | Закрепить действие за одной ролью

Конфликт записи | Зона изменения ресурса | Потеря консистентности, гонка | Single-writer, арбитр изменений

Размывание ответственности | Зона ответственности за итог | Пограничные ситуации не обрабатывает никто | Назначить единственного владельца итога

Цикл взаимной коррекции | Зона оценки правильности | Livelock, несходимость | Единый источник критерия, лимит итераций

Дублирование ради надёжности | Зона действия (намеренно) | Устойчивость к отказу исполнителя | Арбитр результата, дедупликация

Взаимная проверка | Зона чтения/оценки (намеренно) | Поимка ошибок | Запрет на пересечение зоны записи

Эшелонированная проверка инварианта | Зона проверки (намеренно) | Глубина обороны | Явный список стадий проверки

Зазор — это участок пространства ситуаций, за который не отвечает ни одна роль. Зазоры опаснее перекрытий по фундаментальной причине: перекрытие проявляется как лишняя активность (которую видно в трассировке и метриках), а зазор проявляется как отсутствие активности — ничего не происходит, ситуация молча проваливается. Отсутствие труднее заметить, чем избыток. Зазор — это отказ через бездействие.

Зазоры возникают не случайно, а в предсказуемых местах. Полезно знать их типологию, потому что искать зазор продуктивнее не перебором, а по местам, где он заводится.

Зазор на стыке ролей. Самый частый. Роль A заканчивает там, где, как она считает, начинается роль B; роль B начинает позже, чем заканчивает A. Между ними — необработанная полоса. Классический пример: планировщик произвёл план, исполнитель ждёт готовых подзадач, но никто не отвечает за валидацию того, что план вообще выполним и непротиворечив. План с дефектом уходит в исполнение, потому что валидация плана не была ничьей зоной.