Я сделал отдельного бота техподдержки для своего WordPress-плагина MAX Autopost. Причина простая: вопросы начали повторяться, а ручная переписка постепенно превращалась в маленький админский спортзал. Токен, версия PHP, версия WordPress, что нажимали, что получили, где скриншот, где лог. Всё это каждый раз приходилось вытаскивать руками.
Теперь этим занимается MAX Support Bot. Пользователь заходит в бота, выбирает тему обращения, отвечает на вопросы, при необходимости прикладывает скриншот или лог, а я получаю уже собранную заявку в админ-канал.
Бот доступен здесь: MAX Support Bot. Это пока MVP, но уже рабочий. Не «когда-нибудь сделаю», а прямо можно открыть и потыкать.
Отдельно интересно, что для сборки я использовал Grok Build Beta. Бета-версия как раз появилась свежая, и я решил проверить её не на игрушечной задаче, а на реальном Python-боте, который должен работать, принимать заявки и не падать от первого же пользователя с кнопкой «Отмена».
Какую проблему я решал
У MAX Autopost есть понятные типовые вопросы. Кто-то не понимает, где взять токен. У кого-то не отправляется пост. Кто-то путается в настройке канала, подписи, кнопок, версии WordPress или PHP. В личной переписке это быстро превращается в кашу.
Самая неприятная часть поддержки не в том, что люди спрашивают. Это нормально. Неприятно, когда для решения простой проблемы не хватает половины данных. Приходится писать: «какая версия плагина?», «какая версия PHP?», «пришлите скриншот», «а лог есть?», «а что именно нажимали?». И так по кругу.
Поэтому я решил сделать бота, который будет задавать эти вопросы по сценарию. Не вместо человека, а перед человеком. Чтобы до меня доходила уже нормальная заявка, а не набор сообщений в стиле «ничего не работает, помогите срочно».
Что умеет MAX Support Bot
Сейчас бот работает как сценарный помощник для сбора обращений. Пользователь не пишет всё в свободной форме с нуля, а проходит понятный путь.
- Выбирает тему обращения: установка, настройка, ошибка, вопрос по публикации.
- Указывает версию плагина MAX Autopost.
- Указывает версию WordPress.
- Указывает версию PHP или выбирает «не знаю».
- Описывает проблему своими словами.
- Может прикрепить скриншот, лог или другой файл.
- Подтверждает заявку перед отправкой.
- Готовая заявка уходит мне в админ-канал.
На выходе я получаю не поток разрозненных сообщений, а структурированную заявку. Там видно, кто написал, по какой теме, какие версии указаны, что приложено и что именно человек хочет решить.
Это не только экономит время. Это ещё и снижает шанс потерять важную деталь. В техподдержке мелочь вроде версии PHP может быть не мелочью, а причиной всей проблемы. Особенно когда речь про WordPress-плагины, где окружение у каждого своё, а сюрпризы любят жить в старых хостингах.
Почему именно бот, а не форма на сайте
Форма на сайте тоже вариант. Но в моём случае логичнее было сделать бота в MAX. Плагин связан с публикациями в MAX, пользователи и так работают с этой площадкой, а бот позволяет вести диалог пошагово.
Плюс в мессенджере проще прикладывать скриншоты. Человек открыл чат, нажал кнопку, ответил, отправил файл. Всё рядом. Не надо искать отдельную страницу поддержки, вспоминать email, копировать данные и пытаться объяснить проблему в одном большом поле.
Для меня плюс тоже очевидный: заявка сразу приходит туда, где я могу её увидеть. Не в потерянный комментарий, не в личку «а потом разберусь», а в отдельный админ-канал.
Технический стек
Бот написан на Python. Я сознательно не стал делать тяжёлый комбайн. Нужен был понятный MVP, который можно развернуть на VPS, держать под systemd и спокойно сопровождать.
- Python 3.12.
- FastAPI для webhook-обработчика.
- Uvicorn как ASGI-сервер.
- SQLite для хранения заявок и сессий.
- Собственный клиент для MAX API.
- Pydantic и pydantic-settings для конфигурации.
- Systemd для запуска сервиса.
- Nginx как reverse proxy.
- Let’s Encrypt для HTTPS.
Репозиторий открыт: github.com/A-Krivoshen/max-support-bot. Там можно посмотреть структуру проекта, код бота и то, как устроена логика заявок.
Основная идея простая: бот хранит состояние пользователя, понимает текущий шаг сценария, принимает сообщения и вложения, собирает заявку, а после подтверждения отправляет её администратору.
Long Polling сначала, Webhook потом
Изначально я сделал вариант на Long Polling. Это удобный старт: бот сам ходит в API и спрашивает, нет ли новых событий. Для локальных тестов и быстрого прототипа нормально.
Но на VPS соединение начало рваться по таймаутам. Для рабочего бота это не вариант. Если поддержка зависит от процесса, который периодически теряет связь и делает вид, что так и надо, это уже не поддержка, а генератор нервов.
В итоге я перевёл бота на Webhook. Теперь MAX отправляет обновления на мой сервер, а бот принимает их через FastAPI. Это правильнее для постоянной работы: меньше лишнего опроса, понятнее логика и стабильнее поведение.
Упрощённо схема такая:
Пользователь → MAX → webhook на VPS → FastAPI → обработчик сценария → SQLite → админ-канал
Как бот живёт на сервере
На сервере бот запущен под отдельным пользователем. Это нормальная привычка: не надо запускать прикладной сервис от root, если для этого нет железной причины. Root и так занят тем, что умеет ломать всё с размахом.
Проект лежит в отдельном каталоге, зависимости установлены в виртуальное окружение, конфигурация вынесена в env-файл. Токены и секреты в статью, конечно, не попадают.
Примерная структура запуска через systemd может выглядеть так:
max-support-bot/ ├── app/ │ ├── bot/ │ ├── tickets/ │ ├── main.py │ └── settings.py ├── .env ├── requirements.txt └── README.md
Пример unit-файла systemd, без реальных путей и секретов:
[Unit] Description=MAX Support Bot After=network.target [Service] User=maxbot Group=maxbot WorkingDirectory=/opt/max-support-bot EnvironmentFile=/opt/max-support-bot/.env ExecStart=/opt/max-support-bot/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8080 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
Nginx прокидывает внешний HTTPS-запрос на локальный Uvicorn. Примерно так:
server { listen 443 ssl http2; server_name webhook.example.com; ssl_certificate /etc/letsencrypt/live/webhook.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/webhook.example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
После правок в Nginx всегда проверяем конфиг:
sudo nginx -t sudo systemctl reload nginx
А сервис проверяем так:
sudo systemctl status max-support-bot sudo journalctl -u max-support-bot -f
Это базовая, скучная, но правильная часть. Бот может быть сколько угодно умным, но если systemd его не поднимает после падения, вся магия заканчивается первым таймаутом.
Что помог сделать Grok Build Beta
Отдельная часть эксперимента: я использовал Grok Build Beta как AI-агента для разработки. По скриншотам видно, что это терминальный агент с режимом авторизации через браузер, меню с worktree, resume session, changelog и рабочим процессом прямо в консоли.
В моём случае Grok Build помогал не «написать красивый текст», а именно двигать код. Он правил файлы, показывал diff, запускал проверки, улучшал FSM-логику заявок, навигацию и обработку состояний.
Например, на одном из этапов нужно было улучшить возврат к редактированию заявки, поведение кнопок и тексты в FSM. Агент нашёл нужные места, внёс изменения в несколько файлов и показал статистику diff.
Понравилось, что он не просто выдал простыню кода, а работал итерациями: посмотрел структуру, внёс правки, запустил команды, показал результат. Это уже ближе к нормальному рабочему помощнику, а не к «держи кусок Python, дальше сам».
Но важный момент: я всё равно смотрел, что он меняет. AI-агент может ускорить работу, но ответственность за проект не переезжает в терминал. Если он случайно сломает FSM или удалит нужный обработчик, отвечать будет не он, а я. Увы, кнопки «списать на нейросеть» в продакшене пока нет.
FSM: почему без состояния тут никуда
Заявка в поддержку — это не одно сообщение. Это цепочка шагов. Пользователь выбрал тему, потом версию плагина, потом WordPress, потом PHP, потом описание, потом вложение, потом подтверждение. Значит боту нужно помнить, где именно находится человек.
Для этого используется FSM, finite-state machine. По-русски можно сказать проще: машина состояний. У каждого пользователя есть текущий шаг, а каждое сообщение обрабатывается в зависимости от этого шага.
Условно логика выглядит так:
start → choose_topic → plugin_version → wordpress_version → php_version → description → attachments → confirm → submitted
Если пользователь нажал «Отмена», бот должен не упасть в обморок, а вернуть человека в понятное состояние. Если нажал «Назад», нужно показать предыдущий шаг. Если отправил файл там, где ждём текст, нужно аккуратно объяснить, что делать дальше.
Вот здесь AI-агент оказался полезен. Он помог улучшить навигацию по состояниям и тексты шагов, чтобы пользователь не терялся. А это для бота поддержки важнее, чем красивая архитектурная диаграмма.
Что сейчас происходит при создании заявки
Сценарий для пользователя выглядит примерно так:
- Пользователь открывает MAX Support Bot.
- Бот предлагает выбрать тему обращения.
- Пользователь указывает версию MAX Autopost.
- Бот спрашивает версию WordPress.
- Бот спрашивает версию PHP или даёт кнопку «Не знаю».
- Пользователь описывает проблему.
- Пользователь может прикрепить скриншот, лог или файл.
- Бот показывает заявку перед отправкой.
- После подтверждения заявка сохраняется и уходит мне.
На скриншоте как раз видно один из шагов: бот сохранил версию WordPress 7.0 и просит указать версию PHP или нажать «Не знаю». Это обычная мелочь, но из таких мелочей и собирается нормальная поддержка.
Почему это лучше личной переписки
Личная переписка хороша, когда обращений мало. Но как только вопросов становится больше, она начинает ломаться. Где-то потерялся скриншот, где-то забыли версию PHP, где-то человек прислал «не работает», а потом ушёл на два дня.
Бот решает это не магией, а дисциплиной. Он просто не даёт пропустить важные шаги. В итоге заявка получается полнее, а разбор быстрее.
Для пользователя плюс тоже есть: ему не нужно думать, что именно писать. Бот сам ведёт по сценарию. Это особенно полезно для людей, которые не обязаны знать, какие данные нужны разработчику для диагностики.
И да, я не хочу превращать поддержку в бюрократический квест. Поэтому сценарий должен быть коротким. Если бот спрашивает 25 полей перед тем, как принять проблему, пользователь справедливо решит, что проще жить с ошибкой.
Что проверять в таком боте
Бот поддержки кажется простым, пока не начинаешь проверять сценарии. Пользователи умеют нажимать не то, писать не туда, отправлять файл вместо текста, возвращаться назад, отменять заявку и начинать снова. И всё это должно работать.
Минимальный чек-лист:
- первый запуск бота;
- выбор темы обращения;
- переходы между шагами;
- кнопка «Назад»;
- кнопка «Отмена»;
- кнопка «В меню»;
- обработка «Не знаю» для версии PHP;
- прикрепление одного файла;
- прикрепление нескольких файлов;
- подтверждение заявки;
- отправка заявки в админ-канал;
- перезапуск сервиса во время активной сессии.
Отдельно нужно смотреть логи. Если бот молчит, это не значит, что он задумался о жизни. Скорее всего, где-то исключение, ошибка API или неверное состояние пользователя.
sudo journalctl -u max-support-bot -f
Если бот работает через webhook, полезно проверить, что endpoint доступен снаружи:
curl -I https://webhook.example.com/
А если есть healthcheck, лучше сделать отдельный URL:
https://webhook.example.com/health
Где обычно ломается
Long Polling рвётся по таймауту
Для старта Long Polling удобен, но на боевом VPS может вести себя нестабильно. У меня так и было. Перевод на Webhook оказался правильным решением.
Пользователь отправляет не то, что ждёт бот
Бот ждёт текст, а пользователь присылает картинку. Бот ждёт файл, а пользователь пишет «готово». Это нормальная жизнь. Обработчики должны быть готовы к таким вариантам, иначе FSM быстро превращается в лабиринт без выхода.
После перезапуска теряется сессия
Если состояние хранится только в памяти, после перезапуска сервиса пользователь может потеряться. Поэтому сессии лучше сохранять в базе. В моём случае используется SQLite, для MVP этого хватает.
Вложения приходят отдельно от текста
С файлами всегда веселее. Нужно принять вложение, сохранить привязку к заявке, не потерять подпись, не перепутать пользователя и не отправить администратору пустую заявку. Здесь нужно тестировать руками, а не верить, что «ну файл же прикрепился».
AI-агент правит больше, чем нужно
Это касается уже разработки. Grok Build может быстро внести полезные изменения, но за ним нужно смотреть. Если задача маленькая, лучше просить маленький diff. Не «перепиши весь бот красиво», а «исправь возврат к выбору темы и покажи diff».
После правок обязательно:
python -m compileall app git diff --stat git diff
Потом уже запуск и ручная проверка сценариев в MAX. Код может компилироваться и при этом логически делать ерунду. Python такой: синтаксис пропустил, а смысл оставил на совести автора.
Что хочу добавить дальше
Сейчас это MVP, но план развития уже понятен.
- Добавить больше сценариев обращений.
- Улучшить работу с несколькими вложениями.
- Сделать удобный просмотр заявок.
- Добавить статусы заявок.
- Сделать уведомления о новых обращениях понятнее.
- Добавить экспорт или просмотр истории.
- Подумать над маленькой админ-панелью.
- Добавить автоответы на типовые вопросы.
Отдельная идея — связать бота с документацией по MAX Autopost. Например, если человек выбирает вопрос про токен, бот сначала может дать короткую инструкцию. Если не помогло, тогда уже оформлять заявку. Так можно снизить количество ручных обращений без ощущения, что человека отправили читать стену текста.
Мой вывод
MAX Support Bot получился небольшим, но полезным проектом. Он решает конкретную проблему: превращает хаотичные обращения в поддержку в нормальные заявки с нужными данными.
Для меня это ещё и хороший тест современного AI-кодинга. Grok Build Beta помог ускорить разработку, но не заменил проверку. Он полезен как напарник: быстро найти место в коде, предложить diff, поправить сценарий, запустить команды. Но думать, тестировать и принимать решения всё равно приходится самому.
И это, пожалуй, правильная модель работы с такими инструментами. AI не должен быть волшебным чёрным ящиком, который сам всё сделал. Он должен быть ускорителем для разработчика. Особенно когда задача не абстрактная, а вполне земная: бот должен принять обращение, не потерять файл, не перепутать шаг и отправить заявку куда надо.
Пока бот работает, заявки собирает, код открыт. Буду дорабатывать дальше. А ручную переписку в стиле «пришлите ещё раз версию PHP» хочется оставить в прошлом. Там ей самое место, рядом с FTP без бэкапов и правками на проде через встроенный редактор темы.