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.
- Go to Google Cloud Console → Project Selector
- Create or select a project
- 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
- Google Slides API
- People API (
optional — forcontacts)
(optional) - Go to Credentials
- Create Credentials → OAuth 2.0 Client ID
- Application type: Desktop app
- Click Create
- 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
- Download the JSON file
YouThecanclientreusesecret is just your app's identity — it doesn't grant access to any account by itself. Access comes from thesameper-profileOAuthauthclientflowforwheremultipleyouprofiles/accounts,signbutineachwith a specific Googleaccount 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 shorthandHermes
venv Python (), not systemGSETUP="python~/.hermes/profiles/helper/skills/productivity/google-workspace/scripts/setup.py"hermes-agent/venv/bin/pythonpython3
Adjust— theskillGooglepathlibrariesifrequire Python 3.10+ and theskillsystem Python isinstalled in a different profile. The setup script respects$HERMES_HOMEor--hermes-hometo 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 OAuth auth_urlfield.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
--servicesand--format jsonflags 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 ( |
| OAuth token | ~/.hermes/profiles/<profile>/google_token.json |
Authenticated session (unique per profile) |
How It Works
| Piece | Role |
|---|---|
Shared across all profiles. |
|
| Auth flow (browser sign-in) | |
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 |
REFRESH_FAILED |
Token revoked or expired — redo Steps |
HttpError 403: access_denied |
Add |
HttpError 403: Insufficient Permission |
Missing API scope — revoke and redo |
| |
ModuleNotFoundError / No matching distribution |
|
zsh: |
GSETUP 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