Google Workspace
目次
gws CLI か Python で Gmail・Calendar・Drive・Docs・Sheets を扱います。
skill の情報
| 提供元 | 最初から入っています |
| パス | skills/productivity/google-workspace |
| バージョン | 1.2.0 |
| 作者 | Nous Research |
| ライセンス | MIT |
| 対応プラットフォーム | linux, macos, windows |
| タグ | Google, Gmail, Calendar, Drive, Sheets, Docs, Contacts, Email, OAuth |
| 関連 skill | himalaya |
参考: SKILL.md 全文
Google Workspace
Gmail、Calendar、Drive、Contacts、Sheets、Docs を、Hermes が管理する OAuth と薄い CLI のラッパー越しに扱います。gws が入っていれば、この skill はそれを実行の土台として使い、Google Workspace のより広い範囲をカバーします。入っていない場合は、同梱の Python 実装に切り替わります。
参考資料
references/gmail-search-syntax.md(Gmail の検索演算子。is:unread、from:、newer_than: など)references/daily-brief.md(毎日・朝のブリーフの手順。予定と重複の確認、会議の準備、Gmail と Calendar から拾う急ぎのメール)。朝のブリーフや会議の準備、「予定と、対応が要るメールを教えて」といった依頼が来たら読み込んでください。
スクリプト
scripts/setup.py(OAuth2 の初期設定。一度だけ実行して認可します)scripts/google_api.py(互換ラッパーの CLI)。使える場面ではgwsを優先しつつ、Hermes 側のこれまでの JSON 出力の形をそのまま保ちます。
最初の設定
設定は最初から最後まで対話なしで進みます。エージェントが一段ずつ進める形なので、 CLI でも Telegram でも Discord でも、どの経路からでも動きます。
まず短縮名を決めておきます。
GSETUP="python ${HERMES_HOME:-$HOME/.hermes}/skills/productivity/google-workspace/scripts/setup.py"Step 0: 設定済みかどうかを確認する
$GSETUP --checkAUTHENTICATED と出たら設定はすでに済んでいるので、「使い方」まで飛ばしてください。
Step 1: 何が必要かを利用者に聞く
OAuth の設定を始める前に、利用者に 2 つ質問します。
質問 1: 「Google のどのサービスが必要ですか。メールだけですか、それとも Calendar / Drive / Sheets / Docs も使いますか」
- メールだけ → この skill は必要ありません。代わりに
himalayaskill を
使ってください。Gmail のアプリパスワード(設定 → セキュリティ → アプリ パスワード)で動き、設定は 2 分で終わります。Google Cloud のプロジェクトも 要りません。himalaya skill を読み込んで、その設定手順に従ってください。
- メールと Calendar → この skill を続けて使いますが、認可のときに
--services email,calendar を指定して、同意画面で本当に必要な権限だけを 求めるようにします。
- Calendar / Drive / Sheets / Docs だけ → この skill を続けて使い、
calendar,drive,sheets,docs のように --services を絞ります。
- Workspace 全体 → この skill を続けて使い、既定の
allの組み合わせを
そのまま指定します。
質問 2: 「その Google アカウントは高度な保護機能プログラム(ログインにハードウェアのセキュリティキーが要るもの)を使っていますか。よくわからない場合はおそらく使っていません。使うには自分で明示的に登録している必要があるからです」
- いいえ / わからない → 通常どおりの設定です。このまま進めてください。
- はい → Step 4 を通すには、Workspace の管理者が OAuth クライアント ID を
組織の許可アプリ一覧に追加しておく必要があります。先に伝えておいてください。
Step 2: OAuth の認証情報を作る(一度だけ、5 分ほど)
利用者にこう伝えます。
> Google Cloud の OAuth クライアントが必要です。これは一度だけの設定です。 > > 1. プロジェクトを作るか選びます: > https://console.cloud.google.com/projectselector2/home/dashboard > 2. 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 > 3. ここで OAuth クライアントを作ります: > https://console.cloud.google.com/apis/credentials > 「認証情報」→「認証情報を作成」→「OAuth 2.0 クライアント ID」 > 4. アプリケーションの種類は「デスクトップ アプリ」を選んで「作成」 > 5. アプリがまだテスト中なら、ここで自分の Google アカウントをテストユーザーとして追加します: > https://console.cloud.google.com/auth/audience > 「対象」→「テストユーザー」→「ユーザーを追加」 > 6. JSON ファイルをダウンロードして、そのファイルの場所を教えてください > > Hermes CLI での注意: ファイルの場所が / で始まる場合、そのパスだけを単独のメッセージとして CLI に送らないでください。スラッシュコマンドと取り違えられることがあります。次のように文の中に入れて送ってください。 > The JSON file path is: ~/Downloads/client_secret_....json
場所を教えてもらったら、こう実行します。
$GSETUP --client-secret /path/to/client_secret.jsonファイルの場所ではなくクライアント ID とクライアントシークレットの値をそのまま 貼られた場合は、こちらで正しい形のデスクトップ用 OAuth の JSON ファイルを書き、 はっきりした場所(たとえば ~/Downloads/hermes-google-client-secret.json)に 保存してから、そのファイルに対して --client-secret を実行してください。
Step 3: 認可用の URL を取得する
Step 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 jsonauth_url フィールドを含む JSON が返り、同じ URL が ~/.hermes/google_oauth_last_url.txt にも保存されます。
この段階でのエージェント側の決まりごと:
auth_urlフィールドを取り出し、その URL をそのまま 1 行で利用者に送ります。- 承認したあと、ブラウザーは
http://localhost:1でエラーになるはずだと伝えます。それが正常な動きです。 - ブラウザーのアドレス欄にある、リダイレクト後の URL を丸ごとコピーしてもらってください。
Error 403: access_deniedが出た場合は、https://console.cloud.google.com/auth/audienceへ直接案内して、自分をテストユーザーに追加してもらいます。
Step 4: コードを交換する
利用者が返してくるのは、http://localhost:1/?code=4/0A...&scope=... のような URL か、 コードの文字列だけのどちらかです。どちらでも動きます。--auth-url の段階で、 処理中の OAuth セッションが一時的に手元に保存されるので、あとから --auth-code で PKCE の交換を終えられます。画面のない環境でも同じです。
$GSETUP --auth-code "THE_URL_OR_CODE_THE_USER_PASTED" --format jsonコードの期限切れ、使用済み、古いブラウザーのタブから取ったものなどが原因で --auth-code が失敗した場合は、新しい fresh_auth_url が返るようになりました。 そのときは、新しい URL をすぐ利用者に送り、いちばん新しいリダイレクト先だけを 使ってやり直してもらってください。
Step 5: 確認する
$GSETUP --checkAUTHENTICATED と出るはずです。これで設定は完了で、以降はトークンが自動で更新されます。
補足
- トークンは
~/.hermes/google_token.jsonに保存され、自動で更新されます。 - 処理中の OAuth セッションの state と verifier は、交換が終わるまで一時的に
~/.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
# Search (returns JSON array with 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"
# Read full message (returns JSON with body text)
$GAPI gmail get MESSAGE_ID
# Send
$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"
# Reply (automatically threads and sets 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"
# Labels
$GAPI gmail labels
$GAPI gmail modify MESSAGE_ID --add-labels LABEL_ID
$GAPI gmail modify MESSAGE_ID --remove-labels UNREADCalendar
# List events (defaults to next 7 days)
$GAPI calendar list
$GAPI calendar list --start 2026-03-01T00:00:00Z --end 2026-03-07T23:59:59Z
# Create event (ISO 8601 with timezone required)
$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"
# Delete event
$GAPI calendar delete EVENT_IDDrive
# Search existing files
$GAPI drive search "quarterly report" --max 10
$GAPI drive search "mimeType='application/pdf'" --raw-query --max 5
# Get metadata for a single file
$GAPI drive get FILE_ID
# Upload a local file (auto-detects MIME type)
$GAPI drive upload /path/to/report.pdf
$GAPI drive upload /path/to/image.png --name "Logo.png" --parent FOLDER_ID
# Download (binary files download as-is; Google-native files export to a
# sensible default — 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
# Create a folder
$GAPI drive create-folder "Reports"
$GAPI drive create-folder "Q4" --parent FOLDER_ID
# Share
$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 # anyone with link
$GAPI drive share FILE_ID --type domain --domain example.com --role reader
# Delete — defaults to trash (reversible). Use --permanent to skip the trash.
$GAPI drive delete FILE_ID
$GAPI drive delete FILE_ID --permanentContacts
$GAPI contacts list --max 20Sheets
# Create a new spreadsheet
$GAPI sheets create --title "Q4 Budget"
$GAPI sheets create --title "Inventory" --sheet-name "Stock"
# Read
$GAPI sheets get SHEET_ID "Sheet1!A1:D10"
# Write
$GAPI sheets update SHEET_ID "Sheet1!A1:B2" --values '[["Name","Score"],["Alice","95"]]'
# Append rows
$GAPI sheets append SHEET_ID "Sheet1!A:C" --values '[["new","row","data"]]'Docs
# Read
$GAPI docs get DOC_ID
# Create a new Doc (optionally seeded with body text)
$GAPI docs create --title "Meeting Notes"
$GAPI docs create --title "Draft" --body "First paragraph..."
# Append text to the end of an existing Doc
$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}
ルール
- メールの送信、予定の作成と削除、Drive のファイルの削除、ファイルの共有、Docs や Sheets の変更は、必ず先に利用者に確認してから行ってください。 何をするのか(宛先、ファイル ID、内容、共有の権限)を示して、承認をもらいます。
drive deleteは、--permanentより、元に戻せる既定のゴミ箱行きを選んでください。 - 最初に使う前に認証を確認する。
setup.py --checkを実行し、通らなければ利用者を設定の手順に案内します。 - 込み入った検索には Gmail の検索構文の参考資料を使う。
skill_view("google-workspace", file_path="references/gmail-search-syntax.md")で読み込めます。 - Calendar の時刻にはタイムゾーンを必ず入れる。 ISO 8601 のオフセット付き(例:
2026-03-01T10:00:00-06:00)か UTC(Z)で書いてください。 - レート制限を守る。 API を立て続けに呼ぶのは避けます。読み取りはできるだけまとめてください。
困ったとき
| 症状 | 対処 |
|---|---|
NOT_AUTHENTICATED |
上の設定の Step 2〜5 を実行します |
REFRESH_FAILED |
トークンが取り消されたか期限切れです。Step 3〜5 をやり直します |
HttpError 403: Insufficient Permission |
API の権限が足りません。$GSETUP --revoke してから Step 3〜5 をやり直します |
AUTHENTICATED (partial) または "Token missing scopes" |
新しく増えた書き込み機能(Drive の書き込みと削除、Docs の作成と編集)には認可のやり直しが要ります。$GSETUP --revoke してから Step 3〜5 をやり直し、追加された権限を許可してください。 |
HttpError 403: Access Not Configured |
API が有効になっていません。利用者が Google Cloud Console で有効にする必要があります |
ModuleNotFoundError |
$GSETUP --install-deps を実行します |
| 高度な保護機能で認証が止まる | Workspace の管理者が OAuth クライアント ID を許可一覧に入れる必要があります |
権限を取り消す
$GSETUP --revoke