Суть
Спор «агент или хардкод» обычно ведут как выбор одного из двух, хотя на деле это распределение ответственности. Агент хорош там, где нужно понять неструктурированный ввод, выбрать стратегию, сформулировать ответ. Код хорош там, где нужна воспроизводимость и аудит.
Гибридная оркестрация фиксирует это разделение архитектурно:
- Вероятностный слой — интерпретация запроса, подготовка данных, формулировка. Здесь допустима недетерминированность.
- Детерминированный слой — транзакции, вызовы API, проверка прав, переходы состояний. Здесь недетерминированность недопустима.
Взаимодействие идёт только через типизированные структуры: агент не «выполняет перевод денег», а возвращает валидированный объект с параметрами, который исполняет код (см. Structured Output).
Где оправдан
Финтех, управление складскими остатками — домены, где цена ошибки измеряется в деньгах и где регулятор спросит, почему система приняла именно это решение. Ответ «так решила модель» там не работает.
Уязвимость: spaghetti state machine
Обратная сторона — нарастание сложности детерминированного слоя. Бизнес-правила меняются, стейт-машина обрастает ветками и исключениями, и через год в ней невозможно разобраться. Проблема не новая, но здесь она усугубляется тем, что часть логики живёт в промптах, а часть — в коде, и граница со временем размывается.
Приём против этого: описывать граф переходов состояний декларативной конфигурацией (YAML или JSON), строго отделяя её от исполняемого кода. Тогда изменение бизнес-правила — это правка конфига, которую можно провести через ревью и версионировать отдельно от логики исполнения.
Пример устройства
Учебная реализация: маршрутизация обращений в поддержку. Состояние тикета описано Pydantic-моделью, узлы графа — обычные функции Python, а оркестратор — класс, который читает описание переходов и по нему двигает состояние. Модель вызывается только в узле-маршрутизаторе, который классифицирует обращение; дальнейшая обработка детерминирована.
Показательная деталь: для узла-классификатора температуру принудительно ставят в ноль. Маршрутизатор не должен «творчески» интерпретировать одинаковые входы по-разному — иначе воспроизводимость теряется на первом же шаге.
Что не отдают вероятностному слою и как это версионировать
Граница задаётся двумя признаками, а не списком. Первый — необратимость: всё, что нельзя отменить программно, решается детерминированно, и деньги с правами лишь самые заметные примеры; туда же попадают отправка наружу, удаление данных, изменение состояния внешних систем. Второй — выразимость правилом: если решение можно проверить кодом (принадлежность сущности, соблюдение лимита, соответствие каталогу), его отдают коду независимо от обратимости, потому что детерминированная проверка дешевле и не ошибается (Deterministic Veto). Модели остаётся то, что необратимым не является и правилом не выражается.
Версионирование. Граф переходов и промпты разъезжаются ровно потому, что их версионируют по отдельности. Лечится тем же приёмом, что и в релизах: версия — это связка, а не строка в коде — граф, промпты, модель и параметры выкатываются одним объектом конфигурации с общим идентификатором (Canary Release LLM, Feature Flags LLM). Тогда откат возвращает согласованный набор, а не половину.
Связано с
Mastra — композиция агента и процесса в обе стороны как штатная возможность фреймворка
Multi Agent Patterns — остальные паттерны предполагают, что решение принимает модель
Structured Output — типизированный контракт как граница между слоями
Human in the Loop — третий слой контроля там, где детерминизма недостаточно
Hierarchical Decomposition — способ удержать дорогое дерево под детерминированным контролем
Event Driven Agents — противоположный полюс: максимум автономии агентов