Quick Start
В этом руководстве — /ping бот, который отвечает «pong». От нуля до
работающего deployment за 5 минут.
Шаг 1. Создать бота
В UI Reason Space: правый верхний угол → аватарка → Settings → Боты.
Кнопка Создать бота. Имя: Echo, username: echo_bot.
После создания UI покажет BOT_TOKEN вида bot_xxxxxxxx….
Токен показывается один раз. Сохраните его сразу — повторно получить нельзя. Если потеряется — кнопка Rotate на странице бота.
На странице бота → Пригласить в Space. Выберите space, отметьте:
- Scopes:
commands(право регистрировать slash-команды и принимать событиеcommand.invoked). Для отправки сообщений в канал добавьтеmessages.send. - Channels: text-канал, где будут вызывать
/ping
Scope commands запрашивается именно здесь, при invite, — не в коде бота.
Сама регистрация набора команд (PUT /api/bot/commands) — глобальная и от
scope не зависит. Но без commands ваш бот не появится в каталоге команд
канала (GET /api/chat/{space}/{channel}/commands), а юзеры не смогут
вызвать его команды (invoke → 403). Полный список —
Scopes.
Шаг 2. Установить SDK
pip install 'reasonspace-bot[server]'
Extra [server] подтягивает uvicorn, нужный для встроенного bot.run()
(Шаг 5). Без него bot.run() бросит RuntimeError. В основные зависимости
SDK входят только httpx и starlette.
Шаг 3. Написать бота
Бот регистрирует свой набор slash-команд (bulk-overwrite через
PUT /api/bot/commands) и обрабатывает вызов команды на событии
command.invoked. Имя команды передаётся без слэша.
import asyncio
from reasonspace_bot import Bot, CommandInvokedEvent
bot = Bot() # читает BOT_TOKEN + WEBHOOK_SECRET из env
@bot.command("ping") # имя без слэша; ловит /ping в чате
async def on_ping(event: CommandInvokedEvent) -> None:
# Эфемерный ответ — виден только тому, кто вызвал команду.
await bot.respond(event, "🏓 pong")
async def setup() -> None:
# Декларируем ВЕСЬ набор команд бота (idempotent overwrite).
await bot.client.register_commands([
{"name": "ping", "description": "Проверка связи", "options": []},
])
if __name__ == "__main__":
asyncio.run(setup())
bot.run(port=8765)
@bot.command("ping") — имя без /, без параметров scope= и
description=. Хендлер получает CommandInvokedEvent (поля command,
channel_id, actor_user_id, options, interaction_token), а эфемерный
ответ инвокеру отправляется через await bot.respond(event, content) —
под капотом это POST /api/bot/interactions/respond. Подробнее —
Команды.
Шаг 4. Создать webhook
На странице бота → Webhooks → Создать:
- URL:
http://localhost:8765/webhook(или туннель, если бот не на той же машине) - Events: ☑
command.invoked
UI покажет WEBHOOK_SECRET — также один раз. Сохраните.
Шаг 5. Запустить
export BOT_TOKEN=bot_xxxxxxxxxxxx
export WEBHOOK_SECRET=whsec_xxxxxxxxxxxx
export REASONSPACE_API=https://api.reasonspace.ru # опционально
python bot.py
# → INFO Uvicorn running on http://0.0.0.0:8765
Зайдите в Reason Space → в канал, куда пригласили бота → вызовите /ping →
бот ответит 🏓 pong эфемерно (ответ увидите только вы).
E2E: Reason Space шифрует chat-сообщения end-to-end, и бот не может
прочитать обычный текст из ленты. Обычные сообщения юзеров боту как webhook
не доставляются — единственный inbound-канал юзер→бот — это slash-команды.
Текст приходит только как структурированные options команды внутри события
command.invoked (по явному opt-in юзера, привязаны к схеме команды и не
попадают в ленту/модерацию). См. Privacy и
Команды.