Дал Claude Code и Codex инструменты для правки бизнес-процессов Битрикс24
У меня давно было ощущение, что редактирование бизнес-процессов в Битрикс24 застряло в другой эпохе. Нейросети уже разбирают репозитории и меняют код, а здесь ради изменения маршрута согласования по-прежнему приходится открывать блоки, искать условия и вспоминать, что имел в виду человек, который собирал эту схему несколько лет назад.
Сам бизнес-процесс при этом никуда не устарел. Заявку всё ещё нужно согласовать, ответственного — назначить, уведомление — отправить. Меня раздражает количество ручной работы вокруг этих действий. Особенно когда процесс давно вырос из десяти аккуратных прямоугольников в дерево, которое уже неудобно рассматривать на экране.
Я собрал для этого связку: скилл для AI-агента и модуль для коробочного Битрикс24. Со скиллом можно работать через экспорт и импорт шаблонов, в том числе в облаке, если соответствующие операции доступны на вашем портале. Модуль добавляет прямой доступ к шаблонам в коробке: агент читает процесс, находит нужную ветку, готовит изменения и отправляет их через шлюз.
Пользовался этим с Claude Code и Codex. На существующих процессах агент уже находил некорректные URL и проблемы с назначенными сотрудниками, после чего мы исправляли шаблоны. Точных замеров экономии времени у меня нет, а полноценный процесс с нуля этим способом я пока не создавал. Ниже — устройство решения, рабочий порядок правки и ограничения, которые остаются даже при удачном ответе модели.
Сразу о распространении: скилл и Python-инструменты открыты под MIT. Модуль для коробки — отдельный платный продукт; на момент подготовки статьи он проходит модерацию в Marketplace 1С-Битрикс. Для работы с экспортированными файлами покупать модуль не нужно.
Что именно получает агент
Если сказать модели «исправь бизнес-процесс», у неё ещё не появятся знания о том, как Битрикс хранит этот процесс. Скриншот схемы тоже не решает задачу: на нём не видно всех свойств блоков, выражений и ссылок между действиями.
Поэтому сначала я дал агенту описание формата и инструменты. В репозитории один скилл: файл с порядком работы, четыре справочника и Python-скрипты. Справочники объясняют структуру шаблона, выражения, типы действий и работу со шлюзом. Скрипты распаковывают файл, показывают дерево, находят узлы и проверяют ссылки.
Важна именно связка. Документация объясняет, что означает поле. Скрипт позволяет прочитать или изменить его без ручного ковыряния в сериализованных данных. А инструкция задаёт порядок: сначала изучить исходное состояние, затем подготовить правку, после этого проверить результат.
Один скилл, два пути доступа к шаблону. В файловом режиме перенос результата обратно на портал остаётся отдельным шагом.
Для прямого подключения используется Python-клиент bpagent.py и HTTP API модуля. По назначению это похоже на инструменты, которые часто подключают к модели через MCP, но протокол MCP здесь не реализован. Агент запускает клиент, клиент обращается к шлюзу, шлюз работает с Битриксом. Отдельной встроенной модели внутри модуля нет.
За прямоугольниками лежит PHP-массив
Экспортированный .bpt — не XML с координатами блоков и не обычный JSON. В поддерживаемом инструментами формате это PHP-сериализация, поверх которой обычно лежит zlib-сжатие. Внутри находятся дерево действий, переменные, параметры и константы.
Упрощённо путь выглядит так:
файл .bpt
↓ распаковка zlib
PHP serialize
↓ разбор с сохранением типов ключей
дерево действий и разделы шаблона
В PHP-сериализации длина строки записана в байтах. Если заменить русское название прямо в сериализованном тексте и не пересчитать длину, получится повреждённый файл. Поэтому правка идёт через структуру: загрузили, изменили нужное свойство, собрали обратно.
При этом нельзя считать, что каждый узел всегда содержит одинаковый набор полей. В шаблонах встречаются разные сочетания Type, Name, Activated, Node, Properties и Children. У листового действия может не быть Children, у старого шаблона — некоторых служебных полей. Утилита определяет особенности конкретного дерева; добавлять всё отсутствующее ради красивого единого JSON не требуется.
Есть и более серьёзное различие. У последовательного процесса действия вложены друг в друга и выполняются по структуре дерева. У машины состояний нужно учитывать стартовое состояние и переходы. Переставить дочерние узлы и ожидать, что это поменяет маршрут машины состояний, — плохая идея.
Модуль поддерживает запись шаблонов с корнем SequentialWorkflowActivity и StateMachineWorkflowActivity. Для NodeWorkflowActivity запись закрыта: у него другая организация связей. Чтение такого шаблона не означает, что шлюз умеет корректно его пересобрать.
Как попробовать без модуля
Для файлового режима нужны экспортированный шаблон, Python, зависимость phpserialize и агент, которому доступен скилл. Папку скилла нужно подключить способом, предусмотренным вашим агентом. В README репозитория установка описана для Claude Code; в своей работе я использовал и Codex.
git clone https://github.com/ShyDamn/bitrix-bizproc-skill.git
cd bitrix-bizproc-skill
python -m pip install phpserialize
python scripts/inspect_bpt.py info process.bpt
python scripts/inspect_bpt.py tree process.bpt
python scripts/validate_bpt.py process.bpt
Здесь process.bpt — ваш экспортированный файл. Первая команда показывает сводку, вторая — структуру, третья — результаты проверки. Начинать лучше с копии, чтобы исходный экспорт оставался под рукой.
Дальше можно поставить агенту конкретную задачу. Например, такой учебный запрос:
Разбери шаблон process.bpt. Найди действия, в свойствах которых встречается old.example.org. Покажи пути узлов и значения целиком. Пока ничего не меняй. После согласования замени только указанные ссылки на new.example.org, сохрани результат в process-fixed.bpt и сравни результаты проверки до и после.
Это пример постановки задачи, а не восстановленный диалог из боевой работы. В нём специально разделены поиск и изменение: одинаковый домен может находиться в пользовательском сообщении, условии или исполняемом коде, и смысл замены будет разным.
В библиотеке есть load() и dump(), поэтому саму правку агент может оформить небольшим скриптом. Результат сохраняется в новый .bpt, проверяется и импортируется обратно через интерфейс портала. После импорта стоит открыть изменённые блоки в дизайнере и прогнать нужную ветку на тестовой сущности.
Для облака этот путь удобен тем, что установка серверного модуля не требуется. Но доступность экспорта, импорта и самого конструктора зависит от возможностей и прав конкретного портала. Скилл эти ограничения не снимает.
Проверка начинается до изменения
Одна из полезных привычек, заложенных в скилл, — сначала запускать валидатор на исходном шаблоне. Иначе после правки можно обнаружить старые дефекты и решить, что их только что внёс агент.
Структурная проверка ищет, например, ссылки на отсутствующие действия, необъявленные переменные и константы, повторяющиеся имена узлов, некорректные переходы между состояниями. Для переменных отдельно интересно, читается ли значение вообще: переменная, в которую что-то записывают, но которую нигде не используют, может быть следом незаконченной правки.
Успешная структурная проверка не доказывает, что выбран правильный согласующий или что все ветки маршрута работают.
При этом валидатор не знает, хороший ли URL стоит в письме и тому ли сотруднику нужно отправить задачу. Существующая ссылка на существующую константу может быть совершенно корректной по структуре и неверной по смыслу.
Именно поэтому я разделяю две вещи. Скрипт проверяет формальные связи. Агент разбирает содержимое и сопоставляет его с контекстом задачи. На наших процессах при таком разборе находились некорректные URL и проблемы с назначенными сотрудниками. Это опыт работы всей связки, а не обещание, что команда validate автоматически обнаружит любой старый адрес или уволенного согласующего.
Есть ещё выключенные ветки. Ошибка в действии с Activated: "N" или под выключенным родителем сейчас может не влиять на выполнение. Валидатор учитывает это различие. В отчёте полезно отделять действующую проблему от дефекта, который проявится при включении ветки.
Почему не отправить модели весь процесс
Большой бизнес-процесс плохо подходит для подхода «вот тебе JSON, разберись». Даже когда дерево помещается в контекст, модель получает массу однотипных блоков и повторяющихся названий. При этом задача часто касается нескольких конкретных свойств.
В клиенте для живого портала есть ограничение: по умолчанию get не отдаёт дерево целиком, если в нём больше 150 узлов. Сначала выполняется запрос метаданных, затем клиент предлагает использовать поиск и поддеревья. Явный --force позволяет получить большой шаблон для обработки файлом, но не делает чтение всего дерева хорошей стратегией.
Пример команд с условным ID шаблона:
python scripts/bpagent.py list --name=Согласование
python scripts/bpagent.py find 123 --type=IfElseActivity
python scripts/bpagent.py find 123 --contains=old.example.org
python scripts/bpagent.py subtree 123 --path=/0/1
Путь /0/1 здесь иллюстративный: настоящий нужно взять из результатов поиска. Если совпадений несколько, клиент дополнительно напоминает, что нельзя брать первое наугад.
Это хорошо знакомый принцип работы с кодом: сначала найти нужное место, потом прочитать окружение, затем менять. В бизнес-процессах он особенно полезен, потому что названия вроде «Условие» и «Уведомление» редко бывают уникальными.
Что добавляет модуль в коробке
С модулем исчезает необходимость каждый раз переносить .bpt между порталом и рабочей папкой. На стороне коробки появляется точка входа, а агент получает адрес шлюза и ключ доступа через переменные окружения BPAGENT_URL и BPAGENT_TOKEN.
Ключ выдаётся в административном разделе модуля. Ему можно разрешить чтение, запись, создание шаблонов, работу со справочником сотрудников и запуск процессов. Кроме набора операций, задаётся область действия: конкретные ID шаблонов и типы документов. Если указаны оба ограничения, они действуют одновременно.
|
Возможность |
Отдельное право |
|---|---|
|
Читать и проверять шаблоны |
|
|
Изменять шаблоны |
|
|
Менять встроенный PHP-код |
|
|
Создавать шаблоны |
|
|
Запускать процессы |
|
|
Искать сотрудников |
|
Для первого знакомства достаточно чтения нужных шаблонов. Даже если агент пока только объясняет существующую логику и составляет список мест для проверки, это уже полезный сценарий.
Поиск сотрудников нужен, потому что user_271 в шаблоне сам по себе мало что объясняет. Шлюз позволяет сопоставить такой идентификатор с активным сотрудником. Но отсутствие человека в выдаче не стоит автоматически объявлять доказательством увольнения: это повод проверить статус и уточнить замену.
Модуль не выполняет запросы к языковой модели. Данные получает внешний агент, а дальше действуют настройки и условия того AI-инструмента, которым вы пользуетесь. Размещение Битрикса на своём сервере само по себе не означает, что содержимое шаблонов останется только внутри компании.
Как изменение попадает обратно в Битрикс
Чтение возвращает дерево и hash его версии. Подготовленную правку нужно отправить с этим хэшем в заголовке If-Match. Если сервер уже видит другую версию шаблона, он откажет с конфликтом. Без заголовка запрос тоже не пройдёт.
GET /templates/123
→ дерево + hash
PUT /templates/123
If-Match: <hash прочитанной версии>
→ проверки → снимок → сохранение
Снимок сохраняет предыдущее состояние шаблона. Он не отменяет последствия уже запущенного процесса.
В клиенте есть и предварительная сверка: перед put он запрашивает текущий хэш и сравнивает его с хэшем в файле. Если процесс изменился, правку нужно перенести на актуальное дерево, а не просто заменить хэш на новый.
Здесь есть важная граница гарантии. Проверка обнаруживает уже произошедшее изменение, но в версии 0.3.1 не обеспечивает атомарную блокировку относительно параллельного сохранения из визуального редактора. Между сверкой и записью остаётся окно. Для совместной работы это повод договориться, кто сейчас редактирует конкретный процесс.
Дальше шлюз проверяет входные типы, права на изменение PHP, сохранность данных при упаковке и размер разделов. Затем запускает структурный валидатор и сохраняет снимок перед обращением к загрузчику Битрикса.
Обновляются только переданные разделы. Отсутствующее поле означает «оставить как есть», а пустой объект или массив — явную очистку. Значение null вместо раздела отвергается. Это различие легко потерять при автоматической сборке JSON, поэтому оно проверяется на входе.
В API есть force: true для обхода структурных ошибок. Он нужен для отдельных случаев работы с уже проблемными шаблонами и отмечается в аудите вместе с проигнорированными находками. Это не универсальная кнопка обхода: она не отменяет права доступа, проверку хэша, типов, размеров и преобразования данных.
Запись выполняется через CBPWorkflowTemplateLoader::update(), с включённой проверкой загрузчика. Прямой SQL здесь был бы неудобным сокращением пути: помимо колонок шаблона есть кэш и связанные настройки, которыми занимается сам Битрикс.
Три детали, которые не видно на красивой схеме
Один и тот же процесс — разные сжатые байты
Проверять сохранность шаблона сравнением двух .bpt побайтово недостаточно. Разные сборки zlib могут выдать разные сжатые последовательности для одних данных. Поэтому модуль считает хэш по распакованным байтам, а самопроверка отдельно рассматривает сериализацию, преобразование через JSON и сжатие.
Это особенно важно для контроля версий: хэш должен меняться из-за изменения данных, а не из-за того, что другой компрессор иначе упаковал тот же массив. В документации проекта остались более ранние формулировки о побайтовом совпадении; ориентироваться нужно на различие этих слоёв.
Рабочий ключ и неожиданный 401
При подключении к коробке можно упереться в WebDAV: в описанном в проекте случае он перехватывал настоящий HTTP PUT до входа в шлюз. Снаружи это выглядело как ошибка авторизации, хотя проблема была не в ключе.
Поэтому клиент отправляет POST с заголовком X-HTTP-Method-Override: PUT, а шлюз обрабатывает его как обновление. Настоящий PUT тоже поддержан, но клиент использует совместимый путь.
Раздел может не поместиться в колонку
Недостаточно получить валидный PHP-массив. В используемой схеме MySQL у VARIABLES и PARAMETERS лимит BLOB составляет 65 535 байт, а у TEMPLATE и CONSTANTS используется MEDIUMBLOB. Модуль проверяет размер упакованных разделов до записи.
Поддержка PostgreSQL тоже потребовала отдельного обращения с бинарными колонками. А снимки версий сохраняются в base64, чтобы не зависеть от различий представления бинарных данных. Наличие этих веток в коде, конечно, не заменяет установку и прогон на конкретной версии коробки.
Почему право на PHP вынесено отдельно
В бизнес-процессе может находиться CodeActivity со свойством ExecuteCode. Это исполняемый PHP на сервере портала. Возможность менять его существенно отличается от возможности исправить текст уведомления.
Поэтому модуль требует отдельного templates:write_code. Проверка действует не только при обычном обновлении, но и при создании шаблона и откате: старая версия тоже может вернуть на сервер исполняемый код.
Однако это не песочница для всей логики БП. Ключ с правом записи способен менять условия, назначения и другие действия. Сервер также не показывает человеку окно подтверждения каждой правки: при достаточных правах корректный запрос выполняется. Просмотр дифа и согласование изменения — часть организации работы с агентом, а не отдельный встроенный approval-сервис.
Для самого скилла правка ExecuteCode выделена явно: агент должен показать изменяемый код и получить подтверждение перед сохранением. Но инструкция модели и серверное разграничение прав решают разные задачи; подменять одно другим не стоит.
Откат шаблона и отмена процесса — разные операции
В модуле есть история версий. Перед откатом сохраняется текущее состояние, поэтому можно вернуться и от самого отката. В версии 0.3.1 восстановление также требует актуального If-Match и проходит проверки.
На момент подготовки текста публичный Python-клиент ещё не передаёт этот заголовок в команде restore. С модулем 0.3.1 такой вызов получит 428. До синхронизации клиента нужно использовать актуальный контракт API; считать все команды из старой инструкции совместимыми нельзя.
Запуск вынесен в отдельную операцию и отдельное право. Здесь последствия другие: процесс может создать задачи людям или отправить уведомления. Возврат прежнего шаблона этого не отменит. Уже запущенные экземпляры также не следует считать автоматически обновлёнными после изменения шаблона.
API умеет запускать процесс и читать доступное состояние экземпляра, но не пересобирает внутренний граф уже исполняющихся активити. В практическом применении я пока сосредоточился на разборе и редактировании существующих шаблонов. Создание с нуля предусмотрено инструментами, однако проверенного кейса такого создания у меня пока нет.
С чего я бы начал на другом портале
Взял бы небольшой понятный процесс и задачу, результат которой легко проверить: конкретный текст уведомления, известную ссылку или согласованную замену ответственного. Сначала попросил бы агента объяснить найденную ветку и показать текущие значения. Уже после этого — подготовить изменение.
В файловом режиме остаётся исходный экспорт. В коробке перед выдачей права на запись полезно запустить поставляемый с модулем selfcheck.php: он проверяет преобразование шаблонов, не записывая их. Для установки 0.3.1 нужны модуль bizproc, PHP не ниже 8.2, zlib и поддерживаемая СУБД.
После изменения важны три результата: понятный диф, отсутствие новых структурных ошибок и успешный прогон нужного сценария на тестовой сущности. Если изменяли условие согласования, одной проверки «процесс запускается» мало — нужно пройти и альтернативную ветку.
Я не замерял, во сколько раз это быстрее ручного редактора. Зато изменился сам способ работы: можно поставить задачу словами, получить объяснение нужной части процесса и обсуждать конкретную правку. Конструктор остаётся полезен для просмотра и проверки результата, но разыскивать каждое поле руками уже не обязательно.
Для меня в этом и состоит смысл такого набора для вайбкодинга бизнес-процессов. У агента появляется доступ к настоящей структуре и инструменты её изменения. У человека остаётся ответственность за то, правильно ли сформулировано правило и правильно ли процесс ведёт себя после правки.
Интересно, что у вас отнимает больше времени в БП: собрать новый маршрут или разобраться в существующем, который давно пережил своего автора?
Автор: ShyDamn

