Skip to content

Repository files navigation

openclaw-max-plus – плагин MAX для OpenClaw

license TypeScript Node

Important

Для распознавания голосовых настройте Webhook.

При Long Polling (GET /updates) нативные голосовые, записанные микрофоном в MAX, могут приходить как пустой message_created: без message, аудиофайла и идентификатора чата. Плагину нечего передать на распознавание. Обсуждение ограничения и перехода на вебхуки.

Укажите channels.max.webhookUrl — публичный HTTPS-адрес на порту 443 с доверенным сертификатом — и channels.max.webhookSecret, затем перезапустите Gateway. Для расшифровки также нужен настроенный движок распознавания OpenClaw (tools.media.audio), например локальный Whisper. Сам вебхук обеспечивает доставку аудио.

Проверено 9 сентября 2026 года: голосовое из приложения MAX дошло через вебхук, Whisper распознал речь, бот ответил. В плагине 0.6.2 также исправлено дублирование черновика и готового ответа при streamMode: "partial"; повторная проверка в MAX подтвердила исправление.

Канал-плагин для подключения AI-ассистента OpenClaw к мессенджеру MAX (max.ru Bot API).

English: openclaw-max-plus connects OpenClaw to MAX using the Bot API. Supports text, media, inline buttons, response streaming, polling, webhooks, multiple accounts, and sender-based agent routing. Requires OpenClaw 2026.9.3+, Node.js 24.16+ on the 24.x branch or 26.1+. Full setup guide below is in Russian.

Что это

Плагин позволяет общаться с OpenClaw-ботом через мессенджер MAX — так же, как через Telegram. Поддерживает:

  • Приём и отправку текстовых сообщений (markdown)
  • Вложения: фото, видео, файлы, стикеры, контакт, локация (в т.ч. inline-base64 — напр. сгенерированные картинки)
  • Длинные подписи к медиа (>4000 — остаток уходит follow-up-сообщениями)
  • Inline-кнопки: callback (+цвет intent), link, request_contact, request_geo_location, message, clipboard, open_app; выбор модели
  • Reply, forward (приём с атрибуцией автора/канала), edit, delete
  • Pin/unpin сообщений (admin-only, группы/каналы)
  • Стриминг ответа (streamMode: partial / block), typing-индикатор
  • Long polling и Webhook (с валидацией secret/url)
  • Мультиаккаунт, DM-security, pairing, групповые политики

Реакции и опросы MAX Bot API не поддерживает (платформенное ограничение).

Структура проекта

openclaw-max-plus/
├── openclaw.plugin.json    # Манифест плагина
├── package.json
├── index.ts               # Точка входа плагина (register → channel)
├── tsconfig.json
├── README.md
├── src/
│   ├── types.ts            # TypeScript-типы MAX Bot API
│   ├── api.ts              # HTTP-клиент MAX API (send/edit/delete/upload/actions)
│   ├── monitor.ts          # Long polling + webhook (приём обновлений, dispatch)
│   ├── webhook.ts          # Обработчик webhook-запросов
│   ├── send.ts             # Высокоуровневые send-хелперы (текст/медиа/edit)
│   ├── channel.ts          # OpenClaw channel adapter
│   ├── config-schema.ts    # Zod-схема конфига канала
│   ├── accounts.ts         # Резолвинг аккаунтов из конфига
│   ├── runtime.ts          # Доступ к OpenClaw runtime
│   ├── actions.ts          # Действия/команды
│   ├── model-buttons.ts    # Кнопки выбора модели
│   ├── onboarding.ts       # Онбординг/настройка аккаунта
│   ├── format.ts           # Форматирование текста
│   └── sticker-cache.ts    # Кэш стикеров
└── scripts/
    ├── test-api.mjs        # Проверка токена и API (GET /me + GET /updates)
    └── test-send.mjs       # Тест send + edit + delete

🤖 Инструкция для агента: как настроить OpenClaw с этим плагином

Пошаговый runbook (выполнять по порядку, проверяя результат каждого шага).

0. Предусловия

  • OpenClaw 2026.9.3 или новее; версия 0.6.1 проверена с SDK 2026.9.3.
  • Node.js 24.16+ (ветка 24) или 26.1+, согласно требованиям OpenClaw 2026.9.3. Для авто-доверия CA Минцифры используется tls.setDefaultCACertificates. Проверка: node -e "const t=require('node:tls');console.log(typeof t.setDefaultCACertificates)" → должно быть function.
  • Установлен openclaw (CLI/gateway). Проверка: openclaw --version.
  • Есть токен бота MAX (см. «Установка → Создать бота в MAX» ниже). Никогда не печатать токен в логи/коммиты.

1. Собрать плагин (entry — dist/index.js; build кладёт и dist/certs/ с CA):

cd /путь/к/openclaw-max-plus
npm install
npm run typecheck && npm run lint && npm test   # должно быть зелёным
npm run build

2. Подключить плагин к OpenClaw. Способ А — через CLI:

openclaw plugins install --link /путь/к/openclaw-max-plus   # симлинк (live-разработка)

Способ Б — прописать путь в ~/.openclaw/openclaw.json (gateway грузит из рабочей папки):

{ "plugins": { "entries": { "openclaw-max-plus": { "enabled": true } },
               "load": { "paths": ["/путь/к/openclaw-max-plus"] } } }

3. Настроить канал в ~/.openclaw/openclaw.json (минимум — токен + кто может писать):

{ "channels": { "max": {
  "enabled": true,
  "botToken": "ТОКЕН_БОТА",       // или "tokenFile": "/path/to/token", или env MAX_BOT_TOKEN
  "dmPolicy": "allowlist",         // pairing | allowlist | open
  "allowFrom": ["ВАШ_USER_ID"],    // см. шаг 6, как узнать user_id
  "streamMode": "partial"
}}}

Держать src/config-schema.tsopenclaw.plugin.json в синхроне при добавлении полей.

Для разных агентов в личных диалогах задавайте bindings[].match.peer как { "kind": "direct", "id": "USER_ID" }. Начиная с 0.6.1 маршрут и ключ сессии используют sender.user_id; ответы по-прежнему уходят в реальный recipient.chat_id. После обновления старые сессии, названные по ID чата, остаются в истории; новый входящий диалог получает ключ по ID пользователя. Для групп маршрут использует ID чата. При нескольких агентах задайте также владельца канала: например, { "agentId": "main", "match": { "channel": "max", "accountId": "default" } }. Привязка конкретного пользователя имеет приоритет над владельцем канала.

4. Индикатор «печатает…» — ОБЯЗАТЕЛЬНО задать глобально (иначе индикатор будет мигать и обрываться, в MAX одиночный typing_on живёт ~5–6с):

openclaw config set agents.defaults.typingIntervalSeconds 4

5. Перезапустить gateway — зависит от того, как он запущен:

  • launchd-сервис (launchctl list | grep openclaw показывает ai.openclaw.gateway): launchctl kickstart -k "gui/$(id -u)/ai.openclaw.gateway"
  • вручную: остановить и openclaw gateway --port 18789 (или openclaw gateway restart, если поддерживается).

После ЛЮБОЙ правки кода: npm run build → перезапуск gateway (плагин держится в памяти, на лету не подхватывается).

6. Проверить и найти свой user_id:

openclaw plugins inspect openclaw-max-plus --runtime        # канал max зарегистрирован?
# Живой лог gateway (stdout). Путь зависит от запуска:
tail -f ~/Library/Logs/openclaw/gateway.log   # macOS launchd
# Написать боту в MAX любой текст → в логе появится "Starting MAX provider (@bot)" и обработка;
# user_id отправителя виден в логах или: MAX_BOT_TOKEN=xxx node scripts/test-api.mjs (раздел updates)

Подставить найденный user_id в allowFrom (шаг 3) и перезапустить gateway. Бот должен ответить.

7. Диагностика «бот не отвечает» (по приоритету):

  1. getUpdates/TLS падает → проверь домен: curl -I -H "Authorization: ТОКЕН" https://platform-api2.max.ru/me (200/401 = TLS ок; TLS:20/UNABLE_TO_GET_ISSUER = нет CA → Node < 22.15 или npm run build не клал certs/ → обнови Node и пересобери плагин с certs/).
  2. Сообщение приходит, но ответа нет → смотри ~/.openclaw/agents/main/sessions/*.jsonl (последние записи): дошёл ли inbound, не упал ли toolResult отправки (напр. POST /messages → 404 = неверный chat_id; ENAMETOOLONG = inline-медиа; LLM-биллинг = квота).
  3. dmPolicy/allowFrom блокируют отправителя → проверь user_id в allowFrom.

Установка

1. Создать бота в MAX

  1. Зайти на business.max.ru (нужно юрлицо/ИП)
  2. Создать профиль организации и пройти верификацию
  3. Раздел Чат-ботыСоздать (название, лого 500x500, описание)
  4. Дождаться модерации (до 48ч по рабочим дням)
  5. После модерации: Чат-боты → Интеграция → Получить токен

2. Собрать и подключить плагин

cd openclaw-max-plus
npm install
npm run build                          # собирает dist/ (entry: dist/index.js)

# Подключить плагин к OpenClaw из локальной папки
openclaw plugins install ./.           # или абсолютный путь к папке плагина

Альтернатива для разработки — указать путь к плагину прямо в конфиге ~/.openclaw/openclaw.json, тогда gateway грузит его из рабочей папки:

{
  "plugins": {
    "entries": { "openclaw-max-plus": { "enabled": true } },
    "load": { "paths": ["/путь/к/openclaw-max-plus"] }
  }
}

3. Настроить канал

Добавить секцию в ~/.openclaw/openclaw.json:

{
  "channels": {
    "max": {
      "enabled": true,

      // Токен бота из business.max.ru → Чат-боты → Интеграция
      "botToken": "ваш_токен_бота",

      // Политика личных сообщений (по умолчанию "pairing"):
      //   "pairing"   — новый контакт проходит pairing-код
      //   "allowlist" — только user_id из allowFrom
      //   "open"      — любой (требует allowFrom: ["*"])
      "dmPolicy": "allowlist",

      // Список user_id, которым разрешено писать боту
      // Узнать свой user_id: написать боту и посмотреть в логах
      "allowFrom": ["12345678"],

      // Режим стриминга ответа: "off" | "partial" | "block"
      "streamMode": "partial"
    }
  }
}

4. Перезапустить gateway

openclaw gateway restart

Можно проверить регистрацию канала: openclaw plugins inspect openclaw-max-plus --runtime.

Индикатор «печатает…» (typing)

MAX гасит индикатор «печатает…» через несколько секунд, поэтому плагин переотправляет его весь ход ответа через keepalive хоста. Частота переотправки задаётся глобальным параметром agents.defaults.typingIntervalSeconds (по умолчанию 6с). Одиночный typing_on в MAX живёт ~5–6с, поэтому значение по умолчанию (6с) даёт разрывы. Обязательно выставьте 4 — иначе индикатор будет мигать и обрываться:

openclaw config set agents.defaults.typingIntervalSeconds 4
openclaw gateway restart

Параметр общий для всех каналов (затронет и Telegram — для него 4с тоже безопасно). Индикатор «печатает…» бота отображается в мобильном клиенте MAX; веб-версия его показывает ненадёжно — это особенность клиента MAX.

Команды бота

Начиная с версии 0.6.3, плагин регистрирует меню через PATCH /me/commands. Команды отображаются в MAX как подсказки при вводе / и отправляются боту обычным текстом. Выполнение команд и проверка прав остаются на стороне OpenClaw.

Чтобы показывать встроенные команды OpenClaw, включите автоматическое меню:

{
  "channels": {
    "max": {
      "commands": "auto"
    }
  }
}

Плагин берёт список из реестра установленной версии OpenClaw. MAX принимает не более 32 команд, поэтому /help, /commands, /new, /stop, /status, /models, /model и другие основные команды идут первыми. Остальные команды доступны через /commands и ручной ввод. Отдельные команды навыков в меню автоматически не добавляются; для них есть /skill. Описания берутся из реестра OpenClaw: русские при наличии перевода, иначе исходные. При commands.native: false или commands.text: false в глобальной конфигурации режим auto очищает меню.

Можно задать собственный список с русскими описаниями:

{
  "channels": {
    "max": {
      "commands": [
        { "name": "status", "description": "Статус и лимиты подписки" },
        { "name": "new", "description": "Начать новую сессию" },
        { "name": "stop", "description": "Прервать текущую задачу" },
        { "name": "models", "description": "Выбрать модель" }
      ]
    }
  }
}

name задаётся без / (1–64 символа), description — до 128 символов. Ручной список полностью задаёт меню; он не создаёт новые обработчики команд. commands: [] удаляет все команды из меню. Если поле отсутствует, плагин не меняет меню, настроенное через MAX API или другой инструмент.

Для нескольких ботов можно задать channels.max.accounts.<id>.commands. Настройка аккаунта имеет приоритет над общей; пустой массив также считается явным переопределением и очищает меню только этого бота.

После изменения перезапустите Gateway. В логах появится Registered N bot commands via PATCH /me/commands; список можно сверить через GET /me. Ошибка регистрации меню записывается в лог и не останавливает канал.

Настройка — основные поля канала

Поле Тип Описание
enabled boolean Включить канал
botToken string API-токен бота (или tokenFile — путь к файлу с токеном)
dmPolicy string pairing (по умолч.) / allowlist / open
allowFrom string[] Разрешённые user_id (для open["*"])
groupPolicy string Политика групп, по умолч. allowlist
groupAllowFrom string[] Разрешённые user_id в группах
groups object Пер-групповые настройки (requireMention, allowFrom, tools, skills, …)
streamMode string off / partial / block
webhookUrl string URL webhook (если не используется long polling)
webhookSecret string Секрет для валидации webhook (рекомендуется в webhook-режиме)
webhookPath string Путь webhook-эндпоинта (по умолч. из webhookUrl или /max)
responsePrefix string Префикс к ответам бота
mediaMaxMb number Лимит размера медиа
commands "auto" или object[] Встроенные команды OpenClaw либо ручное меню; [] очищает меню — см. «Команды бота»
accounts object Дополнительные аккаунты (мультиаккаунт)

Полный список — в src/config-schema.ts.

Использование

Как написать боту

  1. Найти бота в MAX по нику
  2. Нажать Старт или отправить любое сообщение
  3. Бот ответит, если ваш user_id разрешён политикой (dmPolicy / allowFrom)

Как узнать свой user_id

Написать боту, затем посмотреть в логах OpenClaw:

openclaw logs --follow
# В логах будет sender.user_id входящего сообщения

Или запустить тест-скрипт:

MAX_BOT_TOKEN=xxx node scripts/test-api.mjs
# В разделе updates будет виден ваш user_id

Мультиаккаунт

Можно подключить несколько ботов MAX — например, рабочий и личный:

{
  "channels": {
    "max": {
      // Аккаунт по умолчанию
      "botToken": "токен_основного_бота",
      "allowFrom": ["12345678"],

      // Дополнительные аккаунты
      "accounts": {
        "zaya": {
          "botToken": "токен_второго_бота",
          "allowFrom": ["87654321"],
          "dmPolicy": "open"
        }
      }
    }
  }
}

Разработка

Требования

  • Node.js 20+ (встроенный fetch)
  • TypeScript 6

Команды

npm install
npm run build          # сборка dist/
npm run typecheck      # tsc --noEmit
npm run lint           # eslint (lint:fix — с автофиксом)
npm run format         # prettier --write (format:check — проверка)
npm test               # vitest (test:watch — watch-режим)

Перед коммитом: npm run typecheck && npm run lint && npm test.

Тест API (проверка что токен работает)

# Проверить бота: GET /me + GET /updates
MAX_BOT_TOKEN=xxx node scripts/test-api.mjs

# С отправкой тестового сообщения в чат
MAX_BOT_TOKEN=xxx node scripts/test-api.mjs <chat_id>

Тест отправки (send + edit + delete)

MAX_BOT_TOKEN=xxx node scripts/test-send.mjs <chat_id> "Текст сообщения"

MAX Bot API — краткая справка

Метод Endpoint Описание
GET /me Информация о боте (user_id, name, username)
PATCH /me/commands Задать меню команд; commands: [] удаляет команды
GET /updates Long polling (marker, timeout, types)
POST /messages Отправить (?chat_id или ?user_id)
PUT /messages Редактировать (?message_id)
DELETE /messages Удалить (?message_id)
POST /chats/{chatId}/actions Действия (typing_on, mark_seen, …)
POST /answers Ответ на callback (?callback_id)
POST · GET · DELETE /subscriptions Webhook: подписка / список / отписка
POST /uploads Загрузка медиа
  • Авторизация: заголовок Authorization: <token> (query-параметр access_token устарел).
  • Документация: dev.max.ru/docs-api
  • ⚠️ GET /chats (список чатов) помечен устаревшим с июня 2026; одиночный GET /chats/{chatId} работает.
  • Команды бота задаются через PATCH /me/commands; тело { "commands": [...] }, ответ { "commands": [...] }, максимум 32 команды.
  • Домен: по умолчанию platform-api2.max.ru (legacy platform-api.max.ru отключается 19.07.2026). Этот домен подписан корневым CA Минцифры — плагин бандлит CA и авто-доверяет ему в рамках процесса (certs/, src/ca-trust.ts), без установки сертификата в систему. Требует Node ≥ 22.15. Откат/override: apiBaseUrl в конфиге канала или env MAX_API_BASE_URL.

Лицензия

См. LICENSE.

About

MAX messenger (max.ru) bot channel plugin for OpenClaw — AI-ассистент в мессенджере MAX. TypeScript, Bot API, long polling + webhook.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages