Паттерны рассуждений и мультиагентная оркестрация enterprise-процессов 1С
Вторая статья цикла NOPik: почему линейный граф состояний не масштабируется на сложные сценарии, и как декомпозиция на роли (Супервайзер, Аналитик метаданных, Сборщик СКД) с паттернами ReAct и Tree-of-Thoughts решает эту проблему.
Целевая аудитория: Архитекторы решений 1С, ведущие разработчики, специалисты по интеграции ИИ.
Применимость: Внешний оркестратор NOPik (Python / LangGraph); контур 1С:Предприятие 8.3 не меняется относительно статьи 1.
Серия: NOPik - автономный ИИ-агент для 1С:Предприятие 8 (статья 2 из 7).
Репозиторий: https://github.com/NickScherbakov/nopik-articles-public
🔍 Диагностика: от линейного графа к ролям
В статье 1 цикла граф состояний NOPik был намеренно упрощен до линейной цепочки analyze_intent → plan_executor → deliver_to_1c. Такая цепочка наглядно демонстрирует переход от одного гигантского промпта к формальному FSM, но у нее есть системный недостаток: один узел plan_executor отвечает сразу за все прикладные сценарии - и построение отчета, и диагностику ошибки, и общий ответ. По мере роста числа сценариев этот узел неизбежно превращается в новую версию того самого «монолитного промпта», от которого мы уходили.
Решение - декомпозиция по ролям с явным супервайзером, а не наращивание ветвлений внутри одного узла: та же логика, что в микросервисной архитектуре - каждая роль отвечает за одну зону ответственности и не обязана знать о существовании соседних ролей.
📂 Структура: три роли NOPik
Начиная с этой статьи оркестратор NOPik построен вокруг трех ролей:
- Супервайзер (Supervisor) - единственный узел, которому разрешено видеть весь маршрут целиком. Классифицирует намерение пользователя и решает, какая роль обработает запрос дальше. Не выполняет прикладной работы сам.
- Аналитик метаданных (Metadata Analyst) - находит объекты метаданных 1С (справочники, регистры, реквизиты), релевантные запросу, работая по паттерну ReAct.
- Сборщик СКД (SKD Collector) - строит и «исполняет» отчет через Систему компоновки данных, работая по паттерну Tree-of-Thoughts.
Такое разделение прямо соответствует терминологии HSM из статьи 1: три роли образуют суперсостояние WORKING, а супервайзер реализует функцию переходов δ этого суперсостояния.
💻 Паттерн ReAct: Аналитик метаданных
ReAct (Reasoning + Acting) - паттерн, в котором рассуждение модели (Thought) перемежается с вызовом инструмента (Action) и анализом его результата (Observation), и цикл повторяется, пока не будет собрано достаточно информации.
Наивная реализация зашивает цикл while внутрь одной функции на Python - и тогда граф состояний перестает быть графом состояний, превращаясь обратно в скрытый монолитный скрипт с ИИ внутри. В NOPik цикл ReAct вынесен на уровень графа: каждый вызов узла metadata_analyst_node выполняет ровно один шаг Thought → Action → Observation, а решение «повторить, эскалировать или закончить» принимает conditional edge графа - route_from_metadata_analyst.
Guard, ограничивающий число итераций (MAX_REACT_STEPS = 3), - это тот самый Global Guard из теории HSM: лимит вешается один раз на уровне суперсостояния и защищает от бесконечного цикла «модель не нашла ответ - модель пробует снова с тем же результатом».
В боевой системе discover_metadata_tool обращается к MCP-серверу 1С за реальным списком объектов метаданных (протокол MCP - тема статьи 3 этого цикла); в текущей версии репозитория это детерминированный мок, чтобы граф переходов оставался полностью воспроизводимым в модульных тестах.
💻 Паттерн Tree-of-Thoughts: Сборщик СКД
Tree-of-Thoughts (ToT) - паттерн, в котором вместо последовательного уточнения одной гипотезы (как в ReAct) модель за один шаг порождает несколько альтернативных планов решения задачи, оценивает каждый и исполняет только план-победитель. Для построения отчета СКД это особенно оправдано: неверно угаданный макет компоновки данных нельзя «доуточнить» маленькими шагами - его нужно сравнивать с альтернативами целиком.
Если запрос перед этим прошел через Аналитика метаданных и тот нашел несколько объектов, оценка «детализированного» плана растет автоматически (0.9 против 0.7) - число найденных объектов метаданных напрямую влияет на выбор ветки дерева гипотез. Узел skd_collector_node берет план с максимальной оценкой и передает его в execute_skd_report_tool (в боевой системе - реальный вызов СКД через MCP-сервер).
💻 Сборка графа: супервайзер и conditional edges
LangGraph выражает ветвление не через if внутри узла, а через add_conditional_edges: узел меняет состояние, а отдельная чистая функция-маршрутизатор его читает и решает, куда идти дальше. Это разделение - ключевое отличие управляемого графа состояний от произвольного агентного скрипта.
Обратите внимание: узел skd_collector достижим двумя путями - напрямую от супервайзера (если намерение сразу однозначно про отчет) и через metadata_analyst (если сначала потребовалось найти объекты метаданных). Обе ветки сходятся в единственном терминальном узле deliver_to_1c, что сохраняет свойство FSM из статьи 1: терминальные состояния (F ⊆ S) должны быть предсказуемым и небольшим множеством, а не размазаны по графу.
🔍 Тестирование: маршрутизация графа
Поскольку узлы и маршрутизаторы - обычные чистые функции Python, весь граф проверяется модульными тестами pytest без обращения к реальному LLM или MCP-серверу: достаточно собрать AgentState и провалидировать, в какую роль ушел запрос и сколько шагов ReAct потребовалось.
Такой тест фиксирует именно то поведение, которое обещает Guard из теории HSM: агент не зависает в цикле ReAct навсегда, а после трех безуспешных попыток детерминированно передает управление дальше по графу.
🤝 Итоги: что дальше
Оба инструмента этой статьи - discover_metadata_tool и execute_skd_report_tool - сегодня являются моками. В статье 3 цикла они станут настоящими вызовами к MCP-серверу 1С: разберем протокол Model Context Protocol, валидацию ответов через Instructor/Pydantic, борьбу с нечувствительностью LLM к регистру имен объектов метаданных и генерацию кликабельных навигационных ссылок вида e1cib/data/... прямо в ответе агента.
Полный код ролей - в NOPik/orchestrator/graph/agents/ репозитория проекта.
Как в вашей практике решается баланс между глубиной цикла ReAct (сколько итераций уточнения допустимо) и стоимостью лишних вызовов LLM? Делитесь подходами в комментариях - обсудим в следующих статьях цикла.
Теги: LangGraph, Мультиагентные системы, ReAct, Tree-of-Thoughts, Граф состояний, Супервайзер, Оркестрация агентов, СКД, MCP, LLM, Enterprise AI, 1С:Предприятие 8.3, Python, NOPik, Автоматизация 1С, Иерархический автомат, HSM, FSM
Вступайте в нашу телеграмм-группу Инфостарт