Skip to main content

Google Woekspace app setup

Setting Up Gmail Per Hermes Profile

Each Hermes profile authenticates to its own Google account via OAuth. This guide covers the one-time Google Cloud setup, then the per-profile authorization.


Prerequisites

  • A Hermes profile for each Gmail account you want to connect
  • Access to the Google Cloud Console for each Gmail account

Step 1: Create Google OAuth Credentials (one-time per Google account)time)

Do this once in the Google Cloud ConsoleConsole. forThe same OAuth client can be used across all profiles — each Gmailprofile just signs in with a different Google account youduring wantthe toauth connect:flow.

  1. Go to Google Cloud Console → Project Selector
  2. Create or select a project
  3. Enable the APIs you need from the API Library:
    • Gmail API
    • Google Calendar API (optional — only if you want calendar)
    • Google Drive API (optional)
    • Google Sheets API (optional)
    • Google Docs API
    • (optional)
    • Google Slides API
    • People API (optional — for contacts)
  4. Go to Credentials
    • Create Credentials → OAuth 2.0 Client ID
    • Application type: Desktop app
    • Click Create
  5. If the app is in Testing mode, add youreach Google account you want to connect as a test user:
    • Go to Audience
    • Test users → Add users → add youreach Gmail address
  6. Download the JSON file

YouThe canclient reusesecret is just your app's identity — it doesn't grant access to any account by itself. Access comes from the sameper-profile OAuthauth clientflow forwhere multipleyou profiles/accounts,sign butin eachwith a specific Google account needs to be added as a test user if the app is still in Testing mode.account.

Step 2: Place the client secret file

Put the downloaded JSON file somewherein accessible.a Youshared can use the same file for all profiles:location:

# Example: save to home directory
cp ~/Downloads/client_secret_*.json ~/google_client_secret..hermes/shared/google-app-secret.json

Step 3: Authorize each profile

Run thisthese commands for each profile you want to connect to Gmail.connect. Replace <profile> with the profile name (e.g. james, gabriel, helios-ai).

3a.

Important: SetUse the shorthand

Hermes
venv Python (GSETUP="python ~/.hermes/profiles/helper/skills/productivity/google-workspace/scripts/setup.py"hermes-agent/venv/bin/python), not system python3

Adjust the skillGoogle pathlibraries ifrequire Python 3.10+ and the skillsystem Python is installed in a different profile. The setup script respects $HERMES_HOME or --hermes-home to target the right profile.3.9.

3b.3a. Install the client secret into the profile

hermes --profile HERMES_HOME=~/.hermes/profiles/<profile> config set google.client_secret~/.hermes/hermes-agent/venv/bin/python ~/google_client_secret..hermes/profiles/<profile>/skills/productivity/google-workspace/scripts/setup.py --client-secret ~/.hermes/shared/google-app-secret.json

Or

3b. runGet the setupauthorization script directly:

URL

HERMES_HOME=~/.hermes/profiles/<profile> $GSETUP --client-secret ~/google_client_secret.json.hermes/hermes-agent/venv/bin/python 

3c. Get the authorization URL

Choose the services you need:

# Email only
HERMES_HOME=~/.hermes/profiles/<profile> $GSETUP/skills/productivity/google-workspace/scripts/setup.py --auth-url --services email --format json

# Email + Calendar
HERMES_HOME=~/.hermes/profiles/<profile> $GSETUP --auth-url --services email,calendar --format json

# Full Workspace (email, calendar, drive, sheets, docs, contacts)
HERMES_HOME=~/.hermes/profiles/<profile> $GSETUP --auth-url --services all --format json

This returns a JSON object withprints an auth_urlOAuth field.URL. Open that URLit in your browser and sign in with the Gmail account you want this profile to use.

Note: After approving, the browser will likely show an error on http://localhost:1 — this is expected. Copy the ENTIRE URL from the browser address bar.

Note: The --services and --format json flags are NOT supported in the current version. The setup script uses a fixed set of scopes covering all Google Workspace APIs.

3d.3c. Exchange the authorization code

Paste the redirect URL (or just the code) back:

HERMES_HOME=~/.hermes/profiles/<profile> $GSETUP~/.hermes/hermes-agent/venv/bin/python ~/.hermes/profiles/<profile>/skills/productivity/google-workspace/scripts/setup.py --auth-code "PASTE_THE_URL_OR_CODE_HERE" --format jsonPASTE_REDIRECT_URL_HERE"

3e.3d. Verify it worked

HERMES_HOME=~/.hermes/profiles/<profile> $GSETUP~/.hermes/hermes-agent/venv/bin/python ~/.hermes/profiles/<profile>/skills/productivity/google-workspace/scripts/setup.py --check

Should print AUTHENTICATED.

Step 4: Test it

GAPI="python ~/.hermes/profiles/helper/skills/productivity/google-workspace/scripts/google_api.py"hermes-agent/venv/bin/python

# Search unread emails
HERMES_HOME=~/.hermes/profiles/<profile> $GAPI ~/.hermes/profiles/<profile>/skills/productivity/google-workspace/scripts/google_api.py gmail search "is:unread" --max 5

# List calendar events
HERMES_HOME=~/.hermes/profiles/<profile> $GAPI ~/.hermes/profiles/<profile>/skills/productivity/google-workspace/scripts/google_api.py calendar list

Step 5: Repeat for each profile

Run Steps 3a–3e3d again for each profile, signing in with a different Gmail account each time. Each profile stores its own token at:

~/.hermes/profiles/<profile>/google_token.json

File Locations Per Profile

File Path Purpose
Client secret ~/.hermes/profiles/<profile>/google_client_secret.json OAuth client credentials (cancopied befrom shared)shared file)
OAuth token ~/.hermes/profiles/<profile>/google_token.json Authenticated session (unique per profile)

How It Works

PieceRole
PendingClient OAuthsecret ~/Your app's identity — "I am Hermes app".hermes/profiles/<profile>/google_oauth_pending.json Shared across all profiles.
Auth flow (browser sign-in) TemporaryPick duringwhich authGoogle flowaccount to connect. Done once per profile.
Token (google_token.json)Proof that a specific Gmail account authorized the app. One per profile.

One client secret, many tokens — each token tied to whichever Google account signed in during that profile's auth flow.

Troubleshooting

Problem Fix
NOT_AUTHENTICATED Run Steps 3c–3e3b–3d again
REFRESH_FAILED Token revoked or expired — redo Steps 3c–3e3b–3d
HttpError 403: access_denied Add yourthe Gmail address as a test user in Google Cloud Console → Audience
HttpError 403: Insufficient Permission Missing API scope — revoke and redo with broader --services
AUTHENTICATED (partial)New scopes needed — revoke and re-authorize
ModuleNotFoundError / No matching distribution RunUse the Hermes venv Python: $GSETUP --install-deps~/.hermes/hermes-agent/venv/bin/python
Advancedzsh: Protectionno blockssuch authfile or directory: python WorkspaceDon't admin must allowlistuse the OAuthGSETUP clientvariable IDpattern in zsh. Call the venv Python directly with HERMES_HOME=... prefix

Revoking Access

To disconnect a profile's Gmail:Gmail and re-authorize with a different account:

# Revoke
HERMES_HOME=~/.hermes/profiles/<profile> $GSETUP~/.hermes/hermes-agent/venv/bin/python ~/.hermes/profiles/<profile>/skills/productivity/google-workspace/scripts/setup.py --revoke

# Re-authorize (Steps 3b–3d)
HERMES_HOME=~/.hermes/profiles/<profile> ~/.hermes/hermes-agent/venv/bin/python ~/.hermes/profiles/<profile>/skills/productivity/google-workspace/scripts/setup.py --auth-url

Quick Reference: All Commands For One Profile

# Setup shorthands
PROFILE=james
GSETUP="python ~/.hermes/profiles/helper/skills/productivity/google-workspace/scripts/setup.py"
HH="HERMES_HOME=~/.hermes/profiles/$PROFILE"
PY=~/.hermes/hermes-agent/venv/bin/python
SCRIPT=~/.hermes/profiles/$PROFILE/skills/productivity/google-workspace/scripts/setup.py

# 1. Install client secret
$HH $GSETUPPY $SCRIPT --client-secret ~/google_client_secret..hermes/shared/google-app-secret.json

# 2. Get auth URL (sign in with the Gmail account for this profile)
$HH $GSETUPPY $SCRIPT --auth-url --services email,calendar --format json

# 3. Exchange code (paste the redirect URL)
$HH $GSETUPPY $SCRIPT --auth-code "http://localhost:1/?code=4/0A..."

--format json

# 4. Verify
$HH $GSETUPPY $SCRIPT --check

# 5. Test Gmail
GAPI="python ~/.hermes/profiles/helper/$PROFILE/skills/productivity/google-workspace/scripts/google_api.py"py
$HH $PY $GAPI gmail search "is:unread" --max 5