Перейти к основному содержимому

Настройка Google Chat

Подключите VibeOS к Google Chat в качестве бота. Интеграция использует pull-подписки Cloud Pub/Sub для входящих событий и Chat REST API для исходящих сообщений. Эргономика эквивалентна Slack Socket Mode или long-polling в Telegram: ваш процесс VibeOS не требует публичного URL, туннеля или TLS-сертификата. Он подключается, аутентифицируется и слушает подписку — так же, как бот Telegram слушает токен.

Выполните vibeos gateway setup и выберите Google Chat для пошаговой настройки.

Версия Workspace

Google Chat является частью Google Workspace. Вы можете использовать эту интеграцию с личным Workspace (@yourdomain.com, зарегистрированным через Google) или рабочим Workspace, где у вас есть права администратора для публикации приложения. Аккаунты только с Gmail не могут размещать Chat-приложения.

Обзор​

КомпонентЗначение
Библиотекиgoogle-cloud-pubsub, google-api-python-client, google-auth
Входящий транспортPull-подписка Cloud Pub/Sub (без публичной конечной точки)
Исходящий транспортChat REST API (chat.googleapis.com)
АутентификацияJSON-файл сервисного аккаунта с roles/pubsub.subscriber на подписке
Идентификация пользователейChat resource names (users/{id}) + email

Шаг 1: Создайте или выберите проект GCP​

Вам нужен проект Google Cloud для размещения темы Pub/Sub. Если у вас его нет, создайте его на console.cloud.google.com — личные аккаунты получают бесплатный уровень, который легко покрывает трафик бота.

Запомните ID проекта (например, my-chat-bot-123). Он понадобится на каждом последующем шаге.


Шаг 2: Включите два API​

В консоли перейдите в APIs & Services → Library и включите:

  • Google Chat API
  • Cloud Pub/Sub API

Оба бесплатны для объёмов, которые генерирует личный бот.


Шаг 3: Создайте сервисный аккаунт​

IAM & Admin → Service Accounts → Create Service Account.

  • Имя: vibeos-chat-bot
  • Пропустите шаг «Grant this service account access to project». IAM на конкретной подписке — это всё, что вам нужно. НЕ предоставляйте роли Pub/Sub на уровне проекта.

После создания откройте SA, перейдите в Keys → Add Key → Create new key → JSON и скачайте файл. Сохраните его в месте, доступном только для чтения VibeOS (например, ~/.vibeos/google-chat-sa.json, chmod 600).

Роли «Chat Bot Caller» не существует

Распространённая ошибка — искать специфическую для Chat роль IAM и назначать её на уровне проекта. Такой роли не существует. Полномочия бота Chat определяются его установкой в пространстве, а не IAM. Всё, что нужно вашему SA — это роль подписчика Pub/Sub на подписке, которую вы создадите на следующем шаге.


Шаг 4: Создайте тему и подписку Pub/Sub​

Pub/Sub → Topics → Create topic.

  • Topic ID: vibeos-chat-events
  • Оставьте значения по умолчанию для всего остального.

После создания на странице темы перейдите на вкладку Subscriptions. Создайте подписку:

  • Subscription ID: vibeos-chat-events-sub
  • Delivery type: Pull
  • Message retention: 7 days (чтобы backlog пережил перезапуск vibeos)
  • Остальное оставьте по умолчанию.

Шаг 5: Привязка IAM к теме (критически важно)​

На теме (не на подписке) добавьте IAM-участника:

  • Principal: chat-api-push@system.gserviceaccount.com
  • Role: Pub/Sub Publisher

Без этого Google Chat не сможет публиковать события в вашу тему, и ваш бот никогда ничего не получит.


Шаг 6: Привязка IAM к подписке​

На подписке добавьте ваш собственный сервисный аккаунт в качестве участника:

  • Principal: vibeos-chat-bot@<your-project>.iam.gserviceaccount.com
  • Role: Pub/Sub Subscriber

Также предоставьте Pub/Sub Viewer на той же подписке — VibeOS вызывает subscription.get() при запуске для проверки доступности.


Шаг 7: Настройте Chat-приложение​

Перейдите в APIs & Services → Google Chat API → Configuration.

  • App name: как хотите, чтобы пользователи видели («VibeOS» — разумный вариант).
  • Avatar URL: любое публичное PNG (у Google есть несколько стандартных).
  • Description: короткое предложение, отображаемое в каталоге приложений.
  • Functionality: включите Receive 1:1 messages и Join spaces and group conversations.
  • Connection settings: выберите Cloud Pub/Sub, введите имя темы projects/<your-project>/topics/vibeos-chat-events.
  • Visibility: ограничьте вашим рабочим пространством (или конкретными пользователями) — не публикуйте для всех, пока тестируете.

Сохраните.


Шаг 8: Установите бота в тестовое пространство​

Откройте Google Chat в браузере. Начните диалог с вашим приложением, найдя его имя в меню + New Chat. При первом сообщении Google отправляет событие ADDED_TO_SPACE, которое VibeOS использует для кэширования собственного users/{id} бота для фильтрации само-сообщений.


Шаг 9: Настройте VibeOS​

Добавьте раздел Google Chat в ~/.vibeos/.env:

# Обязательно
GOOGLE_CHAT_PROJECT_ID=my-chat-bot-123
GOOGLE_CHAT_SUBSCRIPTION_NAME=projects/my-chat-bot-123/subscriptions/vibeos-chat-events-sub
GOOGLE_CHAT_SERVICE_ACCOUNT_JSON=/home/you/.vibeos/google-chat-sa.json

# Авторизация — вставьте email'ы людей, которым разрешено общаться с ботом
GOOGLE_CHAT_ALLOWED_USERS=you@yourdomain.com,coworker@yourdomain.com

# Опционально
GOOGLE_CHAT_HOME_CHANNEL=spaces/AAAA... # канал доставки по умолчанию для cron-задач
GOOGLE_CHAT_MAX_MESSAGES=1 # Pub/Sub FlowControl; 1 сериализует команды на сессию
GOOGLE_CHAT_MAX_BYTES=16777216 # 16 MiB — лимит на байты сообщений в обработке

ID проекта также подставляется из GOOGLE_CLOUD_PROJECT, а путь к SA — из GOOGLE_APPLICATION_CREDENTIALS — используйте любое удобное соглашение.

Установите зависимости, необходимые адаптеру Google Chat (дополнительный пакет VibeOS пока не опубликован — установите их напрямую):

pip install google-cloud-pubsub google-api-python-client google-auth google-auth-oauthlib

Запустите шлюз:

vibeos gateway

Вы должны увидеть строку лога вроде:

[GoogleChat] Connected; project=my-chat-bot-123, subscription=<redacted>,
bot_user_id=users/XXXX, flow_control(msgs=1, bytes=16777216)

Отправьте «hola» в тестовом диалоге. Бот отправляет маркер «VibeOS is thinking…», затем редактирует это же сообщение, заменяя его реальным ответом — без «сообщение удалено» tombstones.


Форматирование и возможности​

Google Chat отображает ограниченное подмножество Markdown:

ПоддерживаетсяНе поддерживается
*жирный*, _курсив_, ~зачёркнутый~, `код`Заголовки, списки
Встроенные изображения по URLИнтерактивные кнопки Card v2 (v1 этого шлюза)
Встроенные файловые вложения (после /setup-files — см. Шаг 10)Встроенные голосовые / круговые видео-заметки

Системный промпт агента включает подсказку для Google Chat, чтобы он знал эти ограничения и избегал форматирования, которое не отобразится.

Лимит размера сообщения: 4000 символов на сообщение. Более длинные ответы агента автоматически разбиваются на несколько сообщений.

Поддержка тредов: когда пользователь отвечает внутри треда, VibeOS определяет thread.name и публикует свой ответ в том же треде, так что каждый тред получает отдельную сессию VibeOS.


Шаг 10: Доставка встроенных вложений (опционально)​

Из коробки бот может публиковать текст, встроенные изображения по URL и карточки для скачивания аудио/видео/документов. Чтобы доставлять встроенные вложения Chat — те же виджеты файлов, которые появляются, когда человек перетаскивает файл — каждый пользователь должен один раз авторизовать бота через отдельный OAuth-поток.

Почему отдельный поток​

Конечная точка media.upload API Google Chat категорически отвергает аутентификацию сервисного аккаунта:

Этот метод не поддерживает аутентификацию приложения с помощью сервисного аккаунта. Аутентифицируйтесь с помощью учётной записи пользователя.

Не существует роли IAM или области видимости, которая это исправляет. Конечная точка принимает только учётные данные пользователя. Поэтому бот должен действовать как пользователь всякий раз, когда загружает файл — а именно, как пользователь, который запросил файл.

Одноразовая настройка (на профиль)​

  1. Перейдите в APIs & Services → Credentials в том же проекте GCP.
  2. Create credentials → OAuth client ID → Desktop app.
  3. Скачайте JSON. Перенесите его на хост, где работает VibeOS.
  4. Зарегистрируйте клиент в VibeOS (запустите под профилем, для которого он нужен):
# Профиль по умолчанию:
python -m plugins.platforms.google_chat.oauth \
--client-secret /path/to/client_secret.json

# Именованный профиль получает свою отдельную регистрацию:
vibeos -p <profile> python -m plugins.platforms.google_chat.oauth \
--client-secret /path/to/client_secret.json

Это записывает секрет клиента в домашнюю директорию активного профиля VibeOS (например, ~/.vibeos/google_chat_user_client_secret.json для профиля по умолчанию). Секрет клиента привязан к профилю, а не общий для всех профилей — каждый профиль регистрирует свой собственный. Это сделано намеренно: профили — это изолированные границы аутентификации, поэтому два профиля могут указывать на разные OAuth-приложения / аккаунты Google. Зарегистрируйте его один раз для каждого профиля, которому нужна доставка вложений Google Chat.

Авторизация для каждого пользователя (в чате)​

Каждый пользователь выполняет поток один раз, в своём личном диалоге с ботом:

  1. Он отправляет /setup-files боту. Бот отвечает статусом и следующим шагом.
  2. Он отправляет /setup-files start. Бот отвечает OAuth-ссылкой.
  3. Он открывает ссылку, нажимает Allow и видит, что браузер не может загрузить http://localhost:1/?...&code=.... Этот сбой ожидаем — код авторизации находится в адресной строке.
  4. Он копирует URL сбоя (или просто значение code=...) и вставляет его обратно в чат как /setup-files &lt;PASTED_URL&gt;. Бот обменивает его на токен обновления.

Токен сохраняется в ~/.vibeos/google_chat_user_tokens/&lt;sanitized_email&gt;.json. Последующие запросы файлов в диалоге этого пользователя используют его токен, поэтому бот загружает файл от его имени, и сообщение попадает в его пространство.

Чтобы отозвать позже: /setup-files revoke удаляет только токен этого пользователя. Токены других пользователей не затрагиваются.

Область видимости​

Поток запрашивает ровно одну область: chat.messages.create. Она покрывает как media.upload, так и последующий messages.create, который ссылается на загруженный attachmentDataRef. Никакого Drive, никаких более широких областей Chat — это намеренно минимальные привилегии.

Поведение с несколькими пользователями​

Если у запрашивающего ещё нет персонального токена, бот возвращается к устаревшему единому токену пользователя в ~/.vibeos/google_chat_user_token.json (если он есть от установки до поддержки нескольких пользователей). Если нет ни того, ни другого, бот публикует понятное текстовое уведомление, предлагая запрашивающему выполнить /setup-files.

Отзыв пользователем очищает только его собственный слот. 401/403 от токена одного пользователя удаляет из кэша только этого пользователя. Пользователи не мешают друг другу.


Устранение неполадок​

Бот молчит после отправки «hola».

  1. Проверьте в консоли, есть ли недоставленные сообщения в подписке Pub/Sub. Если есть, VibeOS не аутентифицирован — проверьте GOOGLE_CHAT_SERVICE_ACCOUNT_JSON и что SA указан как Pub/Sub Subscriber на подписке.
  2. Если в подписке ноль сообщений, Google Chat не публикует. Перепроверьте привязку IAM на теме: chat-api-push@system.gserviceaccount.com должна иметь Pub/Sub Publisher.
  3. Проверьте логи vibeos gateway на наличие [GoogleChat] Connected. Если вы видите [GoogleChat] Config validation failed, сообщение об ошибке подскажет, какую переменную окружения исправить.

Бот отвечает, но вместо ответа агента появляется сообщение об ошибке.

Проверьте логи на наличие [GoogleChat] Pub/Sub stream died — если они повторяются, возможно, ваши учётные данные SA были изменены или подписка удалена. После 10 попыток адаптер помечает себя как фатальный.

«403 Forbidden» на каждом исходящем сообщении.

Бот был удалён из пространства, или вы отозвали его в консоли Chat API. Переустановите его в пространстве (следующее событие ADDED_TO_SPACE автоматически восстановит возможность отправки сообщений).

Слишком много предупреждений «Rate limit hit».

Квоты Chat API по умолчанию разрешают 60 сообщений на пространство в минуту. Если ваш агент генерирует длинные потоковые ответы, превышающие это значение, адаптер повторяет попытки с экспоненциальной задержкой — но вы всё равно увидите заметную для пользователя задержку. Рассмотрите возможность кратких ответов или увеличьте квоту в консоли GCP.

Бот продолжает публиковать уведомление «/setup-files» вместо файлов.

У запрашивающего нет персонального OAuth-токена и нет устаревшего запасного варианта. Выполните /setup-files в его диалоге и следуйте Шагу 10. После завершения обмена следующий запрос файла загрузится встроенно без перезапуска шлюза.

/setup-files start говорит «No client credentials stored.»

Одноразовая настройка не была выполнена для этого профиля (секрет клиента привязан к профилю, поэтому регистрация в одном профиле не будет видна другому). Из терминала запустите её под профилем, который использует шлюз:

# Профиль по умолчанию:
python -m plugins.platforms.google_chat.oauth \
--client-secret /path/to/client_secret.json

# Именованный профиль:
vibeos -p <profile> python -m plugins.platforms.google_chat.oauth \
--client-secret /path/to/client_secret.json

Затем отправьте /setup-files start снова.

/setup-files &lt;PASTED_URL&gt; говорит «Token exchange failed.»

Код авторизации одноразовый и короткоживущий (обычно несколько минут). Отправьте /setup-files start, чтобы получить новую ссылку, и повторите попытку.


Замечания по безопасности​

  • Область сервисного аккаунта: адаптер запрашивает области chat.bot и pubsub. IAM должен быть реальным средством контроля — предоставьте вашему SA минимум (roles/pubsub.subscriber + roles/pubsub.viewer на подписке), а не роли Pub/Sub на уровне проекта или организации.
  • Защита загрузки вложений: VibeOS будет прикреплять токен носителя SA только к URL, чей хост соответствует короткому разрешённому списку доменов, принадлежащих Google (googleapis.com, drive.google.com, lh[3-6].googleusercontent.com и несколько других). Любой другой хост отклоняется до HTTP-запроса, чтобы защититься от сценариев SSRF, где поддельное событие может перенаправить токен носителя на сервис метаданных GCE.
  • Редактирование: email'ы сервисных аккаунтов, пути подписок и пути тем удаляются из вывода логов с помощью agent/redact.py. Дамп отладочного конверта (GOOGLE_CHAT_DEBUG_RAW=1) проходит через тот же фильтр редактирования и логируется на уровне DEBUG.
  • Соответствие требованиям: если вы планируете подключить этого бота к регулируемому рабочему пространству (с политикой местонахождения данных или управления ИИ), получите соответствующее одобрение до первой установки.
  • Область OAuth пользователя: поток вложений для каждого пользователя запрашивает только chat.messages.create — минимум, который покрывает media.upload плюс последующий messages.create. Токены сохраняются как обычный JSON в ~/.vibeos/google_chat_user_tokens/&lt;sanitized_email&gt;.json (права доступа к файловой системе служат защитой — та же модель, что и для файла ключа SA). Каждый токен принадлежит ровно одному пользователю; отзыв ограничен этим пользователем.