
Привет! Меня зовут Игорь Росляков, я технический писатель. По приглашению руководителя направления «Маркет и интеграции» Сергея Вострикова готовлю цикл статей на тему ИИ-ассистированной разработки решений для Битрикс24.
Сегодня начинаем новую серию туториалов: будем работать с ИИ-агентами через платформу для вайбкодинга Битрикс24 Вайбкод и создавать полезные приложения почти полностью через интерфейс ИИ. В этой статье я использовал OpenAI Codex.
В первой статье создадим паспорт клиента: сводный документ по всем ключевым данным, связанным с компанией. Без такого или подобного приложения эксперт должен вручную обходить все нужные разделы и собирать информацию.
Что будет в этой статье:

Что делает платформа Битрикс24 Вайбкод
Обобщённо — это прослойка между агентом, порталом Битрикс24 и сервером приложения. Платформа выполняет несколько функций.
Даёт API-ключи. Они нужны, чтобы агент мог обращаться к API: создавать приложение, сервер, смотреть статус и логи.
Даёт OAuth-приложение для Битрикс24. Это отдельный ключ vibe_app_..., через который приложение получает право читать данные портала в рамках установленных прав.
Регистрирует встройки в Битрикс24. Например, наше приложение появится как пункт в левом меню и как вкладка в карточке компании.
Хостит сервер приложения. Агент деплоит код на сервер Битрикс24 Вайбкод, и он становится доступен как приложение через URL.
Даёт доступ к данным Битрикс24 через API-обёртку. Приложение обращается к VibeCode Entity API и Batch, а платформа уже прокидывает запросы к порталу с нужной авторизацией.
Даёт инфраструктурные инструменты: создание сервера, деплой и просмотр логов.
Что сделаем и зачем это нужно
Чтобы собрать сводную информацию о компании, часто приходится вручную обходить вкладки с контактами и сделками, проверять завершённые и запланированные активности и искать дополнительный контекст.
Такой информации может быть много: только записей по звонкам и сделкам могут быть сотни. На поиск этой информации вручную уйдут часы.
Мы сделаем приложение «Паспорт клиента», которое будет делать всё за нас: собирать нужные данные в одном месте и выводить список всех компаний, по которым можно посмотреть информацию:


У нас будет отдельная страница с подробной информацией о компании и дополнительно — дашборд, который будет показывать список компаний-клиентов:

Что нужно для повторения нашего проекта
Для работы понадобится аккаунт в системе Битрикс24 с оплаченной подпиской, чтобы иметь разрешение на публикацию приложений.
Если мы уже зарегистрированы в системе Битрикс24, переходим в веб-приложение платформы vibecode.bitrix24.tech и нажимаем кнопку «Войти»:

Подключаемся к своему порталу в открывшемся окне и выдаём разрешение на работу с платформой:

Платформа соединяет наш портал и ИИ-инструмент. Для этой связи понадобится API-ключ. Получаем его на странице vibecode.bitrix24.tech/dashboard:

Что можно указать при создании ключа:

Название ключа будет отображаться в списке ключей после создания.
Режим доступа доступен в двух вариантах: Только чтение или Чтение и запись. Режим чтения нужен для безопасных интеграций, которые могут смотреть данные, но не могут ничего менять в портале. Режим Чтение и запись нужен, если приложение должно создавать или изменять данные, регистрировать бота и отправлять сообщения.
Права доступа определяют возможности созданных приложений с новым ключом на портале. Для начала можно выбрать все права, а после создания приложения убрать лишние — ключ можно отредактировать.

Вайбкод определяет доступ к разделам самой платформы, а не портала.
Срок действия определяет время жизни ключа.
Лимит запросов определяет, сколько обращений в секунду приложение может отправлять через этот ключ. Ограничение защищает портал от слишком высокой нагрузки, например если из-за ошибки приложение начнёт непрерывно повторять один и тот же запрос.
Белый список IP определяет, с каких IP-адресов разрешено использовать этот ключ. Если поле заполнить, платформа Битрикс24 Вайбкод и портал Битрикс24 будут принимать запросы с этим ключом только с указанных IP. С любых других IP ключ будет отклоняться.
Ключ лучше сохранить в .env-файл, где он будет храниться в переменной:
VIBECODE_API_KEY=vibe_api_...
Тогда его не нужно пересылать агенту в чате.
После этого остаётся открыть рабочую директорию агента, с которым вы привыкли работать, попросить его взять ключ из .env-файла и дать ссылку на документацию платформы Битрикс24 Вайбкод: https://vibecode.bitrix24.tech/v1/me.
Составляем план и условия работы
Чтобы повысить надёжность дальнейшей работы, я обрисовал агенту задачу и попросил составить план и сохранить его в .md-файл.
После этого добавил базовые инженерные условия:
Использовать максимально доступную типизацию: основной код пишем на TypeScript, включаем строгий режим и избегаем any, кроме явно изолированных адаптеров внешнего API.
Подключать минимум зависимостей: каждая новая runtime-зависимость должна быть нужна для конкретной функции приложения. Если задачу можно безопасно решить стандартными возможностями платформы, зависимость не добавляем.
Тесты добавлять по максимуму: покрываем адаптер VibeCode API, нормализацию данных, агрегатор паспорта, расчёты метрик, обработку частичных ошибок, UI-состояния и smoke-проверки backend routes.
Подключить coverage-проверку после каждого шага: начиная с появления тестового раннера, каждый отчёт должен содержать команду тестов и текущие проценты покрытия.
План агент составил подробный, но неравномерный:
Составить безопасную базу: создать в папке репозиторий, завести
.env,.gitignoreи.env.example, проверить VibeCode API, документацию и прямой портал.Подробно изучить нужные разделы документации и составить архитектурную схему реализации приложения, карту по типу «раздел паспорта → endpoint → фильтр → связь → fallback». После этого проверить все доступы к нужным источникам и зафиксировать инженерные ограничения: минимальные зависимости, обязательные тесты и coverage-отчёт.
Реализовать приложение и запустить его локально для теста.
Провести финальный деплой.
Чтобы следить за исполнением работы, я добавил в план чёткое правило останавливаться после каждого шага и давать подробный отчёт о том, что сделано.
Во время работы у меня периодически возникали проблемы с доступом к платформе из-за сбоев c интернетом, поэтому я попросил агента в конце каждого шага делать мини-отчёт не только по техническому состоянию проекта, но и по доступам. В итоге каждый шаг от агента заканчивался примерно такими статусами:
Проверки: Секреты: ключ не найден нигде кроме .env. Тесты: пока не запускались. Coverage: N/A, потому что scaffold приложения ещё не создан. VibeCode API: работает. Документация VibeCode: работает. Прямой доступ к порталу Битрикс24: всё ещё не работает, DNS/resolve timeout. Продолжать можно через VibeCode wrapper/API.
Реализация
Теперь разбираем по шагам, как агент собирал решение, и что у него получалось сразу, а что нужно было исправлять.
1 — Проектирование структуры проекта
Основную реализацию агент сделал в один заход, и после этого мы вносили правки.
ИИ учёл требования и сделал приложение на TypeScript со строгой типизацией через tsconfig.json. Runtime-зависимости полностью отсутствовали. Для тестов агент сначала пробовал Vitest, но он оказался тяжеловат и капризен под текущий Node, поэтому заменил на более минимальный стек: встроенный node:test и c8 для coverage.
В начале планирования ИИ свернул не туда и вместо простой сборки уже существующей информации попытался включить в приложение кучу новых полей для работы с холдингами, когортами, рисками расторжения и инцидентами. После этого мы отдельно зафиксировали, что приложение имеет конкретную цель: показать экономию ручного сбора контекста, а не требовать перестройки CRM.
Технически проект делится на несколько слоёв:
http.ts— маршруты, placement-контекст, ответы сервера.passport.ts— бизнес-логика паспорта клиента.vibe.ts— клиент VibeCode API.ui/pages.ts— HTML-интерфейс.Отдельные тесты для конфигурации, HTTP, VibeCode-клиента, паспорта и UI.
Это помогло создать аккуратное разделение: отдельно лежат сбор данных, рендеринг, работа с API.
На этом этапе приложение можно было запустить локально на машине, но я не видел в этом большой пользы, потому что в итоге нам всё равно нужно рабочее приложение в нашем портале. Поэтому мы сразу разобрались с технической реализацией и начали деплоить кастомизацию на сервер Битрикс24 Вайбкод.
2 — Создание интерфейса и полей на портале
Агент зарегистрировал два места встраивания в интерфейс Битрикс24:
В панели слева появилась кнопка, по которой должен быть открываться общий дашборд со всеми компаниями.
В карточке компании открывался паспорт конкретной компании.
При этом и карточка, и дашборд связаны друг с другом — в каждом из них есть кнопки для переключения вида с карточки на дашборд и обратно.
Ключевая логика на этом этапе простая: что приложение смотрит, откуда его открыли. Если это карточка компании, оно достаёт ID компании из placement-контекста. Если это левое меню, показывает общий дашборд.
В коде src/http.ts это место выглядит так:
// создаём объект url из входящего запроса // это нужно, чтобы одинаково работать и с обычными get-параметрами, и с параметрами placement const url = createRequestUrl(rawUrl, rawBody) // проверяем, что пользователь открыл корень приложения // именно на корень обычно приходит запуск из placement Битрикс24 if (url.pathname === '/') { // читаем тип placement из параметров запроса // по нему понимаем, приложение открыли из левого меню или из карточки компании const placement = getParam(url, 'placement') // если placement равен CRM_COMPANY_DETAIL_TAB, значит приложение открыто как вкладка в карточке компании if (placement === 'CRM_COMPANY_DETAIL_TAB') { // достаём id текущей компании из placement_options // это главный контекст: вокруг этой компании дальше строится паспорт const companyId = extractPlacementCompanyId(url) // собираем паспорт конкретной компании и отдаём html-страницу встройки return htmlResponse(200, renderCompanyCardPage({ passport: await loadClientPassport( companyId ?? 'не передан', createVibeClient(context.auth) ) })) } // если это не вкладка компании, считаем, что открыт общий вход в приложение // в этом случае показываем общий дашборд со списком компаний return htmlResponse(200, renderDashboardPage({ data: await loadDashboardData(createVibeClient(context.auth)) })) }
3 — Сбор данных через Entity API и Batch
По ID компании приложение формирует пять batch-команд: отдельно запрашивает саму компанию, связанные контакты, сделки, лиды и активности.
Вместо 5 отдельных запросов мы собираем команды в Batch. Это хорошо показывает экономию, потому что раньше эксперт раньше открывал всё руками, а приложение одним пакетом запрашивает нужные сущности.
Как это записано в коде в src/passport.ts:
// функция формирует первый набор batch-команд для паспорта клиента // на вход приходит id компании, которую пользователь открыл в Битрикс24 function createPrimaryCalls(companyId: string): readonly BatchCall[] { // пробуем привести id компании к числу // для некоторых get-запросов entityId удобнее передавать числом const id = Number(companyId) // возвращаем массив команд, который потом уйдёт в VibeCode Batch API return [ // получаем саму карточку компании // это базовая сущность паспорта: название, телефон, отрасль, выручка, последняя активность { id: 'company', entity: 'companies', action: 'get', entityId: Number.isFinite(id) ? id : companyId }, // получаем контакты, связанные именно с этой компанией // фильтр companyId не даёт забрать все контакты портала, только релевантные текущей карточке { id: 'contacts', entity: 'contacts', action: 'list', params: { filter: { companyId }, limit: 50 } }, // получаем сделки компании // по ним считаются статусы: в процессе, выиграны, проиграны, а также сумма сделок { id: 'deals', entity: 'deals', action: 'list', params: { filter: { companyId }, limit: 50 } }, // получаем лиды, связанные с компанией // если лидов нет, приложение покажет пустой источник { id: 'leads', entity: 'leads', action: 'list', params: { filter: { companyId }, limit: 50 } }, // получаем активности, привязанные напрямую к компании // ownerTypeId = 4 в нашей модели означает crm-компанию { id: 'companyActivities', entity: 'activities', action: 'list', params: { filter: { ownerTypeId: COMPANY_ENTITY_TYPE_ID, ownerId: companyId }, limit: 50 } } ] }
Потом приложение делает второй проход по сделкам. Это нужно потому, что часть касаний может быть привязана не к компании напрямую, а к её сделкам.
src/passport.ts, функция loadDealActivities(client, deals):
// функция догружает активности по найденным сделкам // это второй batch-проход после того, как мы уже получили список сделок компании async function loadDealActivities( client: VibeClient, deals: readonly DealSummary[] ): Promise<{ readonly activities: readonly ActivitySummary[] readonly errors: readonly string[] }> { // если сделок нет, то и активности по сделкам искать негде // возвращаем пустой результат без ошибки if (deals.length === 0) return { activities: [], errors: [] } // собираем batch-команды для активностей каждой сделки // ограничиваемся первыми 20 сделками, чтобы не раздувать пакет бесконечно const calls: BatchCall[] = deals.slice(0, 20).map((deal) => ({ // задаём уникальный id результата, чтобы потом понимать, к какой сделке относится ответ id: dealActivities_${deal.id}, // работаем с сущностью activities entity: 'activities', // запрашиваем список активностей action: 'list', // фильтруем активности по сделке // ownerTypeId = 2 означает crm-сделку params: { filter: { ownerTypeId: DEAL_ENTITY_TYPE_ID, ownerId: deal.id }, limit: 20 } })) // отправляем второй batch-запрос через VibeCode API const batch = await client.batch(calls) // ответы приходят сгруппированными по id команд // разворачиваем все списки активностей в один общий массив const activities = Object.values(batch.results).flatMap((value) => asArray(value).map(normalizeActivity) ) // возвращаем найденные активности и отдельно список ошибок api, если они были return { activities, errors: formatBatchErrors(batch.errors) } }
4 — Деплой на сервер Вайбкод и проверка в портале
После локальной реализации приложение нужно было сделать рабочим снаружи. Мы подняли сервер на VibeCode, задеплоили Node-приложение, привязали его к OAuth-приложению и зарегистрировали встройки.
Это оказалось самой сложной частью проекта для ИИ-разработки.
Сначала агент решил, что публикация приложения должна идти через обычный мастер Битрикс24 Вайбкод: выбрать сервер, выбрать места показа, нажать кнопку Опубликовать. Из-за этого ИИ раз за разом давал инструкции по работе с UI: где выбрать левое меню, где вкладку компании, какой сервер указать. Это было неверное направление для задачи, потому что смысл проекта был именно в том, что агент должен довести приложение до финальной работы самостоятельно.
Потом выяснилось, что агент запутался между несколькими сущностями в интерфейсе публикации: API-ключом, OAuth-приложением, сервером, каталогом приложений, placement-встройками и Black Hole сервером. Я отправлял в Codex скриншоты, на которых он видел, что приложение как ключ авторизации существует, серверы существуют, но в каталоге приложений приложение не появляется. При публикации через стандартный путь платформа хотела создать или выбрать сервер и пройти настройку через мастер настройки UI:

Некоторое время агент ошибочно воспринимал это как обязательный путь.
Реальная проблема была в том, что «публикация в каталог» и «регистрация встраиваний в портал» оказались не одним и тем же. Для задачи не обязательно было публиковать приложение в каталог. Нужно было, чтобы оно стало видно в интерфейсе Битрикс24: в левом меню и во вкладке карточки компании. Это решается через placement bind.
Понять это мешали проблемы с доступом: из среды агента мой бизнес-портал был недоступен и возвращал DNS timeout. Поэтому ИИ не мог открыть портал и проверить, что происходит после каждого действия.
В конце концов агент нашёл решение и сделал регистрацию через API Битрикс24 Вайбкод.
Фактически решение было таким:
Создать и использовать OAuth-приложение Вайбкод. То есть у нас появилось приложение «Паспорт клиента» с app key вида vibe_app_....
Задеплоить сервер приложения. Агент собрал проект, загрузил его на VibeCode Black Hole server и настроил старт:
npm ci --omit=dev
npm run startУказать приложению VIBE_APP_KEY. На сервере приложение получило ключ OAuth-приложения, чтобы запросы к Entity API шли от имени установленного приложения, а не от личного API-ключа.
Зарегистрировать placements напрямую. Это был главный инсайт для ИИ: вместо прохода публикации через UI агент использовал API-привязку placements.
Нужны были два placement:
LEFT_MENU CRM_COMPANY_DETAIL_TAB
И handler:
https://vibecode.bitrix24.tech/v1/bitrix-handler
Это именно handler Вайбкода, не прямой URL сервера. Это важно, потому что handler прокидывает gateway-авторизацию и открывает приложение корректно внутри портала.
После этого приложение появилось в левом меню как Паспорт клиента и во вкладке карточки компании:


Во время деплоя агент оперативно реагирует на происходящее и держит в курсе процесса, это приятно:

На всякий случай скажу, что посмотреть и настроить свои серверы можно в меню платформы:

5 — Исправление ошибок после реальной проверки
После деплоя и запуска первой версии в портале осталось внести небольшие правки: например, иногда при переходе между общим дашбордом и паспортом конкретной компании терялась авторизация:

Для сохранения авторизации агент начал сохранять авторизацию в подписанную HttpOnly cookie. Для этого понадобились 2 правки в src/http.ts. Сначала — место, где используется авторизация:
// при обработке запроса сначала пытаемся взять свежую авторизацию из заголовка gateway // если заголовка уже нет, пробуем восстановить авторизацию из подписанной cookie authorization: getHeader(request, 'x-vibe-authorization') ?? readSignedAuthCookie(request, config.vibeAppKey)
Потом — место, где создаётся cookie:
// функция создаёт cookie только если есть и авторизация, и ключ приложения // без этих данных сохранять нечего export function createSignedAuthCookie( authorization: string | null, appKey: string | null ): string | null { // если авторизации нет, возвращаем null // это защищает от установки пустой или бессмысленной cookie if (!authorization || !appKey) return null // кодируем значение авторизации в base64url // так его безопаснее положить в cookie как строку const value = Buffer.from(authorization, 'utf8').toString('base64url') // подписываем значение через hmac // подпись нужна, чтобы пользователь не мог подменить cookie вручную const signature = signCookieValue(value, appKey) // возвращаем защищённую cookie // httponly не даёт читать её из javascript // secure требует https // samesite=none нужен, потому что приложение работает внутри iframe/placement return ${AUTH_COOKIE_NAME}=${value}.${signature}; Path=/; Max-Age=3600; HttpOnly; Secure; SameSite=None }
Другие правки были проще — видимая область при открытии во встройке компании была слишком маленькой, а подписи к проигранным сделкам и сделкам в процессе выглядели как просвечивающая техническая часть:

Некоторые недочёты стали видны только после тестирования на реальных сценариях — например, сумма сделок считалась некорректно:
const totalDealAmount = deals.reduce((sum, deal) => sum + deal.amount, 0) const currency = deals.find((deal) => deal.currency)?.currency ?? null
Получался такой алгоритм:
Взять все сделки компании.
Сложить
amountкаждой сделки в одно число.Найти первую сделку, у которой есть валюта.
Показать всю сумму в этой первой валюте.
Готовая структура проекта
Итоговый состав приложения выглядит так:
VKVVPart1Passport/ ├─ src/ │ ├─ server.ts │ ├─ http.ts │ ├─ config.ts │ ├─ vibe.ts │ ├─ passport.ts │ ├─ ui/ │ │ └─ pages.ts │ ├─ config.test.ts │ ├─ http.test.ts │ ├─ vibe.test.ts │ ├─ passport.test.ts │ └─ ui/ │ └─ pages.test.ts │ ├─ docs/ │ ├─ DEPLOYMENT_STATUS.md │ ├─ ENGINEERING_STANDARDS.md │ ├─ INVENTORY.md │ └─ TEST_DATA_SCENARIO.md │ ├─ dist/ ├─ coverage/ ├─ node_modules/ ├─ package.json ├─ package-lock.json ├─ tsconfig.json ├─ PLAN.md ├─ .env ├─ .env.example └─ .gitignore
Основные составляющие проекта:
src/server.ts— точка входа приложения, которая запускает HTTP-сервер на нужном порту.src/http.ts— HTTP-слой маршрутизации, который отвечает на несколько вопросов: какой URL открыл пользователь, открыл ли он общий дашборд или карточку компании, какой HTML или JSON вернуть.src/passport.ts— главный бизнес-слой, где живёт логика приложения. Этот скрипт понимает, какие сущности нужны, как собрать Batch-запрос, как считать метрики и нормализовывать ответы. При добавлении новых функций основная работа будет здесь.src/vibe.ts— клиент VibeCode API. Он знает, куда отправлять Batch, какие заголовки авторизации нужны, как распарсить ответ. Весь контакт с внешним API изолирован в одном месте. Благодаря этому, если поменяется формат ответа или endpoint, не придётся переписывать весь проект.src/ui/pages.ts— серверный HTML-рендеринг. Здесь хранятся общий дашборд, карточка компании, таблицы, метрики, стили. Агент сознательно не стал использовать React/Vue, потому что на этапе первой версии это было бы лишней зависимостью. Нам нужен был быстрый, типизированный и минимальный проект, который можно легко задеплоить на VibeCode-сервер.src/*.test.ts— тесты, которые проверяют конфиг, HTTP-роутинг, Вайбкод-клиент, сбор паспорта и HTML-рендеринг.docs/— рабочая документация проекта. Здесь агент сохранил сценарий тестовых данных, статус деплоя, инженерные правила. По этим деталям я частично восстанавливал историю, когда писал статью.
Общий процесс выглядит так:

Что сделаем дальше
Сегодня мы попробовали сделать реальное приложение, которое может сэкономить часы работы с бизнес-порталом. В следующий раз покажем другие полезные применения платформы и попробуем включить их в реальные сценарии использования.
Если у вас есть вопросы по работе с платформой или предложения по созданию интересных кастомизаций — напишите в комментариях, а мы постараемся об этом написать.
mia123
Ждем официальную библиотеку Bitrix UI для платформы вайбкодинга и чёткие инструкции для агента по авторизации. Все путаются , как у вас , так и у нас разные агенты разных вендоров, наталкиваются на одно и тоже препятствие в авторизации. По задумке одного ключа должно быть достаточно для всего. А получается , что нет , и количество вариаций зашкаливает в таком случае. Необходимо чёткое разделение в документации видов приложений в зависимости от видов их использования и видов планируемой авторизации.
не знаю как у остальных, у нас 99% приложений это встройка в интерфейс Битрикс. Но чёткого алгоритма создания такой встройки не описано. Даже у вас описано, что агент запутался.
так же на пример на презентации вайб платформы, был упомянута возможность создавать внешнее приложение со своей авторизацией логин/пароль без привязки к битрикс паспорту и без регистрации на портале, это влечёт за собой кучу инфраструктурных решений, хранение и администрирование этих учёток, ролевая модель прав, ну и связь с информацией из портала, на пример покупатель войдя в "личный кабинет" мог видеть связанные с ним сделки в нашем формате.
в документации я такой возможности не нашёл, а агенты тем более.