Google Workspace
Gmail, Calendar, Drive, Docs, Sheets через gws CLI или Python.
Метаданные навыка
| Источник | Встроенный (установлен по умолчанию) |
| Путь | skills/productivity/google-workspace |
| Версия | 1.1.0 |
| Автор | Nous Research |
| Лицензия | MIT |
| Платформы | linux, macos, windows |
| Теги | Google, Gmail, Calendar, Drive, Sheets, Docs, Contacts, Email, OAuth |
| Связанные навыки | himalaya |
Справочник: полный SKILL.md
Ниже приведено полное определение навыка, которое Hermes загружает при срабатывании этого навыка. Именно его агент видит как инструкции, пока навык активен.
Google Workspace
Gmail, Calendar, Drive, Contacts, Sheets и Docs — через управляемый Hermes OAuth и тонкую обёртку CLI. Если установлен gws, навык использует его для более широкого охвата Google Workspace; иначе переходит к встроенному Python-клиенту.
References
references/gmail-search-syntax.md— операторы поиска Gmail (is:unread, from:, newer_than: и т.д.)
Scripts
scripts/setup.py— настройка OAuth2 (запускается один раз для авторизации)scripts/google_api.py— CLI-обёртка для совместимости. Для операций предпочитаетgws, когда тот доступен, при этом сохраняет контракт JSON-вывода Hermes без изменений.
Первичная настройка
Настройка полностью неинтерактивная — вы ведёте её шаг за шагом, чтобы она работала в CLI, Telegram, Discord или на любой другой платформе.
Сначала задайте сокращение:
GSETUP="python ${HERMES_HOME:-$HOME/.hermes}/skills/productivity/google-workspace/scripts/setup.py"
Шаг 0: Проверьте, не настроено ли уже
$GSETUP --check
Если вывелось AUTHENTICATED, переходите к разделу «Использование» — настройка уже выполнена.
Шаг 1: Уточнение — спросите пользователя, что ему нужно
Перед началом настройки OAuth задайте пользователю ДВА вопроса:
Вопрос 1: «Какие сервисы Google вам нужны? Только почта или ещё и Calendar/Drive/Sheets/Docs?»
-
Только почта → Этот навык им вообще не нужен. Используйте навык
himalaya— он работает с паролем приложения Gmail (Настройки → Безопасность → Пароли приложений) и настраивается за 2 минуты. Проект Google Cloud не требуется. Загрузите навык himalaya и следуйте его инструкциям по настройке. -
Почта + Calendar → Продолжайте с этим навыком, но при авторизации укажите
--services email,calendar, чтобы экран согласия запрашивал только нужные им разрешения. -
Только Calendar/Drive/Sheets/Docs → Продолжайте с этим навыком и задайте более узкий набор
--services, напримерcalendar,drive,sheets,docs. -
Полный доступ к Workspace → Продолжайте с этим навыком и используйте набор сервисов
allпо умолчанию.
Вопрос 2: «Использует ли ваш аккаунт Google усиленную защиту (Advanced Protection, для входа обязательны аппаратные ключи безопасности)? Если не уверены — скорее всего, нет: её подключают только осознанно и вручную.»
- Нет / Не уверен → Обычная настройка. Продолжайте ниже.
- Да → Администратор их Workspace должен добавить идентификатор клиента OAuth в список разрешённых приложений организации, иначе Шаг 4 не сработает. Предупредите их заранее.
Шаг 2: Создайте учётные данные OAuth (разово, ~5 минут)
Скажите пользователю:
Вам нужен OAuth-клиент Google Cloud. Это разовая настройка:
- Создайте или выберите проект: https://console.cloud.google.com/projectselector2/home/dashboard
- Включите нужные API в библиотеке API: https://console.cloud.google.com/apis/library Включите: Gmail API, Google Calendar API, Google Drive API, Google Sheets API, Google Docs API, People API
- Создайте OAuth-клиент здесь: https://console.cloud.google.com/apis/credentials Credentials → Create Credentials → OAuth 2.0 Client ID
- Тип приложения: «Desktop app» → Create
- Если приложение ещё в режиме Testing, добавьте аккаунт Google пользователя как тестового пользователя здесь: https://console.cloud.google.com/auth/audience Audience → Test users → Add users
- Скачайте файл JSON и сообщите мне путь к нему
Важное замечание по Hermes CLI: если путь к файлу начинается с
/, НЕ отправляйте голый путь отдельным сообщением в CLI — его могут принять за слэш-команду. Пошлите его в составе предложения, например:The JSON file path is: /home/user/Downloads/client_secret_....json
Как только они укажут путь:
$GSETUP --client-secret /path/to/client_secret.json
Если вместо пути к файлу они вставляют сырые значения client ID / client secret,
сами сформируйте корректный JSON-файл Desktop OAuth, сохраните его в явное
место (например, ~/Downloads/hermes-google-client-secret.json), а затем запустите
--client-secret для этого файла.
Шаг 3: Получите URL авторизации
Используйте набор сервисов, выбранный на Шаге 1. Примеры:
$GSETUP --auth-url --services email,calendar --format json
$GSETUP --auth-url --services calendar,drive,sheets,docs --format json
$GSETUP --auth-url --services all --format json
Команда возвращает JSON с полем auth_url и заодно сохраняет точный URL в
~/.hermes/google_oauth_last_url.txt.
Правила для агента на этом шаге:
- Извлеките поле
auth_urlи отправьте этот точный URL пользователю одной строкой. - Предупредите пользователя, что после подтверждения браузер, скорее всего, выдаст ошибку на
http://localhost:1— это ожидаемо. - Скажите им скопировать ЦЕЛИКОМ перенаправленный URL из адресной строки браузера.
- Если у пользователя возникает
Error 403: access_denied, отправьте его прямо наhttps://console.cloud.google.com/auth/audience, чтобы он добавил себя как тестового пользователя.
Шаг 4: Обменяйте код
Пользователь вставит обратно либо URL вида http://localhost:1/?code=4/0A...&scope=...,
либо просто строку с кодом. Подойдёт и то, и другое. Шаг --auth-url сохраняет временную
ожидающую OAuth-сессию локально, чтобы --auth-code мог завершить обмен PKCE
позже, даже на серверах без графического интерфейса:
$GSETUP --auth-code "THE_URL_OR_CODE_THE_USER_PASTED" --format json
Если --auth-code завершается ошибкой из-за истёкшего, уже использованного кода или кода из старой вкладки браузера, команда вернёт свежий fresh_auth_url. В этом случае
сразу отправьте новый URL пользователю и попросите повторить попытку, используя только
самое свежее перенаправление браузера.
Шаг 5: Проверьте
$GSETUP --check
Должно вывестись AUTHENTICATED. Настройка завершена — токен с этого момента обновляется автоматически.
Примечания
- Токен хранится в
~/.hermes/google_token.jsonи обновляется автоматически. - Состояние ожидающей OAuth-сессии и верификатор временно хранятся в
~/.hermes/google_oauth_pending.jsonдо завершения обмена. - Если установлен
gws,google_api.pyнаправляет его на тот же файл учётных данных~/.hermes/google_token.json. Отдельный потокgws auth loginзапускать не нужно. - Чтобы отозвать доступ:
$GSETUP --revoke
Использование
Все команды идут через API-скрипт. Задайте сокращение GAPI:
GAPI="python ${HERMES_HOME:-$HOME/.hermes}/skills/productivity/google-workspace/scripts/google_api.py"
Gmail
# Поиск (возвращает JSON-массив с id, from, subject, date, snippet)
$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 с текстом тела)
$GAPI gmail get MESSAGE_ID
# Отправить
$GAPI gmail send --to user@example.com --subject "Hello" --body "Message text"
$GAPI gmail send --to user@example.com --subject "Report" --body "<h1>Q4</h1><p>Details...</p>" --html
$GAPI gmail send --to user@example.com --subject "Hello" --from '"Research Agent" <user@example.com>' --body "Message text"
# Ответить (автоматически выстраивает цепочку и проставляет In-Reply-To)
$GAPI gmail reply MESSAGE_ID --body "Thanks, that works for me."
$GAPI gmail reply MESSAGE_ID --from '"Support Bot" <user@example.com>' --body "Thanks"
# Ярлыки
$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
# Создать событие (нужен ISO 8601 с часовым поясом)
$GAPI calendar create --summary "Team Standup" --start 2026-03-01T10:00:00-06:00 --end 2026-03-01T10:30:00-06:00
$GAPI calendar create --summary "Lunch" --start 2026-03-01T12:00:00Z --end 2026-03-01T13:00:00Z --location "Cafe"
$GAPI calendar create --summary "Review" --start 2026-03-01T14:00:00Z --end 2026-03-01T15:00:00Z --attendees "alice@co.com,bob@co.com"
# Удалить событие
$GAPI calendar delete EVENT_ID
Drive
# Поиск существующих файлов
$GAPI drive search "quarterly report" --max 10
$GAPI drive search "mimeType='application/pdf'" --raw-query --max 5
# Получить метаданные одного файла
$GAPI drive get FILE_ID
# Загрузить локальный файл (MIME-тип определяется автоматически)
$GAPI drive upload /path/to/report.pdf
$GAPI drive upload /path/to/image.png --name "Logo.png" --parent FOLDER_ID
# Скачать (бинарные файлы скачиваются как есть; нативные файлы Google
# экспортируются в разумный формат по умолчанию — Docs→pdf, Sheets→csv, Slides→pdf, Drawings→png)
$GAPI drive download FILE_ID
$GAPI drive download DOC_ID --output ~/doc.pdf
$GAPI drive download DOC_ID --export-mime text/plain --output ~/doc.txt
# Создать папку
$GAPI drive create-folder "Reports"
$GAPI drive create-folder "Q4" --parent FOLDER_ID
# Поделиться
$GAPI drive share FILE_ID --email alice@example.com --role reader
$GAPI drive share FILE_ID --email alice@example.com --role writer --notify
$GAPI drive share FILE_ID --type anyone --role reader # любой по ссылке
$GAPI drive share FILE_ID --type domain --domain example.com --role reader
# Удалить — по умолчанию в корзину (обратимо). Используйте --permanent, чтобы минуть корзину.
$GAPI drive delete FILE_ID
$GAPI drive delete FILE_ID --permanent
Contacts
$GAPI contacts list --max 20
Sheets
# Создать новую таблицу
$GAPI sheets create --title "Q4 Budget"
$GAPI sheets create --title "Inventory" --sheet-name "Stock"
# Прочитать
$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
# Создать новый документ (по желанию с начальным текстом тела)
$GAPI docs create --title "Meeting Notes"
$GAPI docs create --title "Draft" --body "First paragraph..."
# Добавить текст в конец существующего документа
$GAPI docs append DOC_ID --text "Additional content to append"
Формат вывода
Все команды возвращают JSON. Разбирайте его через jq или читайте напрямую. Ключевые поля:
- Gmail search:
[{id, threadId, from, to, subject, date, snippet, labels}] - Gmail get:
{id, threadId, from, to, subject, date, labels, body} - Gmail send/reply:
{status: "sent", id, threadId} - Calendar list:
[{id, summary, start, end, location, description, htmlLink}] - Calendar create:
{status: "created", id, summary, htmlLink} - Drive search:
[{id, name, mimeType, modifiedTime, webViewLink}] - Drive get:
{id, name, mimeType, modifiedTime, size, webViewLink, parents, owners} - Drive upload:
{status: "uploaded", id, name, mimeType, webViewLink} - Drive download:
{status: "downloaded", id, name, path, mimeType} - Drive create-folder:
{status: "created", id, name, webViewLink} - Drive share:
{status: "shared", permissionId, fileId, role, type} - Drive delete:
{status: "trashed" | "deleted", fileId, permanent} - Contacts list:
[{name, emails: [...], phones: [...]}] - Sheets get:
[[cell, cell, ...], ...] - Sheets create:
{status: "created", spreadsheetId, title, spreadsheetUrl} - Docs create:
{status: "created", documentId, title, url} - Docs append:
{status: "appended", documentId, inserted_at, characters}
Правила
- Никогда не отправляйте письма, не создавайте и не удаляйте события Calendar, не удаляйте файлы Drive, не делитесь файлами и не меняйте Docs/Sheets без предварительного подтверждения от пользователя. Покажите, что будет сделано (получатели, ID файлов, содержимое, роль доступа), и спросите согласия. Для
drive deleteпредпочитайте корзину по умолчанию (обратимо), а не--permanent. - Проверяйте авторизацию перед первым использованием — запустите
setup.py --check. Если она не проходит, проведите пользователя через настройку. - Для сложных запросов используйте справочник по синтаксису поиска Gmail — загрузите его командой
skill_view("google-workspace", file_path="references/gmail-search-syntax.md"). - Время в календаре должно включать часовой пояс — всегда используйте ISO 8601 со смещением (например,
2026-03-01T10:00:00-06:00) или UTC (Z). - Соблюдайте лимиты запросов — избегайте быстрых подряд идущих вызовов API. По возможности группируйте чтения в пакеты.
Устранение неполадок
| Проблема | Решение |
|---|---|
NOT_AUTHENTICATED | Выполните Шаги настройки 2–5 выше |
REFRESH_FAILED | Токен отозван или истёк — повторите Шаги 3–5 |
HttpError 403: Insufficient Permission | Не хватает разрешения API — $GSETUP --revoke, затем повторите Шаги 3–5 |
AUTHENTICATED (partial) или «Token missing scopes» | Новые возможности записи (Drive write/delete, Docs create/edit) требуют повторной авторизации. $GSETUP --revoke, затем повторите Шаги 3–5, чтобы выдать расширенные разрешения. |
HttpError 403: Access Not Configured | API не включён — пользователю нужно включить его в Google Cloud Console |
ModuleNotFoundError | Запустите $GSETUP --install-deps |
| Усиленная защита блокирует авторизацию | Администратор Workspace должен добавить идентификатор клиента OAuth в список разрешений |
Отзыв доступа
$GSETUP --revoke