Проектирование управляемого runtime
Конкурентность агентов нужно управлять через инварианты, а не через процессы
Управляемая автономная организация должна решать, что можно выполнять параллельно, исходя из бизнес-инвариантов, которые затрагивает действие, а не из агентов или процессов, которые это действие выполняют.

Автономные организации будут терпеть неудачи не потому, что запускают слишком мало агентов одновременно. Они будут терпеть неудачи, когда отдельные авторизованные и локально разумные действия вместе создают недопустимый бизнес-результат.
В этом и состоит проблема конкурентности. Агент может иметь право одобрить возврат, зарезервировать товар, изменить настройку развёртывания или назначить дежурного инженера. Его рассуждение может быть корректным для состояния, которое он наблюдал. Второй агент может быть столь же правомочен и столь же корректен. Но оба действия могут опираться на один дефицитный ресурс, порог, правило разделения обязанностей или ограничение безопасности. Если они выполняются на пересекающихся или устаревших представлениях состояния, организация способна нарушить инвариант, хотя ни один участник не превысил своих полномочий.
Поэтому полезная единица контроля — не агент, промпт, очередь или процесс. Это бизнес-инвариант: условие, которое должно оставаться истинным при изменении состояния организации. Управление должно явно зафиксировать эти инварианты и на их основе определить, какие операции могут идти параллельно, какие обязаны подтвердить актуальное предусловие, а какие требуют единственного упорядоченного решения.
Начните с каталога инвариантов
Каталог инвариантов — это управляемая запись условий, которые действия обязаны сохранять. Например: принятые обязательства по расходам не превышают утверждённый бюджет; клиент не получает два взаимоисключающих предложения; численность дежурной смены не опускается ниже заданного минимума; один человек не может одновременно запросить и одобрить чувствительное изменение; суммарно обещанный по всем каналам товар не превышает доступный остаток.
Это точнее, чем схема процесса. Процесс говорит, что одна активность обычно следует за другой. Инвариант говорит, что должно быть истинно, даже если действия приходят от разных агентов, через разные инструменты, очереди или пути восстановления. Именно это нужно runtime, когда параллельная работа становится нормой, а не исключением.
Для каждой мутации каталог должен указывать затрагиваемые инварианты, состояние, прочитанное для принятия решения, границы состояния, которые покрывает каждый механизм защиты, и последствия невыполненного предусловия. Решение агента должно нести этот набор зависимостей: релевантные версии состояния, основание в политике и инварианты, от которых зависел предполагаемый эффект. Тогда на границе мутации runtime сможет проверить, остаются ли эти основания действительными.
Разделите операции на три режима исполнения
Каталог позволяет применить практическую классификацию. Она не требует глобальной сериализации, которая уничтожила бы значительную часть ценности автономного исполнения. Она требует координации только там, где её действительно требует корректность.
1. Без координации
Операция не требует координации, если параллельные исполнения и результат их слияния сохраняют релевантный инвариант. Формальный критерий инвариантной конфлюэнтности гласит: если все корректные независимые исполнения можно объединить с сохранением прикладного инварианта, координация для гарантии корректности не нужна.
Такие операции можно безопасно распараллеливать с учётом собственных правил авторизации и обработки эффектов. Вопрос не в том, различаются ли агенты. Вопрос в том, оставляет ли любое возможное сочетание их допустимых эффектов управляемое состояние допустимым.
2. Условный режим
Операция условна, когда она остаётся корректной, только если конкретное предположение о состоянии всё ещё верно в момент фиксации. Агент может установить, что изменение безопасно для версии объекта 41. Runtime не должен молча применять это решение к версии 42. На границе записи он должен потребовать проверки версии или предусловия состояния.
Один из знакомых механизмов — HTTP If-Match. RFC 9110 определяет, что он может предотвращать потерянные обновления: если переданный тег сущности не совпадает, сервер не должен выполнять запрошенный метод. Kubernetes применяет тот же базовый паттерн через resourceVersion и отклоняет устаревшее обновление объекта с HTTP 409 Conflict.
Но валидатор защищает только то состояние, которое он покрывает. ETag одной записи не может установить инвариант, охватывающий несколько записей, сервисов или инструментов. Для более широкого состояния условие нужно проверять там, где этот более широкий инвариант действительно может быть обеспечен.
3. Сериализованный режим
Операция должна быть сериализована, когда безопасного слияния нет, а корректность требует одного упорядоченного решения. Сюда могут относиться общий лимит, эксклюзивное распределение или ограничение между несколькими записями. Один из вариантов реализации в границах базы данных — сериализуемая изоляция: успешно зафиксированные конкурентные транзакции должны давать эффект, согласующийся с некоторым последовательным порядком их выполнения. PostgreSQL выявляет шаблоны, которые могли бы привести к аномалиям сериализации, прерывает транзакцию и требует от приложения повторной попытки.
Ключевое архитектурное решение — не просто включить сериализуемый режим базы данных. Нужно определить границу решения, которой требуется порядок. Изоляция в стиле снимков может допускать write skew: две транзакции читают допустимое состояние, делают непересекающиеся записи и вместе создают состояние, невозможное при последовательном исполнении. Именно такую ошибку организация получает, когда разные агенты принимают локально совместимые решения относительно одного бизнес-правила.
Считайте конфликт событием управления
Отклонённый compare-and-swap, HTTP 409, прерванная сериализуемая транзакция или неудавшееся резервирование не должны исчезать внутри общего цикла повторных попыток. Это означает, что свидетельства агента больше не обосновывают предполагаемый эффект либо другое допустимое действие уже заняло нужное состояние.
Runtime должен ограничивать число повторов, обновлять релевантные свидетельства и заново оценивать действие по текущей политике и состоянию. Повторяющиеся конфликты должны быть операционно наблюдаемы: они могут указывать на узкое место ёмкости, чрезмерно широкий инвариант, плохо разделённую работу или слишком частое нацеливание агентов на одну поверхность принятия решений. Журнал конфликтов — не просто данные для отладки. Это обратная связь о проектировании организации.
Параллелизм безопасен только тогда, когда организация может объяснить, почему совокупный эффект остаётся допустимым.
Не путайте конкурентность со смежными контролями
Авторизация отвечает на вопрос, может ли субъект выполнить действие. Она не доказывает совместимость двух авторизованных действий. Идемпотентность и обработка эффекта ровно один раз отвечают на вопрос, был ли продублирован один задуманный бизнес-эффект. Они не предотвращают решения на устаревшем состоянии, write skew или несовместимые обязательства. Все эти контроли необходимы автономному runtime, но они решают разные задачи.
Блокировки и аренды также требуют осторожности. Бывший владелец аренды, приостановленный на время, может продолжить работу после её истечения и попытаться записать данные. Сама по себе аренда не делает такую запись безопасной. Fencing tokens решают эту проблему: каждому захвату назначается монотонно возрастающий токен, а защищаемый ресурс обязан отклонять записи со старым токеном. Проверка должна находиться у ресурса, способного остановить эффект, а не только у координатора, выдавшего аренду.
Наконец, у сильной транзакции есть границы. Spanner прямо указывает, что его внутренние блокировки обеспечивают согласованность внутри базы данных, но не эксклюзивный доступ к внешним ресурсам. Транзакция БД сама по себе не делает платёжного провайдера, SaaS-платформу или физическое устройство частью того же атомарного действия. Межсистемные эффекты требуют явного протокола: резервирования, где оно возможно, долговечного намерения и сверки, условных API и управляемой компенсации, когда эффект уже нельзя предотвратить.
Сделайте политику исполнимой
Управляемый runtime должен встроить политику конкурентности в путь выполнения действия. До запуска он определяет релевантные инварианты и выбирает режим: без координации, условный или сериализованный. Агент создаёт предполагаемый эффект вместе с набором зависимостей. При фиксации runtime применяет нужный механизм — правила слияния, проверку версии, резервирование, сериализуемую транзакцию либо аренду с fencing token — и записывает результат.
Это меняет операционную модель. Команды больше не спорят абстрактно, можно ли агентам работать параллельно. Они определяют, какие бизнес-истины должны пережить параллельную работу, связывают их с мутациями и делают не подтвердившееся предположение видимым до того, как оно превратится в незаметный результат last-write-wins.
Цель не в том, чтобы замедлить организацию тотальной сериализацией. Цель — тратить координацию точно там, где её требуют инварианты, и позволять безопасной работе двигаться со скоростью машины.
Источники: Bailis и соавт., «Coordination Avoidance in Database Systems» (VLDB); документация PostgreSQL по изоляции транзакций и Serializable Snapshot Isolation; RFC 9110; Kubernetes API Concepts; материал Martin Kleppmann о fencing tokens; документация Google Cloud Spanner по транзакциям.

