Навык Google Workspace
Интеграция Gmail, Calendar, Drive, Contacts, Sheets и Docs для Hermes. Использует OAuth2 с автоматическим обновлением токенов. Если в системе установлен Google Workspace CLI (gws), навык работает через него — он перекрывает больший спектр возможностей. При его отсутствии — через клиентские библиотеки Python.
Путь к навыку: skills/productivity/google-workspace/
Настройка
Процесс настройки полностью ведёт агент — попросите Hermes Agent настроить Google Workspace, и он проведёт вас по каждому шагу. Порядок действий:
- Создайте проект Google Cloud и включите нужные API (Gmail, Calendar, Drive, Sheets, Docs, People)
- Создайте учётные данные OAuth 2.0 (тип — Desktop app) и скачайте JSON с секретом клиента
- Авторизация — Hermes Agent генерирует URL, вы подтверждаете в браузере, вставляете обратно redirect URL
- Готово — токен обновляется автоматически
Если нужна лишь почта (без Calendar, Drive и Sheets), возьмите навык himalaya — он работает с паролем приложения Gmail и настраивается за 2 минуты. Проект Google Cloud не требуется.
Gmail
Поиск писем
$GAPI gmail search "is:unread" --max 10
$GAPI gmail search "from:boss@company.com newer_than:1d"
$GAPI gmail search "has:attachment filename:pdf newer_than:7d"
Возвращает JSON с полями id, from, subject, date, snippet и labels для каждого письма.
Чтение
$GAPI gmail get MESSAGE_ID
Возвращает полный текст письма (приоритет — plain text, при отсутствии — HTML).
Отправка
# Простая отправка
$GAPI gmail send --to user@example.com --subject "Hello" --body "Message text"
# HTML-письмо
$GAPI gmail send --to user@example.com --subject "Report" \
--body "<h1>Q4 Results</h1><p>Details here</p>" --html
# Произвольный заголовок From (отображаемое имя + адрес)
$GAPI gmail send --to user@example.com --subject "Hello" \
--from '"Research Agent" <user@example.com>' --body "Message text"
# С копией (CC)
$GAPI gmail send --to user@example.com --cc "team@example.com" \
--subject "Update" --body "FYI"
Произвольный заголовок From
Флаг --from позволяет задать отображаемое имя отправителя. Удобно, когда несколько агентов используют один Gmail-аккаунт, но получатели должны видеть разные имена:
# Агент 1
$GAPI gmail send --to client@co.com --subject "Research Summary" \
--from '"Research Agent" <shared@company.com>' --body "..."
# Агент 2
$GAPI gmail send --to client@co.com --subject "Code Review" \
--from '"Code Assistant" <shared@company.com>' --body "..."
Как это работает: значение --from записывается в заголовок RFC 5322 From MIME-сообщения. Gmail разрешает менять отображаемое имя для собственного аутентифицированного адреса без дополнительных настроек. Получатели видят заданное имя (например, «Research Agent»), а адрес остаётся прежним.
Важно: если в --from указан другой адрес (не тот, с которого выполнена аутентификация), Gmail потребует, чтобы этот адрес был добавлен как псевдоним через Send As в настройках Gmail → Аккаунты → Отправлять письма как.
Флаг --from работает как при отправке, так и при ответе:
$GAPI gmail reply MESSAGE_ID \
--from '"Support Bot" <shared@company.com>' --body "We're on it"
Ответ на письмо
$GAPI gmail reply MESSAGE_ID --body "Thanks, that works for me."
Ответ автоматически вставляется в тред — заголовки In-Reply-To и References проставляются сами, thread ID берётся из исходного письма.
Метки
# Показать все метки
$GAPI gmail labels
# Добавить / убрать метку
$GAPI gmail modify MESSAGE_ID --add-labels LABEL_ID
$GAPI gmail modify MESSAGE_ID --remove-labels UNREAD
Calendar
# Список событий (по умолчанию — следующие 7 дней)
$GAPI calendar list
$GAPI calendar list --start 2026-03-01T00:00:00Z --end 2026-03-07T23:59:59Z
# Создать событие (часовой пояс обязателен)
$GAPI calendar create --summary "Team Standup" \
--start 2026-03-01T10:00:00-07:00 --end 2026-03-01T10:30:00-07:00
# С местом проведения и участниками
$GAPI calendar create --summary "Lunch" \
--start 2026-03-01T12:00:00Z --end 2026-03-01T13:00:00Z \
--location "Cafe" --attendees "alice@co.com,bob@co.com"
# Удалить событие
$GAPI calendar delete EVENT_ID
Время событий обязательно должно содержать смещение часового пояса (например, -07:00) или суффикс UTC (Z). Дата и время без указания зоны, например 2026-03-01T10:00:00, неоднозначны и будут интерпретированы как UTC.
Drive
$GAPI drive search "quarterly report" --max 10
$GAPI drive search "mimeType='application/pdf'" --raw-query --max 5
Sheets
# Читаем диапазон
$GAPI sheets get SHEET_ID "Sheet1!A1:D10"
# Пишем в диапазон
$GAPI sheets update SHEET_ID "Sheet1!A1:B2" --values '[["Name","Score"],["Alice","95"]]'
# Добавляем строки
$GAPI sheets append SHEET_ID "Sheet1!A:C" --values '[["new","row","data"]]'
Docs
$GAPI docs get DOC_ID
Возвращает заголовок документа и полный текстовый контент.
Contacts
$GAPI contacts list --max 20
Формат вывода
Все команды возвращают JSON. Основные поля по каждому сервису:
| Команда | Поля |
|---|---|
gmail search | id, threadId, from, to, subject, date, snippet, labels |
gmail get | id, threadId, from, to, subject, date, labels, body |
gmail send/reply | status, id, threadId |
calendar list | id, summary, start, end, location, description, htmlLink |
calendar create | status, id, summary, htmlLink |
drive search | id, name, mimeType, modifiedTime, webViewLink |
contacts list | name, emails, phones |
sheets get | двумерный массив значений ячеек |
Устранение неполадок
| Проблема | Решение |
|---|---|
NOT_AUTHENTICATED | Запустите настройку (попросите Hermes Agent настроить Google Workspace) |
REFRESH_FAILED | Токен отозван — повторите шаги авторизации |
HttpError 403: Insufficient Permission | Не хватает scope — отзовите токен и авторизуйтесь заново с нужными сервисами |
HttpError 403: Access Not Configured | API не включён в Google Cloud Console |
ModuleNotFoundError | Запустите скрипт настройки с флагом --install-deps |