Автономный ИИ-агент "NOPik" для платформы 1С:Предприятие - от монолита к автономным агентам

21.09.26

Интеграция - WEB-интеграция

Представленные материалы открывают цикл статей о создании автономного ИИ-агента NOPik для экосистемы «1С:Предприятие», предлагая переход от примитивных чат-форм к сложной агентной архитектуре. Автор критикует «наивный» подход к интеграции LLM из-за его ненадежности, галлюцинаций моделей и блокировки пользовательских транзакций. Взамен предлагается концепция Zero-Footprint Core, где логика рассуждений вынесена за пределы учетной системы, а взаимодействие строится на базе конечных автоматов (FSM/HSM). Особое внимание уделено паттерну «Адаптер», который позволяет использовать ИИ уже сегодня через команды форм, сохраняя готовность к будущим обновлениям платформы. Источники также содержат практические рекомендации по DevOps-инструментам, таким как ibcmd и Git, для ускорения разработки интеллектуальных систем. В конечном итоге проект NOPik служит дорожной картой для внедрения мультиагентных систем в строгий корпоративный контур.

От монолита к автономным агентам: архитектура и граф состояний ИИ-агента в 1С

Первая статья цикла из 7 практических руководств по проектированию, разработке и промышленному внедрению автономных мультиагентных систем в корпоративном контуре «1С:Предприятие 8» на примере открытого проекта NOPik.

Целевая аудитория: Архитекторы решений 1С, ведущие разработчики, руководители ИТ-отделов, специалисты по интеграции ИИ.
Применимость: 1С:Предприятие 8.3 (не ниже 8.3.20), любая типовая конфигурация (ERP, УТ, КА, УНФ, БП, ЗУП). Точка входа подключается через сменный адаптер: «Команда формы» работает уже сегодня, адаптер на основе объекта «Бот» Системы взаимодействия - начиная с платформы 8.5.5 (пока не выпущена, см. раздел «Точка входа»).
Серия: NOPik - автономный ИИ-агент для 1С:Предприятие 8 (статья 1 из 7).

Репозиторий: https://github.com/NickScherbakov/nopik-articles-public

🔍 Введение: кризис наивного вайб-кодинга в Enterprise

Первая волна энтузиазма вокруг больших языковых моделей (LLM) в сообществе 1С породила десятки однотипных решений: внешняя обработка, на форму которой выведено поле ввода промпта, многострочное текстовое поле ответа и кнопка, отправляющая синхронный HTTP-запрос к публичному API нейросети.

В реальном корпоративном секторе такой подход терпит немедленный крах по четырем причинам.

  1. Иллюзия агентности (Stateless Predictor vs Stateful Agent). Сама по себе языковая модель - это статический вероятностный предсказатель следующего токена. У нее нет ни долгосрочной памяти, ни воли, ни внутреннего детерминированного состояния. Попытка возложить на один гигантский промпт («Ты ведущий эксперт 1С, проверь остатки, сформируй проводки и создай документ») приводит к катастрофическому росту контекста, галлюцинациям в именах реквизитов и нарушению ссылочной целостности базы.
  2. Закон Люссера: падение надежности цепочки шагов. Согласно закону Люссера, надежность последовательной системы равна произведению надежностей каждого ее элемента: R_sys = R_1 × R_2 × ... × R_n. Если на каждом шаге вероятность корректного ответа модели составляет даже 90% (0.9), то цепочка всего из 5 невалидируемых шагов завершится успехом с вероятностью менее 60% (0.9^5 ≈ 0.59). В контуре бухгалтерского или складского учета такая погрешность недопустима: за долей несошедшихся цепочек стоят не абстрактные проценты, а неверные проводки и расхождения в остатках.
  3. Хрупкость кастомных интерфейсов (UI Fragmentation). Попытки встроить в форму 1С веб-документ (HTML/JS/React WebView) для имитации чата приводят к постоянным сбоям: несовместимость движков рендеринга на разных ОС (Windows, Linux-дистрибутивы Astra/RED OS), проблемы с пробросом событий через document.location и сломанная верстка при обновлении платформы.
  4. Нарушение транзакционной изоляции. Синхронное ожидание ответа модели внутри сеанса пользователя 1С блокирует интерфейс, вызывает клиентские таймауты и создает риск зависания транзакций при сетевых лагах.

Чтобы преодолеть эти ограничения, необходим переход от монолитных скриптов к системной инженерии автономных агентов, где модель помещена внутрь строгого математического автомата состояний, отделена от прикладных данных протокольными контрактами и встроена в нативные механизмы платформы.

🎯 Архитектурный манифест: проект NOPik

В качестве сквозного демонстрационного проекта цикла мы берем архитектуру NOPik - корпоративного ИИ-агента. Исходный код расширения и примеры оркестратора публикуются в открытом репозитории проекта.

Фундаментальный принцип NOPik - «Zero-Footprint Core» (минимальный след в целевой конфигурации): внутри контура 1С:Предприятие живет только точка входа - сменный адаптер и пара обслуживающих модулей - а вся оркестрация, память и рассуждение вынесены за периметр учетной системы. Сам адаптер не фиксирован жестко: единый программный контракт приема сообщений реализован в общем модуле, а способ его физического вызова - через объект «Бот» или через команду формы - подключается отдельно (подробности - в разделе «Точка входа» ниже).

Три контура архитектуры NOPik Схема
Контур 1С:Предприятие (Zero-Footprint)
Пользователь (тонкий / веб / мобильный клиент) → адаптер точки входа (сегодня - команда формы; с 8.5.5 - объект «Бот» Системы взаимодействия) → единый контракт приема сообщений (~30 строк BSL)
HTTP POST: JSON Payload + TraceID
Реальный внешний сервис (nopikreport.com/api/ask)
Синхронный RAG-ответ на вопрос (Vertex AI Discovery Engine) - живой, работающий сервис, а не часть кода этого цикла
запросы к данным через Tools
Протокольный контур MCP (Model Context Protocol)
MCP-сервер 1С: метаданные, безопасное чтение через СКД
Схема. Три контура архитектуры NOPik и точки пересечения по сети

Такое разделение убирает из контура 1С любую бизнес-логику, специфичную для ИИ, и позволяет обновлять «мозг» агента, не трогая продуктивную базу.

📂 Точка входа: адаптерный слой вместо жесткой привязки к объекту «Бот»

В платформе «1С:Предприятие 8.3» существует штатный объект дерева метаданных Общие → Боты. У него есть реальные преимущества как у точки входа: нативность (пользователь общается с агентом в стандартном окне обсуждений, рядом с коллегами и привязанными к документам чатами - одинаково в тонком клиенте на Windows и Linux, в браузере и в мобильном клиенте) и готовый контекст обсуждения (бота можно тегать через @NOPik в чате конкретного заказа, где агент сразу получает ИдентификаторОбсуждения и ссылку на объект).

Но у этого преимущества есть срок начала действия, который честно нужно назвать: для расширений конфигурации (CFE) объект «Бот» становится доступен только начиная с платформы 8.5.5 - на момент публикации эта версия еще не вышла (по объявленному 1С плану выпуск ожидается во второй половине 2026 года, а массовое распространение на типовых конфигурациях - позже). До этого момента объект «Бот» существует только в основной конфигурации (CF), а не в расширении, и жесткая привязка к нему в расширении делает цикл нерабочим прямо сейчас. Проверено эмпирически на платформе 8.3.27.2130: пункт «Добавить» для объекта «Боты» в дереве расширения недоступен независимо от режима совместимости.

Решение - не ждать 8.5.5 и не снимать конфигурацию с поддержки ради обхода, а развязать точку входа от бизнес-логики через адаптерный слой. Весь прием сообщения сведен к одному программному контракту в общем модуле НОПик_Сеть:

НОПик_Сеть.ПоставитьЗадачуНаОтправку(АвторID, ТекстСообщения, ИдентификаторОбсуждения = "")

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

  • «Команда формы» (доступен уже сейчас). Общая команда НОПик_СпроситьАгента запрашивает у пользователя текст сообщения стандартным диалогом ввода строки и передает его в тот же контракт. Не требует объекта «Бот», работает на любой поддерживаемой версии платформы, устанавливается и проверяется в тестовой базе за минуты.
  • «Бот» Системы взаимодействия (с 8.5.5). Код обработчика сообщений уже написан и лежит в расширении - он активируется как только целевая платформа и конфигурация подтвердят поддержку 8.5.5, без изменения контракта и без переписывания оркестратора.

Такое разделение - пример разрешения противоречия «точка входа должна быть объектом «Бот» и одновременно не может им быть» через отделение способа доставки сообщения от бизнес-логики его обработки, а не через компромисс или ожидание. Один и тот же прием применяется в цикле еще как минимум дважды: в изоляции MCP-контура от специфики 1С и в Circuit Breaker, отделяющем доступность сети от бизнес-логики (см. статьи 3 и 5).

🎯 Теория управления агентом: граф состояний FSM и HSM

Отличие Predictor от Agent

Агентная система возникает только тогда, когда рассуждение модели связывается с циклом действий и обратной связи из среды: c(t+1) = (c_t, a_t, o_t), где a_t - действие в среде (вызов инструмента/API) или рассуждение (мысль/план), а o_t - наблюдаемый отклик среды (ошибка компиляции, результат SQL/BSL-запроса, ответ пользователя).

Чтобы агент не уходил в бесконечные циклы и сохранял управляемость, его поведение моделируется в виде конечного автомата состояний (Finite State Machine, FSM), описываемого кортежем M = (S, Σ, δ, s_0, F), где:

  • S - конечное множество состояний агента (например: RECEIVE, PLAN, CALL_TOOL, VERIFY, RESPOND);
  • Σ - входной алфавит событий (получено сообщение, инструмент вернул данные, ошибка валидации, отказ пользователя);
  • δ: S × Σ → S - функция переходов между состояниями с предикатами защиты (Guards);
  • s_0 ∈ S - начальное состояние (IDLE / RECEIVE);
  • F ⊆ S - терминальные состояния (RESPOND, ABORT).

Переход к иерархическим автоматам (HSM)

Для сложных сценариев плоский FSM приводит к взрывному росту числа связей («спагетти-маршрутизация»). В архитектуре NOPik мы используем иерархический автомат состояний (Hierarchical State Machine, HSM). В HSM состояния могут быть сгруппированы в суперсостояния (Superstates):

  • Суперсостояние WORKING объединяет подсостояния ANALYZE_METADATA, COMPOSE_QUERY, EXECUTE_READ.
  • Общие политики (Global Guards). Лимиты токенов, тайм-ауты транзакций и контуры безопасности (Circuit Breakers) вешаются на суперсостояние один раз и наследуются всеми дочерними узлами.
  • Чекпоинтинг (Deep History). Маркер состояния сохраняет снимок контекста на диск/в БД. Если на шаге 4 из 6 произошел сбой сети или падение сервиса, выполнение возобновляется ровно с контрольной точки шага 4, не требуя повторных затрат на предшествующие вызовы LLM.

💻 Инфраструктура разработки: от монолита к Git и ibcmd

Разработка ИИ-агентов требует высокой скорости итерирования. Классическая схема «Конфигуратор → Сохранить → Обновить конфигурацию БД» здесь неприменима: она медленная и не автоматизируется скриптами агентов.

Конфигурация расширения версионируется в формате открытых иерархических файлов (XML/JSON/BSL) — том же, что дают штатная выгрузка конфигурации в файлы средствами платформы и 1C:EDT:

Структура репозитория NOPik: адаптерный слой (CommonModules, CommonCommands, Constants, HTTPServices) и объект Бот

Вместо запуска тяжелого графического Конфигуратора для применения изменений используется утилита командной строки ibcmd, доступная в дистрибутивах платформы 8.3. Для частичной накатки изменений из Git-репозитория в тестовую базу выполняется скрипт:

Bash — deploy_partial.sh UTF-8 CLI
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env bash
set -e

IB_PATH="/var/1c/bases/test_db"
SRC_PATH="./src"

# Частичная загрузка измененных исходников в информационную базу
ibcmd infobase config import \
    --data-dir="${IB_PATH}" \
    --src-dir="${SRC_PATH}" \
    --partial

echo "Изменения успешно применены через ibcmd без блокировки Конфигуратора."

При работе в ОС Linux (или WSL2 под Windows) критически важно задать локальную настройку Git, исключающую экранирование кириллических путей к объектам метаданных 1С: git config core.quotepath false.

💻 Практическая реализация: модуль бота в 1С

Создадим расширение со свойствами:

  • Имя: NOPik
  • Префикс: НОПик_
  • Назначение: Дополнение
  • Режим совместимости: Соответствует основной конфигурации (не ниже 8.3.20).
Дерево расширения NOPik в Конфигураторе Дерево расширения NOPik в Конфигураторе 1С: реальные общие модули (НОПик_КлиентСервер, НОПик_Сеть, НОПик_СКД) под настоящим кириллическим префиксом расширения «НОПик_», пустая ветка «Боты» - платформенное ограничение до 8.5.5, общая команда НОПик_СпроситьАгента, HTTP-сервис НОПик_СервисСКД.

Ниже - модуль адаптера «Бот»: Общие → Боты → НОПик в дереве метаданных расширения. Напоминание из раздела «Точка входа» выше: этот объект физически создается в расширении начиная с платформы 8.5.5. Код приведен как целевая реализация адаптера и уже лежит в репозитории проекта; для проверки цикла на текущей платформе используйте адаптер «Команда формы» (код - сразу после этого блока).

Обратите внимание, насколько тонкий этот модуль: он не собирает контекст запроса сам, а лишь извлекает из объекта «Сообщение обсуждения» три значения (автора, текст, идентификатор обсуждения) и передает их в единый контракт общего модуля НОПик_Сеть - тот же самый, которым пользуется адаптер «Команда формы».

BSL - Bots/НОПик/Ext/Module.bsl UTF-8 Открыть файл
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Обслуживание Системы взаимодействия для агента NOPik
#Область ОбработчикиСобытий

// Основная точка входа для обработки сообщений, адресованных боту
Процедура ОбработкаСообщения(Сообщение, Отказ) Экспорт

    // Guard-клауза вынесена в НОПик_КлиентСервер отдельной чистой функцией,
    // чтобы ее можно было покрыть модульным тестом без объекта "Сообщение
    // обсуждения" и без полноценного сеанса 1С (см. Tests/YAxUnit)
    Если НОПик_КлиентСервер.ЭтоСобственноеСообщениеБота(Сообщение.Автор, ПользователиИнформационнойБазы.ТекущийПользователь()) Тогда
        Возврат;
    КонецЕсли;

    // Адаптер «Бот» лишь извлекает (автор, текст, обсуждение) из своего
    // родного события и передает их в единый контракт НОПик_Сеть - тот же,
    // которым пользуется адаптер «Команда формы» (см. НОПик_КлиентСервер)
    НОПик_Сеть.ПоставитьЗадачуНаОтправку(
        Строка(Сообщение.Автор),
        Сообщение.Текст,
        Строка(Сообщение.ИдентификаторОбсуждения),
        Сообщение.Обсуждение
    );

КонецПроцедуры

#КонецОбласти

А вот адаптер «Команда формы» - тот, который можно проверить прямо сейчас, без ожидания 8.5.5. Общая команда НОПик_СпроситьАгента запрашивает текст сообщения стандартным диалогом ввода строки и передает его через клиент-серверный модуль НОПик_КлиентСервер в тот же контракт НОПик_Сеть.ПоставитьЗадачуНаОтправку:

BSL - CommonModules/НОПик_КлиентСервер/Ext/Module.bsl (фрагмент) UTF-8 Открыть файл
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Адаптер «Команда формы»: работает на любой платформе уже сегодня, без
// объекта метаданных «Бот» (тот появится в расширениях только с 8.5.5)
&НаКлиенте
Процедура ЗапроситьИОтправитьСообщение() Экспорт
    Оповещение = Новый ОписаниеОповещения("ПослеВводаСообщенияНОПик", НОПик_КлиентСервер);
    ПоказатьВводСтроки(Оповещение, "", "NOPik: сообщение агенту", 500);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВводаСообщенияНОПик(РезультатВвода, ДополнительныеПараметры) Экспорт
    Если РезультатВвода = Неопределено Или ПустаяСтрока(РезультатВвода) Тогда
        Возврат;
    КонецЕсли;
    НОПик_Сеть.ОтправитьСообщениеФормыНаСервере(РезультатВвода);
КонецПроцедуры

&НаСервере
Процедура ОтправитьСообщениеФормыНаСервере(ТекстСообщения) Экспорт
    НОПик_Сеть.ПоставитьЗадачуНаОтправку(
        Строка(ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор),
        ТекстСообщения,
        "form-adapter"
    );
КонецПроцедуры
Процедура ОтправитьВнешнемуАгенту, финальный код Процедура ОтправитьВнешнемуАгенту в Конфигураторе - финальный код после живого тестирования: второй параметр Истина у ПрочитатьJSON (баг №6 из раздела «Живое тестирование» ниже).

Оба фрагмента выше показаны уже в финальном, исправленном виде. Первая версия компилировалась без единой ошибки («Проверка модулей» в Конфигураторе - синтаксический контроль, не выполнение) и выглядела корректной на бумаге. Реальный прогон в 1С:Предприятии вскрыл 6 runtime-ошибок, которые статический контроль платформы не поймал ни разу - полный разбор, с точными формулировками ошибок и скриншотами живого выполнения, в разделе «Живое тестирование» ниже. Модуль на стороне сервера (CommonModules/НОПик_Сеть/Module.bsl) обращается к настоящему, действующему сервису nopikreport.com/api/ask - без ключа авторизации, с ответом за десятки секунд (замерено живым вызовом - 42 секунды на простом вопросе), а не быстрым подтверждением приема: таймаут HTTP-соединения выставлен в 90 секунд именно поэтому. Полученный ответ фоновое задание публикует обратно в то же обсуждение Системы взаимодействия, из которого пришел вопрос.

BSL — CommonModules/НОПик_Сеть/Module.bsl UTF-8 Открыть файл
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#Область ПрограммныйИнтерфейс

// Единая точка входа контракта адаптеров: любой способ доставки сообщения в
// контур 1С (объект «Бот» Системы взаимодействия, общая команда формы или,
// в будущем, любой другой адаптер) сводится к этим параметрам и здесь
// становится одинаковой асинхронной задачей отправки во внешний сервис.
//
// Параметры:
//  АвторID              - Строка - идентификатор автора сообщения в
//                          терминах адаптера-вызывающей стороны.
//  ТекстСообщения        - Строка - текст сообщения пользователя.
//  ИдентификаторОбсуждения - Строка - идентификатор диалога/треда, если
//                          у адаптера есть такое понятие (по умолчанию "").
//  ОбъектОбсуждения     - СправочникСсылка.Обсуждения / Неопределено -
//                          реальная ссылка на обсуждение, если адаптер её
//                          предоставляет - используется для доставки
//                          ответа обратно в чат. У адаптера «Команда формы»
//                          такого объекта нет: доставка ответа для него не
//                          входит в объем этой задачи, ответ только
//                          протоколируется в журнале регистрации.
Процедура ПоставитьЗадачуНаОтправку(АвторID, ТекстСообщения, ИдентификаторОбсуждения = "", ОбъектОбсуждения = Неопределено) Экспорт

    КонтекстЗапроса = Новый Структура;
    КонтекстЗапроса.Вставить("MessageID",        Строка(Новый УникальныйИдентификатор));
    КонтекстЗапроса.Вставить("ConversationID",   ИдентификаторОбсуждения);
    КонтекстЗапроса.Вставить("AuthorID",         АвторID);
    КонтекстЗапроса.Вставить("Text",             ТекстСообщения);
    КонтекстЗапроса.Вставить("Timestamp",        Формат(ТекущаяУниверсальнаяДатаВМиллисекундах(), "ЧГ=0"));
    КонтекстЗапроса.Вставить("TraceID",          НОПик_КлиентСервер.НовыйTraceID());
    КонтекстЗапроса.Вставить("ОбъектОбсуждения", ОбъектОбсуждения);

    // Передача обработки в асинхронный фоновый контур: реальный ответ
    // nopikreport.com приходит синхронно, но за десятки секунд (замерено
    // живым вызовом - 42 сек на простом вопросе) - недопустимо ждать этого
    // в сеансе пользователя.
    ФоновыеЗадания.Выполнить(
        "НОПик_Сеть.ОтправитьВнешнемуАгенту",
        ПараметрыЗадания = Новый Массив; ПараметрыЗадания.Добавить(КонтекстЗапроса);
        ПараметрыЗадания,
        КонтекстЗапроса.TraceID,
        "NOPik: Запрос к nopikreport.com"
    );

КонецПроцедуры

// Процедура выполняется в фоновом задании.
//
// Реальный контракт nopikreport.com (проверено живым HTTP-вызовом
// 2026-09-17): POST на голый домен (без "api." поддомена - тот не отвечает
// по TLS), без ключа авторизации, синхронный ответ с готовым текстом за
// 40+ секунд, а не быстрый 202 Accepted, как предполагалось раньше.
Процедура ОтправитьВнешнемуАгенту(ПараметрыЗапроса) Экспорт

    СерверБэкенда = "nopikreport.com";
    Ресурс        = "/api/ask";

    ТелоЗапроса = Новый Структура;
    ТелоЗапроса.Вставить("question", ПараметрыЗапроса.Text);
    // "utmp" - реальное значение, разбирающееся backend'ом в движок
    // "1c-code-intelligence-engine" (код+руководства 1С). Любое нераспознанное
    // значение backend молча трактует как продукт по умолчанию "buh" -
    // бухгалтерский движок. Проверено сравнением источников ответа на один
    // и тот же вопрос при разных product (2026-09-17).
    ТелоЗапроса.Вставить("product",  "utmp");

    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, ТелоЗапроса);
    ТелоJSON = ЗаписьJSON.Закрыть();

    HTTPЗапрос = Новый HTTPЗапрос(Ресурс);
    HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
    HTTPЗапрос.Заголовки.Вставить("X-Trace-ID", ПараметрыЗапроса.TraceID);
    HTTPЗапрос.УстановитьТелоИзСтроки(ТелоJSON, КодировкаТекста.UTF8);

    Попытка
        HTTPСоединение = Новый HTTPСоединение(
            СерверБэкенда,
            443,
            ,,,
            90, // Реальный замер - 42 сек на простом вопросе, запас на более сложные
            Новый ЗащищенноеСоединениеOpenSSL()
        );

        Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);

        Если Ответ.КодСостояния <> 200 Тогда
            ЗаписьЖурналаРегистрации(
                "NOPik.Сеть",
                УровеньЖурналаРегистрации.Предупреждение,,,
                СтрШаблон("Ошибка бэкенда nopikreport.com. Код: %1, Ответ: %2", Ответ.КодСостояния, Ответ.ПолучитьТелоКакСтроку())
            );
            Возврат;
        КонецЕсли;

        ЧтениеJSON = Новый ЧтениеJSON;
        ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
        РезультатОтвета = ПрочитатьJSON(ЧтениеJSON, Истина);
        ЧтениеJSON.Закрыть();

        ТекстОтвета = РезультатОтвета.Получить("answer");

        ЗаписьЖурналаРегистрации(
            "NOPik.Сеть",
            УровеньЖурналаРегистрации.Информация,,,
            СтрШаблон("Ответ nopikreport.com получен (tier=%1, source=%2)",
                РезультатОтвета.Получить("tier"), РезультатОтвета.Получить("source"))
        );

        ДоставитьОтветВОбсуждение(ПараметрыЗапроса, ТекстОтвета);

    Исключение
        ИнформацияОбОшибке = ИнформацияОбОшибке();
        ЗаписьЖурналаРегистрации(
            "NOPik.Сеть",
            УровеньЖурналаРегистрации.Ошибка,,,
            ПодробноеПредставлениеОшибки(ИнформацияОбОшибке)
        );
    КонецПопытки;

КонецПроцедуры

// Публикует готовый текст ответа обратно в чат пользователя.
//
// Работает только когда адаптер передал реальную ссылку на обсуждение
// (сегодня - адаптер «Бот»; сам объект «Бот» недоступен на этой платформе
// до 8.5.5, поэтому вызов СистемаВзаимодействия.СоздатьСообщение НЕ
// проверен живым выполнением - только компилятором). У адаптера «Команда
// формы» обсуждения нет: синхронное уведомление пользователя для него не
// входит в объем этой задачи, ответ остается только в журнале регистрации.
Процедура ДоставитьОтветВОбсуждение(ПараметрыЗапроса, ТекстОтвета)

    ОбъектОбсуждения = ПараметрыЗапроса.ОбъектОбсуждения;

    Если ОбъектОбсуждения = Неопределено Тогда
        Возврат;
    КонецЕсли;

    ОтветСообщения = СистемаВзаимодействия.СоздатьСообщение(ОбъектОбсуждения);
    ОтветСообщения.Текст = ТекстОтвета;
    ОтветСообщения.Записать();

КонецПроцедуры

#КонецОбласти

🧪 Живое тестирование: 6 runtime-ошибок, которые не поймал компилятор

Код выше - уже финальная версия. Первая версия компилировалась в Конфигураторе без единой ошибки («Проверка модулей» - синтаксический контроль, не выполнение) и выглядела правильной на бумаге. Реальный прогон в 1С:Предприятии - не в Конфигураторе - вскрыл 6 отдельных ошибок, ни одну из которых статический контроль платформы не поймал: все они проявляются только в runtime, потому что связаны с типизацией, которая определяется во время исполнения, а не во время компиляции.

  1. Ссылка вместо Неопределено. Новый ОписаниеОповещения("Обработчик", Неопределено) падает с «Ошибка при вызове конструктора» - конструктору нужна настоящая ссылка на модуль, где определена процедура-обработчик.
  2. Клиент не может вызвать серверную процедуру двухконтекстного модуля по имени. Платформа резолвит такой вызов к клиентскому экземпляру модуля, где серверных методов нет вообще - «Метод объекта не обнаружен» в runtime. Рабочий паттерн - чисто серверный модуль (ВызовСервера = Истина), вызываемый с клиента напрямую по имени.
  3. УникальныйИдентификатор - свойство, не метод. Вызов со скобками, ...ТекущийПользователь().УникальныйИдентификатор(), падает с «Метод объекта не обнаружен» - скобки нужно убрать.
  4. Конструктору Массив нужно число, а не объект. Новый Массив(КонтекстЗапроса) падает с «Ошибка при вызове конструктора» - единственный позиционный параметр конструктора Массив - это размерность, а не элемент. Массив параметров собирается через .Добавить().
  5. Позиционные параметры HTTPСоединение сдвигают Таймаут. Пропуск одной лишней запятой при пропуске необязательных параметров (Сервер, Порт, Пользователь, Пароль, ИнтернетПрокси, Таймаут, ЗащищенноеСоединение, ...) сдвигает значение 90 в позицию ЗащищенноеСоединение, а объект ЗащищенноеСоединениеOpenSSL - в позицию ИспользоватьАутентификациюОС. Платформа ловит это только в runtime как «Конструктор не найден», потому что позиционные параметры типизируются во время исполнения.
  6. ПрочитатьJSON без второго параметра возвращает Структуру, а не Соответствие. У Структуры метода Получить(Ключ) нет вообще - вызов РезультатОтвета.Получить("answer") падает с «Метод объекта не обнаружен». Второй параметр Истина заставляет читать JSON-объекты как Соответствие, у которого этот метод есть.

Каждая ошибка найдена и исправлена по одной и той же схеме: реальный клик «NOPik: Спросить агента» в открытом сеансе 1С:Предприятия → «Метод объекта не обнаружен» / «Ошибка при вызове конструктора» в Журнале регистрации с номером строки модуля → правка → повторный клик. Ниже - скриншоты этого цикла на последней, успешной итерации.

Раздел NOPik в 1С:Предприятии 1С:Предприятие, живой сеанс: раздел «NOPik» с командой «NOPik: Спросить агента» - появился в командном интерфейсе только после добавления Подсистемы (см. раздел выше про роли и командный интерфейс).
Диалог ввода сообщения агенту Диалог адаптера «Команда формы»: реальный пользовательский ввод перед отправкой в фоновое задание.
Чистый возврат без ошибок после отправки Чистый возврат к странице «Информация» без диалога ошибки - все клиентские и раннесерверные баги из списка выше действительно устранены.
Журнал регистрации: успешный ответ nopikreport.com Журнал регистрации Конфигуратора, ~86 секунд после клика: «Ответ nopikreport.com получен (tier=1, source=vertex)» - фоновое задание реально дошло до nopikreport.com/api/ask и разобрало ответ. Это единственное надежное доказательство успеха для адаптера «Команда формы»: он не выводит ответ обратно в интерфейс, только протоколирует (см. ограничение выше про адаптер «Бот»).

Честное ограничение: адаптер «Команда формы» не показывает текст ответа пользователю - он существует ровно для того, чтобы можно было проверить всю цепочку до появления объекта метаданных «Бот» в 8.5.5. Единственное наблюдаемое сегодня доказательство успеха - запись в Журнале регистрации выше. Когда «Бот» станет доступен, тот же контракт НОПик_Сеть.ПоставитьЗадачуНаОтправку доставит текст ответа прямо в чат Системы взаимодействия - код для этого уже написан и ждет платформы (см. Bots/НОПик/Ext/Module.bsl).

💻 Учебная ветка: свой оркестратор на Python и LangGraph

Важное уточнение, прежде чем читать этот раздел: то, что сейчас реально отвечает на сообщение бота - живой сервис nopikreport.com, показанный в разделе выше, а не граф ниже. Этот граф - не описание того, что происходит на стороне nopikreport.com (туда мы не заглядываем и не должны), а самостоятельный учебный путь: как построить свой оркестратор, если вам нужна логика поверх ваших собственных данных 1С (а не общий вопрос, на который отвечает готовый сервис). Ниже - минимальная, но полностью функциональная архитектурная реализация графа FSM такого агента на базе Python и контрактов Pydantic; она не подключена к боевому пути и развивается отдельно в следующих статьях цикла.

Ключевые узлы графа:

  • analyze_intent_node - определяет намерение пользователя (построение отчета, диагностика ошибки, общий вопрос) и формирует план шагов;
  • plan_executor_node - выполняет сформированный план и готовит текст ответа;
  • deliver_to_1c_node - отправляет ответ обратно в Систему взаимодействия 1С через обратный webhook.
Python — граф состояний оркестратора (LangGraph) UTF-8 Открыть файл
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from typing import TypedDict, Annotated, Literal
from pydantic import BaseModel, Field
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver

# 1. Схема входного контракта сообщения из 1С
class Incoming1CMessage(BaseModel):
    message_id: str = Field(..., alias="MessageID")
    conversation_id: str = Field(..., alias="ConversationID")
    author_id: str = Field(..., alias="AuthorID")
    text: str = Field(..., alias="Text")
    trace_id: str = Field(..., alias="TraceID")

# 2. Состояние агента (граф состояний FSM)
class AgentState(TypedDict):
    conversation_id: str
    trace_id: str
    user_query: str
    intent: str
    plan: list[str]
    current_step: int
    final_response: str
    error: str | None

# 3. Узлы графа состояний (Nodes)
def analyze_intent_node(state: AgentState) -> dict:
    """Определение намерения пользователя: отчет, анализ ошибки, консультация."""
    query = state["user_query"].lower()

    if "остат" in query or "склад" in query or "отчет" in query:
        return {"intent": "REPORT_GENERATION", "plan": ["DISCOVER_METADATA", "BUILD_QUERY", "EXECUTE"]}
    elif "ошибка" in query or "лог" in query or "журнал" in query:
        return {"intent": "DIAGNOSTICS", "plan": ["READ_EVENT_LOG", "ANALYZE_TRACE"]}
    else:
        return {"intent": "GENERAL_QUERY", "plan": ["GENERATE_ANSWER"]}

def plan_executor_node(state: AgentState) -> dict:
    """Выполнение сформированного плана действий."""
    intent = state["intent"]
    if intent == "REPORT_GENERATION":
        response = (
            f"Запрос на построение отчета принят (TraceID: {state['trace_id']}).\n"
            f"План выполнения: {', '.join(state['plan'])}.\n"
            f"Исследую остатки товаров через MCP-контур..."
        )
    else:
        response = f"Обработка запроса: '{state['user_query']}'."

    return {"final_response": response}

def deliver_to_1c_node(state: AgentState) -> dict:
    """Отправка сформированного ответа обратно в Систему взаимодействия 1С."""
    # Вызов обратного Webhook/API 1C для отправки сообщения в чат conversation_id
    print(f"[1C Webhook] Отправка в диалог {state['conversation_id']}: {state['final_response']}")
    return {}

# 4. Сборка графа
workflow = StateGraph(AgentState)

workflow.add_node("analyze_intent", analyze_intent_node)
workflow.add_node("plan_executor", plan_executor_node)
workflow.add_node("deliver_to_1c", deliver_to_1c_node)

workflow.add_edge(START, "analyze_intent")
workflow.add_edge("analyze_intent", "plan_executor")
workflow.add_edge("plan_executor", "deliver_to_1c")
workflow.add_edge("deliver_to_1c", END)

# Чекпоинтер сессий по conversation_id для отказоустойчивости
memory_checkpointer = MemorySaver()
agent_app = workflow.compile(checkpointer=memory_checkpointer)

Узлы связываются в StateGraph с чекпоинтером MemorySaver (в production заменяется на PostgresSaver - тема статьи 6 цикла), что дает агенту устойчивость к сбоям сети и падениям процесса ровно в духе HSM-чекпоинтинга, описанного выше.

🤝 Итоги: дорожная карта цикла

Дальше цикл переходит к остальным компонентам корпоративной инженерии ИИ-агентов. Следующие материалы серии:

  • Статья 2. Паттерны рассуждений и мультиагентная оркестрация enterprise-процессов 1С. Декомпозиция задач NOPik на роли: Супервайзер, Аналитик метаданных, Сборщик СКД. Паттерны ReAct и Tree-of-Thoughts.
  • Статья 3. Универсальные контракты и протокол MCP. Развертывание MCP-сервера 1С, валидация через Instructor/Pydantic, кликабельные навигационные ссылки e1cib/data/....
  • Статья 4. Надежность и качество. TDD для агента: модульные тесты YAxUnit, сценарии Vanessa Automation, статический анализ BSL Language Server.
  • Статья 5. Изоляция и DevSecOps. Контейнеризация в Docker/Kubernetes, безопасные песочницы, защита от Path Traversal.
  • Статья 6. Корпоративная память агентов. Двухуровневая память: ConversationID против семантического поиска в Qdrant, шины RabbitMQ и 1С:Шина.
  • Статья 7. Безопасность, мониторинг и наблюдаемость. Threat Modeling по OWASP ASI Top 10, Human-in-the-Loop прямо в чате, трейсы в Grafana/ClickHouse.

Исходные коды расширения NOPik и примеры конфигурации графов доступны в репозитории проекта.


Какие узкие места вы видите в переходе от «монолитных» обработок с ИИ к архитектуре на графах состояний в вашей инфраструктуре 1С? Делитесь опытом и вопросами в комментариях - разберем в следующих статьях цикла.

Теги: 1С:Предприятие 8.3, Система взаимодействия, Объект Бот, ИИ-агент, LLM, LangGraph, FSM, HSM, Граф состояний, MCP, ibcmd, BSL, Фоновые задания, Zero-Footprint, Автоматизация 1С, Python, Pydantic, Enterprise AI, NOPik

Вступайте в нашу телеграмм-группу Инфостарт

Автономный агент FSM HSM граф состояний Бот Команда формы MCP Zero-Footprint LLM вайб-кодинг Circuit Breaker фоновые задания ibcmd Система взаимодействия BSL LangGraph Pydantic

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

SALE! %

Банковские операции Обмен с интернет-банком Мастера заполнения Нейросети Разработчик Бухгалтер Пользователь 1С:Предприятие 8 1C:ERP 1С:Бухгалтерия 3.0 1С:ERP Управление предприятием 2 1С:Управление холдингом 1С:ERP. Управление холдингом 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Управление торговлей 11 1С:Розница 3.0 Платные (руб)

Корректируйте банковские документы быстро и легко! Создайте правило обработки — и оно автоматически применится при загрузке выписки (отбор по любому реквизиту или регулярному выражению). Решение заполняет расшифровку платежа, комиссию эквайринга, подбирает ведомости на выплату зарплаты, помечает дубли из банка на удаление и многое другое. Доплачивать за алгоритмы не нужно — они включены в решение. Обработка работает при загрузке из файлов клиент-банка и через DirectBank. Новое — искусственный интеллект: модель приводит нестандартные назначения платежа к виду, понятному алгоритмам, а ИИ-ассистент прямо в 1С консультирует по решению и разбирает код правил и алгоритмов. Поддерживаются локальные и облачные OpenAI-совместимые модели — данные могут не покидать ваш контур.

17500 руб.

20.12.2024    19375    98    32    

83

Нейросети Системный администратор Разработчик Аналитик Бухгалтер Пользователь Руководитель проекта 1С 8.3 1С:Документооборот 1С:Бухгалтерия 3.0 1С:Зарплата и Управление Персоналом 3.x Россия Платные (руб)

Задавайте вопросы базе 1С обычными словами: получайте данные, находите ошибки и связанные документы, проверяйте права, работайте с вложениями и контролируемо вносите изменения. Всё это работает в самой программе, а Codex и Claude подключаются по желанию.

15989 руб.

30.07.2026    12489    26    4    

27

Инструментарий разработчика Нейросети Платные (руб)

Первые попытки разработки на 1С с использованием больших языковых моделей (LLM) могут разочаровать. LLMки сильно галлюцинируют, потому что не знают устройства конфигураций 1С, не знают нюансов синтаксиса. Но если дать им подсказки с помощью MCP, то результат получается кардинально лучше. Далее в публикации: MCP для поиска по метаданным 1С, справке синтакс-помощника и проверки синтаксиса.

15250 руб.

25.08.2025    70784    140    41    

149

SALE! 50%

Мессенджеры и боты SMS рассылки Email рассылки Пользователь 1С:Предприятие 8 1C:Бухгалтерия 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Управленческий учет Платные (руб)

Расширение 1С с полным набором инструментов для качественных транзакционных, триггерных и маркетинговых рассылок Email, SMS, MAX, WhatsApp, Telegram. Даже простые уведомления об оплате счетов способны существенно упростить сбор дебиторской задолженности. Применение всех возможностей прямого маркетинга выводит коммуникацию с клиентами, уровень сервиса и лояльность на новый уровень.

6100 3050 руб.

07.04.2014    98807    90    205    

173

WEB-интеграция Разработчик Аналитик 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Оптовая торговля, дистрибуция, логистика ИТ-компания Платные (руб)

Модуль "Экспортер" — это расширение для 1С, предназначенное для автоматизации процессов выгрузки данных. Оно позволяет эффективно извлекать, преобразовывать и передавать данные из систем 1С в интеграционную платформу Spot2D. Подсистема упрощает настройку, снижает количество ручных операций и обеспечивает удобный контроль данных.

17568 руб.

20.12.2024    7239    32    4    

34

WEB-интеграция Анализ продаж Системный администратор Разработчик Пользователь 1С:Предприятие 8 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Управленческий учет Платные (руб)

Модуль "Подсистема интеграции AmoCRM с 1С" позволяет обеспечить единое информационное пространство, в котором пользователи могут эффективно управлять клиентской базой, следить за статусами сделок и поддерживать актуальность данных как в AmoCRM, так и в 1С.

60000 руб.

07.05.2019    44246    76    45    

32
Для отправки сообщения требуется регистрация/авторизация