- BrainTools - https://www.braintools.ru -
В этой статье хочу рассказать как я разрабатывал агента, который принимает запросы из телеги и создает страницы на WordPress + Elementor, не путает проекты, не трогает прод и не собирает каждый раз дизайн рандомно.
То есть мысль перед созданием была следующая – есть Elementor MCP, есть агент, есть запрос пользователя, а значит, агент может вызвать нужные методы, добавить контейнеры, виджеты, текст, кнопки и готово. Спрашивается, почему бы и не сделать такого агента, удобно же.
Но по факту все, конечно же, оказалось сложнее.
Чтобы это начало работать нормально, пришлось сделать отдельный навык – очередь задач, SQLite, CLI-проверки, правила для телеги, валидаторы, перенос бета в прод и отдельный компилятор на Python.
Так что расскажу все по порядку, возможно, кому то пригодится.
Тут будет по сути хронология работы с агентом, так что идем от начала до сегодняшнего дня.
У нас есть несколько сайтов на WordPress + Elementor. Периодически в телегу прилетает обычный рабочий запрос, по типу «сделай страницу», «поправь блок», «создай лендинг», «нужно по документу собрать страницу».
К этому моменту мой агент в OpenClaw уже умел делать соседние задачи – писать тексты, готовить SMM, работать с изображениями, публиковать анонсы. Поэтому первая идея была такой – раз есть Elementor MCP-инструменты, пусть агент просто вызывает их и собирает страницу. Собственно, так он и делал и, естественно, это не работало так как надо.
Когда запрос один все выглядит нормально, но как только появляются реальные пользователи, несколько проектов и риск задеть прод все начинает сыпаться.
Нужно было настроить агента так, чтобы он собирал страницу по определенным правилам – в нужном окружении, по очереди, с проверками и понятным состоянием.
Так появился навык в отдельном пространстве, куда главный агент делегирует именно эти задачи под названием “web42-elementor-builder”

Навык начинался как обычный scaffold:
SKILL.md [1] – главный файл с правилами;
settings/triggers.yaml и settings/intents.yaml – чтобы понять, какие фразы запускают какой workflow;
skills-map.yaml – карта intent → workflow;
workflows/ – YAML-файлы для операций со страницами, контейнерами, виджетами, стилями и публикацией;
modules/ – отдельные инструкции для окружения, роутинга, резолва страниц, валидации;
scripts/ – первые Python CLI для задач, окружений и SQLite.
На этом этапе важнее всего было принять архитектурное решение – агент не должен сам читать и менять состояние, все операции с задачами, окружениями и базой идут только через CLI.
29 июня я проверял навык в телеге с двумя пользователями, оба попросили создать страницы и тут выяснилось, что scaffold не вывозит.
И первый баг был самый неприятный, задача первого пользователя могла тупо потеряться. То есть, пользователь просит страницу, агент спрашивает проект, ждет ответа, а task record создает уже потом. Кроме того, пока первый пользователь думает, второй тоже отправляет запрос и агент создает активную задачу для второго, а первый фактически проваливается между шагами.
Так что сначала надо было настроить порядок операций. Task record нужно создавать до любого вопроса пользователю, даже если проект еще неизвестен, в задаче фиксируется плейсхолдер вроде pending_project, то есть пользователь сразу занимает место в очереди и его запрос больше не теряется.

Второй баг был про дубликаты – один пользователь мог запустить сразу несколько задач. Поэтому, я добавил проверку на уровне db.py [2]: перед созданием новой задачи вызывается get_user_open_task(telegram_user_id). Если у пользователя уже есть active или queued задача, новая не создается.
Третий баг хорошо показал логику [3] поведения [4] агентов – даже когда навык уже существовал, агент все равно пытался делать прямое обращение к МСР
И поэтому жестко зафиксировали правило – для Web / Elementor задач главный агент не строит страницы напрямую, а делегирует ее ИИ-верстальщику внутри которого уже workspace-elementor task routing должен пройти через навык и CLI. Прямые MCP-вызовы до маршрутизации – обход системы.
Еще один типичный сбой – compound-вопросы.
Агент спрашивал сразу все – какой проект, какой источник, какой стиль, публиковать ли в бету или прод. Вроде бы это правильно для задачи, но в очереди задач это ломает состояние. То есть, пользователь отвечает на три вопроса сразу, агент уже переключился на другую задачу, часть ответа относится к текущему шагу, часть к будущему, часть вообще еще нельзя применять.
Поэтому появилось правило одного ближайшего блокера “если не хватает проекта – спросить только проект; если проект есть, но не выбран источник – спросить только источник”, короче просто не забегать вперед.
Для этого появился workflow_cli.py [5] next-question. Агент больше не сочиняет формулировки сам, он спрашивает CLI, какой вопрос сейчас разрешен и отправляет только его. Это выглядит менее эффектно, зато система становится воспроизводимой.

На той же отладке всплыл обратный перекос.
Агент сделал внутренний шаг – сохранил метаданные, прочитал Google Doc, извлек заголовок и остановился с сообщением вроде “продолжаю”, хотя по факту для пользователя это бесполезный ответ, как и для workflow.
Я разделил состояния на те, которые могут останавливать выполнение, и те, которые обязаны вести дальше. Условно – waiting_*, blocked_*, done_* могут быть причиной остановки, а ready_* – нет. Если задача в активе и следующий шаг можно выполнить без пользователя, агент должен продолжать.
Позже из этого вырос модуль long-running-progress.md [6], то есть сообщать о долгих операциях можно, но progress-only финальный ответ запрещен. Грубо говоря “если можно идти дальше – надо идти дальше”.
Отдельная тема – окружения.
Есть бета и прод и понятное дело нужно его ограничить, чтобы все тесты были в бете, поэтому – create_page идет в бету по умолчанию, а прод разрешен только через отдельный transfer workflow. Да, да, супер база, но вдруг.
Для этого добавили:
env-project-guard.md [7] – проверку проекта и окружения перед операциями;
production-transfer.md [8] – порядок переноса;
transfer_cli.py [5] – export из beta и import в production;
workflow_cli.py [5] guard-production-operation – блокировку прямых правок на production.
Ключевой момент – перенос это не пересборка. Нельзя собрать заново примерно то же самое на рабочем сайте. Нужно взять проверенный результат из беты и перенести его, а перед переносом – обязательно явное подтверждение.

Мы проверяли одну из созданных страниц и нашли системную проблему с отступами.
Агент применял padding и margin к контейнерам. В Elementor эти ключи относятся к widgets, а у контейнеров другие настройки – padding, margin, css_classes, flex_gap, grid_gaps. У widgets – padding, margin, cssclasses.
То есть агент использовал неправильный слой API. После этого появился модуль elementor-spacing-builder.md [9], в нем зафиксировали матрицу container vs widget controls. Модуль стал обязательным перед сохранением Elementor layout.
Здесь был еще один важный урок – агент смотрел в JSON/export и писал, что spacing применен, но браузер мог рендерить иначе из-за темы, каскада CSS или особенностей Elementor. Поэтому проверки только по JSON недостаточно, нужна связка schema-compatible settings + exported Elementor data, а в идеале еще и браузерная проверка computed styles.

Через неделю стало понятно, что агент смешивает две разные вещи – workflow questions и final handoff.
Один инструмент должен отвечать на вопрос “что спросить дальше?”, а другой “что показать пользователю, когда задача завершена?” Если смешать это в голове агента, финальный ответ превращается в смесь URL, внутренних статусов, task ID, вопросов и отладочных деталей, поэтому появился result_cli.py [5].
workflow_cli.py [5] отвечает за шаги и вопросы, result_cli.py [5] render-final собирает user-facing результат из task state и metadata – preview URL, edit URL, применяемые модули, evidence. Внутренности БД и технические трассировки в обычный ответ не попадают.
Разделение получилось небольшим, но полезным – стало меньше путаницы в том, что агент должен делать дальше и что он должен показать пользователю.
Еще через неделю добавили отдельный quality_gate_cli.py [5], потому что агент может сказать “проверено”, не проверив. Иногда он считает, что если шаг был в плане, значит он выполнен, а иногда видит валидный JSON и делает слишком широкий вывод.
Поэтому passing quality gate может поставить только CLI – агент запускает проверку, получает passed или failed, и дальше действует по результату. Self-asserting quality gate запрещён. Quality gate проверяет наличие обязательных артефактов и evidence, а для Figma-сценариев – strict compiler artifacts, asset binding, visual/pixel evidence и repair state, где это требуется от воркфлоу.

Изначально создание страниц из гугл дока было основным сценарием – документ дает контент, style audit берет референсную страницу, агент собирает структуру в Elementor.
Style audit и widget/template extraction обязательны для того, чтобы переиспользовать стиль проекта и не изобретать компоненты заново.
Но вот второй сценарий оказался намного сложнее – Figma и Elementor описывают страницу по-разному. В Figma есть дерево нод, координаты, компоненты, фреймы, варианты, vector paths, image fills, а в Elementor – контейнеры, widgets, flexbox/grid, WordPress media, responsive settings, то есть прямой маппинг “нод → виджет” быстро ломается.
Первые версии компилятора шли через упрощенные представления:
В 6 версии был scene.json и из Figma REST JSON делалось упрощенное дерево, потом deterministic compiler с self-heal пытался получить Elementor structure и проблема тут, что при упрощении терялось слишком много информации.
В 7 пробовал гибрид с JavaScript и Elementor MCP widgets.mjs – это добавило второй runtime и усложнило отладку. Python-окружение агента, Node.js-компилятор, validate-readback – все вместе стало слишком хрупким.
А в 8 сделал разворот strict Python compiler. Figma REST JSON напрямую превращается в Elementor JSON через figma_json_to_elementor.py [10]. Ассеты выбираются через figma_selective_assets.py [11], потом связываются с WordPress media через figma_bind_assets.py [11].
Короче, главное правило – никакой ручной сборки Figma-страницы агентом. Никаких скриншотов вместо страницы. Никаких HTML/CSS-подстановок чтобы похоже выглядело.
Если компилятор ошибся – исправляем Python и прогоняем заново.
К 14 версии пайплайн стал таким:

Смысл semantic tree в том, чтобы сначала понять, что перед нами, заголовок, текст, кнопка, карточка, изображение или декоративный элемент, а уже потом решать, как это разложить в Elementor flex/grid. Это важное разделение, потому что если сразу превращать Figma-ноды в Elementor-элементы, компилятор путает смысл и раскладку, а если разделить semantic tree и layout tree, можно отдельно улучшать распознавание и отдельно геометрию.
В v14 также закрепил правило “Figma REST JSON – единственный runtime source”. JSON из Figma-to-Elementor плагина можно использовать только в benchmark mode как golden reference, но нельзя копировать его в runtime, использовать как шаблон сборки страницы или строить страницу по нему.
Это архитектурно правильный pipeline, но он еще не означает полной визуальной эквивалентности Figma и Elementor.
18 июля нашел еще один практический баг.
Тысячи VECTOR-фрагментов могли экспортироваться как отдельные SVG. WordPress media library быстро засоряется такими файлами, а сборка тормозится.
Поэтому правило изменил:
generic VECTOR paths не считаются самостоятельными SVG-ассетами;
COMPONENT/INSTANCE экспортируются как SVG только при explicit export или семантическом имени вроде icon, logo, illustration, badge, symbol;
raster image fills дедуплицируются по imageRef;
декоративные zero-geometry paths не блокируют build.
Это хороший пример того, что большое количество данных не гарантирует лучшее качество работы. Для production-процесса важно экспортировать ровно то, что нужно странице.
На момент подготовки статьи наш “web42-elementor-builder” – это уже не один промпт и не один SKILL.md [1].
В сумме это тысячи строк Python, десятки workflow/config-файлов и большой SKILL.md [1]. То есть полноценный регламент, а не один промпт.
Фактический объем в рабочей директории сейчас такой:
|
Компонент |
Объем |
|
SKILL.md [1] |
2258 строк, около 90 KB |
|
modules/ |
15 файлов, 5309 строк |
|
scripts/*.py |
19 Python-скриптов, 9787 строк |
|
workflows/ |
15 активных YAML workflow плюс backup/recovery copies |
|
settings/ |
4 файла, 489 строк |
Самые крупные Python-файлы:
figma_json_to_elementor.py [10] — 3623 строки;
db.py [2] — 1764 строки;
workflow_cli.py [5] — 657 строк;
template_cli.py [5] — 623 строки;
task_cli.py [5] — 466 строк;
result_cli.py [5] — 384 строки;
figma_pipeline_cli.py [5] — 383 строки;
figma_preflight.py [12] — 373 строки;
transfer_cli.py [5] — 250 строк.
Цифры понятно еще будут меняться, но они хорошо показывают, что подобная вроде простая задачка в реальной работе довольно быстро превращается в систему с состоянием, правилами, проверками и запретами.
Figma-компилятор пока работает так себе.
В документации по ограничениям зафиксировано, что на ERP golden pair benchmark coverage около 35.6% по количеству элементов – 528 сгенерированных против 1482 в референсе. Это значит, что benchmark mode правильно блокирует заявления об эквивалентности.
Обычный компилятор можно использовать для разработки и тестов, но слабые места остаются:
tree alignment нужно улучшать;
breakpoint-specific branch generation для tablet/mobile еще не всегда корректен;
сложные Figma-компоненты не всегда мапятся 1:1 в Elementor.
В общем, еще есть над чем поработать.
Сейчас “web42-elementor-builder” – это навык, который держит несколько инвариантов:
один пользователь – одна открытая задача;
task record создается до любого вопроса;
вопросы идут только через workflow_cli.py [5] next-question;
состояние задач и окружений меняется только через CLI;
beta используется по умолчанию;
prod не редактируется напрямую;
перенос в prod идет через export/import и подтверждение;
style audit и spacing builder обязательны для Google Docs сценария;
Figma-сценарий идет только через Python compiler;
quality gate нельзя проставить словами агента;
финальный ответ рендерится отдельно через result_cli.py [5].
В принципе, это довольно банально и понятно, что нужно грамотно строить архитектуру, но просто ради галочки зафиксирую.
AI-агенту нужно четко вносить ограничения в правила, состояние, CLI, guard’ы и проверки. Промпт помогает объяснить намерение, но рабочий навык начинается там, где появляется регламент – кто владеет задачей, где хранится состояние, какие шаги нельзя пропустить, какие действия запрещены, чем подтверждается результат и где агент обязан остановиться.
На этом все. Дайте знать, если интересно чем в итоге все закончится – отчитаюсь.
А если есть мысли что и как можно доработать – буду рад видеть в комментах.
Спасибо за внимание [13]!
Автор: RomanOpenclaw
Источник [14]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/33499
URLs in this post:
[1] SKILL.md: http://SKILL.md
[2] db.py: http://db.py
[3] логику: http://www.braintools.ru/article/7640
[4] поведения: http://www.braintools.ru/article/9372
[5] cli.py: http://cli.py
[6] long-running-progress.md: http://long-running-progress.md
[7] env-project-guard.md: http://env-project-guard.md
[8] production-transfer.md: http://production-transfer.md
[9] elementor-spacing-builder.md: http://elementor-spacing-builder.md
[10] elementor.py: http://elementor.py
[11] assets.py: http://assets.py
[12] preflight.py: http://preflight.py
[13] внимание: http://www.braintools.ru/article/7595
[14] Источник: https://habr.com/ru/articles/1062724/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1062724
Нажмите здесь для печати.