Guide: Создать бота и отправить первое сообщение
Пошаговый гайд для разработчиков, которые пишут своего первого бота для PartyFlow: получить токен, вступить в канал, проверить self-check, отправить сообщение. Весь флоу — 5-10 минут.
Для углублённого tour по архитектуре ботов — concepts/bots.md. Полный справочник endpoints — reference/bot-rest-api.md.
Что понадобится
- Доступ к workspace (space) в PartyFlow с правами admin'а — нужны для создания бота.
- ID канала, в который бот будет писать — скопируйте из URL или из Channel settings → About.
- Secrets manager (Vault, AWS Secrets Manager, 1Password для dev). Bot token показывается один раз и его нельзя восстановить — только перевыпустить.
Базовый URL в примерах — $BASE (адрес вашей инсталляции PartyFlow, например https://api.partyflow.ru).
Шаг 1. Создать бота в UI
Space → Integrations → Bots → New bot:
| Поле | Пример | Заметки |
|---|---|---|
| Display name | Standup Bot |
Имя, которое видят участники канала. 1..64 символа. |
| Avatar URL | https://cdn.example.com/bot.png |
HTTPS only, опционально. |
Нажмите Create. Появится диалог с bot token — строка вида fri_bot_<base64url>.
Сразу сохраните токен в secrets manager. После закрытия диалога его нельзя посмотреть снова — только Regenerate token, что инвалидирует старый.
# Сохраните в окружение для последующих шагов
export TOKEN='fri_bot_...'
export BASE='https://api.partyflow.ru'
export CHANNEL_ID='<uuid-канала>'Шаг 2. Добавить бота в канал
Бот должен быть участником канала, чтобы слать туда сообщения. Два способа:
Способ A. Через UI (ручной)
В канале → Channel settings → Members → Add bot → выбрать вашего бота → Add.
Способ B. Через REST (programmatic, идемпотентно)
curl -X POST "$BASE/api/v1/bot/conversations/$CHANNEL_ID/join" \
-H "Authorization: Bearer $TOKEN"Ожидаемый ответ:
{"ok": true}Этот endpoint идемпотентен — если бот уже в канале, вернётся тот же 200. Можно вызывать при каждом старте вашего сервиса — это частый паттерн для ботов, которые должны гарантировать своё присутствие в канале.
Ограничения:
- Бот должен принадлежать тому же space, что и канал.
- Для
/joinподдерживаются только групповые каналы. DM не требуют join: пользователь создаёт direct-чат с ботом в UI или бот вызываетPOST /api/v1/bot/dm.
Шаг 3. Self-check через GET /api/v1/bot/me
Проверьте, что токен активен и бот не отключён админом:
curl "$BASE/api/v1/bot/me" \
-H "Authorization: Bearer $TOKEN"Ответ:
{
"ok": true,
"bot": {
"id": "<uuid>",
"space_id": "<uuid>",
"display_name": "Standup Bot",
"avatar_url": "https://cdn.example.com/bot.png",
"is_active": true,
"event_types": ["MESSAGE_CREATED"],
"channel_ids": [],
"event_delivery_mode": "none",
"webhook_url": ""
}
}Если /bot/me возвращает 401 — токен недействителен, перевыпущен или бот отключён админом. Если успешный ответ содержит "is_active": false, попросите админа включить бота обратно через UI.
Этот endpoint стоит дёшево — вызовите его при старте сервиса как health-check.
Шаг 4. Первое сообщение
curl -X POST "$BASE/api/v1/bot/messages" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"conversation_id\":\"$CHANNEL_ID\",\"content\":\"Hello from my first bot!\"}"Ожидаемый ответ:
{"ok": true, "message_id": "<uuid>"}Если вы увидели это в канале — первое сообщение отправлено. Поздравляем.
Python-вариант
import os
import requests
BASE = os.environ["BASE"]
TOKEN = os.environ["TOKEN"]
CHANNEL_ID = os.environ["CHANNEL_ID"]
session = requests.Session()
session.headers.update({"Authorization": f"Bearer {TOKEN}"})
# Self-check
me = session.get(f"{BASE}/api/v1/bot/me").json()
assert me["bot"]["is_active"], "bot is disabled by admin"
print(f"Bot ready: {me['bot']['display_name']}")
# Idempotent join (call on every startup)
session.post(f"{BASE}/api/v1/bot/conversations/{CHANNEL_ID}/join")
# Send message
resp = session.post(
f"{BASE}/api/v1/bot/messages",
json={
"conversation_id": CHANNEL_ID,
"content": "Hello from my first bot!",
},
)
resp.raise_for_status()
print(resp.json())Запускается без зависимостей, кроме requests. Для production замените session.post на обработку ошибок (см. ниже раздел Troubleshooting).
Шаг 5. DM и SSE Stream (опционально)
Если ваш бот должен работать в личных переписках (например, AI-ассистент, helpdesk-бот, личный reminder), используйте DM + SSE Stream.
5a. Создать DM с пользователем
curl -X POST "$BASE/api/v1/bot/dm" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"user_id":"USER_ID"}'Ответ:
{"ok": true, "conversation_id": "<uuid>"}Сохраните conversation_id — через него бот будет отправлять сообщения в эту личку (POST /api/v1/bot/messages с этим conversation_id).
5b. Подключить SSE Stream
curl -N "$BASE/api/v1/bot/stream" \
-H "Authorization: Bearer $TOKEN"Формат — text/event-stream. Каждое сообщение:
data: {"event":"message.new","message_id":"...","conversation_id":"...","author_id":"...","text":"...","msg_index":1042,"sent_at":"...","conversation_context":{"conversation_id":"...","type":"chat","scope":"dm","is_direct":true,"is_public":false}}
В SSE payload автор приходит как плоское поле author_id; вложенного author.user_id нет. Контекст беседы приходит в conversation_context: для DM это scope="dm", для публичных/приватных каналов в Poll/Webhook будет public или private, для Call Thread — type="thread" и subtype="call_thread".
Keep-alive ping (игнорируйте):
:ping
Обработка на вашей стороне:
import requests
resp = requests.get(
f"{BASE}/api/v1/bot/stream",
headers={"Authorization": f"Bearer {TOKEN}"},
stream=True,
)
for line in resp.iter_lines():
if not line:
continue
if line.startswith(b":"):
continue # ping
if line.startswith(b"data: "):
payload = json.loads(line[6:])
if payload.get("event") == "message.new":
ctx = payload["conversation_context"]
print(f"New {ctx['scope']} message from {payload['author_id']}: {payload['text']}")Reconnect: при обрыве соединения reconnect с exponential backoff (1с → 2с → 4с … max 30с). Backlog сообщений, пришедших пока бот был offline, доставляется автоматически при reconnect.
Шаг 6. Что дальше
Базовый бот работает. Следующие расширения зависят от сценария:
- Личные переписки (DM) — reference/bot-rest-api.md → DM и SSE Stream.
POST /api/v1/bot/dm+GET /api/v1/bot/stream. - Читать историю канала (для AI-summarizer'ов, индексеров) — reference/bot-rest-api.md → Чтение истории канала. Endpoint
GET /api/v1/channels/{id}/messages. - Загрузить файл и прикрепить к сообщению — reference/bot-rest-api.md → Bot Files API. Создайте upload session, загрузите байты по short-lived URL, подтвердите файл и передайте
attachments: [{"file_id": "..."}]. - Долгие AI-ответы — reference/bot-rest-api.md → Agent Runs. Создайте run, обновляйте
sequence, завершайтеcompletedсpublic_textи optional final files. - Task widgets для агентских задач — reference/bot-rest-api.md → Execution Tasks. Используйте, когда пользователю нужен отдельный статус задачи, artifacts и review flow.
- Кастомные slash-команды (
/deploy,/standup) — reference/slash-commands.md. Бот регистрирует команду и получает invocation через HTTP callback или Poll API. - Интерактивные кнопки и модалки (approval flows, deploy-подтверждения) — guides/bot-interactive-quickstart.md для быстрого старта или reference/interactive-components.md для полного справочника. Доставка click/submit событий поддерживает callback и Poll API.
- Аттачменты, блоки, severity-badges в сообщениях — reference/message-format.md. Отправляются через поле
metadata_jsonвPOST /api/v1/bot/messages.
Troubleshooting
| Симптом | Причина | Решение |
|---|---|---|
401 invalid or revoked token |
Неправильный токен, токен перевыпущен, или бот отключён админом. | Проверьте токен в secret manager и попросите админа подтвердить, что бот активен. Если /bot/me тоже возвращает 401, нужен новый токен или re-enable бота. |
401 missing authorization header |
Забыли заголовок Authorization: Bearer .... |
Добавьте -H "Authorization: Bearer $TOKEN". |
401 invalid authorization format |
Формат Authorization без префикса Bearer или с лишними пробелами. |
Используйте строго Authorization: Bearer fri_bot_.... |
403 / 400 failed to join conversation на /join |
Бот пытается вступить в канал из другого space, или беседа — DM, или канала нет. | Проверьте: (1) канал существует, (2) тот же space, что и у бота, (3) это групповой канал. Для DM используйте POST /api/v1/bot/dm. |
400 bot not in conversation на /messages |
Бот ещё не вступил в канал. | Вызовите POST /api/v1/bot/conversations/{id}/join (Шаг 2). |
400 content too long (max 4000 chars) |
Длина content > 4000 символов. |
Разбейте сообщение на несколько, либо используйте metadata_json с attachment для длинного блока. |
400 conversation_id is required / content or attachments required |
Пустое или отсутствующее поле. | Проверьте payload: нужен conversation_id и хотя бы content или один подтверждённый file attachment. |
400 invalid JSON |
Сломанный JSON в body. | Прогоните payload через jq . перед отправкой. |
400 user not found на /bot/dm |
Пользователь не состоит в space'е бота, или user_id совпадает с bot_id. |
Проверьте user_id и убедитесь, что пользователь — участник того же space'а. |
429 Too Many Requests |
Превышен rate limit — 10 msg/sec на канал или 1 req/sec на /bot/dm. |
Дождитесь окна и продолжите. Для burst'ов используйте message queue на вашей стороне. |
500 failed to send message |
Внутренняя ошибка chat-слоя. | Повторите с exponential backoff — типично транзиент. |
| SSE stream обрывается каждые ~30 секунд без сообщений | Это нормально — :ping keep-alive. |
Игнорируйте строки, начинающиеся с :. Используйте их только для health-check соединения. |
| SSE stream не получает сообщения из групповых каналов | SSE работает только для DM. | Для групповых каналов настройте outgoing webhook в admin UI. |
Сообщение отправилось (message_id вернулся), но в канале не видно |
Возможно, канал заархивирован или участники его не открывают. | Проверьте в UI, откройте сам канал. |
Rate limits: 10 сообщений/сек на канал. При превышении — HTTP 429 + заголовок Retry-After. Читайте заголовок, не угадывайте интервал.
Логирование: при ошибках сохраняйте полный HTTP-ответ (status + body) — это главный ключ к диагностике.
Связанное
- concepts/bots.md — концепция ботов, authentication, lifecycle, privacy.
- reference/bot-rest-api.md — полный справочник endpoints.
- concepts/security.md — хранение bot tokens, ротация, HMAC для callback-mode interactive/slash delivery.
- guides/bot-interactive-quickstart.md — "от нуля до первой кнопки" за 5 минут.