hermes - 💡(How to fix) Fix [Feature]: Service-account auth + Docs/Drive create endpoints in google-workspace skill (for autonomous deployments) [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#17272Fetched 2026-04-30 06:48:42
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
labeled ×3

Fix Action

Fix / Workaround

We've been working around both gaps in our deployment with a parallel SA-auth client (google_workspace_client.py) plus runtime monkey-patches to inject docs_create/docs_update/drive_create_folder into the upstream skill at boot. We just deleted the runtime patches (they're a maintenance trap — any upstream change can silently break them), but the parallel client stays until Hermes upstream covers this surface natively. We'd love to delete it.

  1. Keep wrapping in our own deployment. What we do today — and the cost is that anyone reading upstream's google_api.py doesn't see what's actually running, and any change to get_credentials() upstream can silently break our patches. We've now stopped patching at runtime and instead maintain a parallel client (google_workspace_client.py) — but that's still divergence we'd rather delete.
  2. Maintain a Sunrise-managed fork with these additions. We explicitly declined this — fork = perpetual sync burden, defeats the purpose of using upstream.
  3. Use the gws CLI binary that the skill optionally bridges to. gws does support service accounts and create operations, but bundling/installing it adds another moving piece, and the Python fallback path still exists in the skill — so the gaps need to be closed there regardless.
  4. Migrate the whole skill to gws (existing #411). Adjacent — would solve some of this if it landed — but doesn't address the core question of "should google_api.py itself support SA auth" (we think yes, even with a gws future).

Code Example

gmail_search / gmail_get / gmail_send / gmail_reply / gmail_labels / gmail_modify
calendar_list / calendar_create / calendar_delete
drive_search                        ← search only, no create
contacts_list
sheets_get / sheets_update / sheets_append
docs_get                            ← read only, no create / no update
(no slides_* at all — though tracked separately in #15600)

---

def get_credentials():
    sa_payload = os.getenv("GOOGLE_SERVICE_ACCOUNT_JSON", "").strip()
    if sa_payload:
        from google.oauth2 import service_account
        info = (
            json.loads(sa_payload)
            if sa_payload.lstrip().startswith("{")
            else json.load(open(sa_payload))
        )
        if info.get("type") != "service_account":
            sys.exit("GOOGLE_SERVICE_ACCOUNT_JSON must be a service-account JSON")
        return service_account.Credentials.from_service_account_info(info, scopes=SCOPES)

    # … existing OAuth flow unchanged

---

docs_create   --title "..." [--folder FOLDER_ID] [--content "..."]    → returns {fileId, url}
docs_update   FILE_ID --requests '<batchUpdate JSON>' | --append "..."
drive_create_folder   --name "..." [--parent FOLDER_ID]               → returns {folderId, url}
sheets_create --title "..." [--folder FOLDER_ID]                      → returns {fileId, url}
RAW_BUFFERClick to expand / collapse

Problem or Use Case

The bundled productivity/google-workspace skill is well-shaped for interactive use on a developer's laptop: an OAuth-Desktop-App flow runs once via setup.py, drops a google_token.json at $HERMES_HOME/google_token.json, and google_api.py reads/refreshes it on every call.

That model is hostile to autonomous Hermes deployments — agents running headless in Docker / Railway / Fly / etc., responding to Slack/Telegram/Discord events with no human at a terminal. Two specific gaps:

Gap 1 — Auth: OAuth-only

google_api.py:get_credentials() requires google_token.json from a one-time setup.py run. The OAuth flow (whether console copy-paste or PKCE redirect) is interactive by design. To get a token onto a Railway volume today, an operator has to either railway ssh in and paste an auth code, or generate the token on a laptop and scp/upload it onto the volume — and refresh-token rotation can break this state silently months later.

For an autonomous agent, service-account auth is the standard answer: drop a JSON key into env, let the agent boot, calls Just Work, no interactive flow ever needed.

Gap 2 — API surface: read-heavy, no create

google_api.py at v2026.4.23 exposes:

gmail_search / gmail_get / gmail_send / gmail_reply / gmail_labels / gmail_modify
calendar_list / calendar_create / calendar_delete
drive_search                        ← search only, no create
contacts_list
sheets_get / sheets_update / sheets_append
docs_get                            ← read only, no create / no update
(no slides_* at all — though tracked separately in #15600)

So an autonomous agent cannot create a Google Doc, Sheet, Slides deck, or Drive folder using the bundled skill. The skill is a great reader, but it can't produce client-facing deliverables.


We've been working around both gaps in our deployment with a parallel SA-auth client (google_workspace_client.py) plus runtime monkey-patches to inject docs_create/docs_update/drive_create_folder into the upstream skill at boot. We just deleted the runtime patches (they're a maintenance trap — any upstream change can silently break them), but the parallel client stays until Hermes upstream covers this surface natively. We'd love to delete it.

This shows up in the wild whenever someone runs Hermes for a "produce documents on demand" use case — sales decks, client briefs, weekly reports, meeting summaries — from a chat platform with no terminal access.

Proposed Solution

Two coordinated additions to skills/productivity/google-workspace/scripts/google_api.py:

1. Service-account auth as a first-class option

In get_credentials(), before the existing OAuth path, check for GOOGLE_SERVICE_ACCOUNT_JSON:

def get_credentials():
    sa_payload = os.getenv("GOOGLE_SERVICE_ACCOUNT_JSON", "").strip()
    if sa_payload:
        from google.oauth2 import service_account
        info = (
            json.loads(sa_payload)
            if sa_payload.lstrip().startswith("{")
            else json.load(open(sa_payload))
        )
        if info.get("type") != "service_account":
            sys.exit("GOOGLE_SERVICE_ACCOUNT_JSON must be a service-account JSON")
        return service_account.Credentials.from_service_account_info(info, scopes=SCOPES)

    # … existing OAuth flow unchanged

The env var accepts either inline JSON or a path to a JSON file (matches how most cloud-deployment tooling wants secrets shaped).

Behavior contract: SA auth is opt-in via env. Nothing changes for users today. Skill docs gain a one-paragraph "for autonomous deployments" section pointing at SA auth.

2. Create/update endpoints to match the read surface

Add the symmetric write side:

docs_create   --title "..." [--folder FOLDER_ID] [--content "..."]    → returns {fileId, url}
docs_update   FILE_ID --requests '<batchUpdate JSON>' | --append "..."
drive_create_folder   --name "..." [--parent FOLDER_ID]               → returns {folderId, url}
sheets_create --title "..." [--folder FOLDER_ID]                      → returns {fileId, url}

Slides is already tracked in #15600 — happy to roll that into the same PR or keep separate, your call.

For Shared Drives (where SA-authenticated agents typically write), all create endpoints need to pass supportsAllDrives=True. The Drive files().create() and documents().create() calls handle this with one parameter — supportsAllDrives for Drive, the doc/sheets APIs accept it through the body or headers depending on which.

Alternatives Considered

  1. Keep wrapping in our own deployment. What we do today — and the cost is that anyone reading upstream's google_api.py doesn't see what's actually running, and any change to get_credentials() upstream can silently break our patches. We've now stopped patching at runtime and instead maintain a parallel client (google_workspace_client.py) — but that's still divergence we'd rather delete.
  2. Maintain a Sunrise-managed fork with these additions. We explicitly declined this — fork = perpetual sync burden, defeats the purpose of using upstream.
  3. Use the gws CLI binary that the skill optionally bridges to. gws does support service accounts and create operations, but bundling/installing it adds another moving piece, and the Python fallback path still exists in the skill — so the gaps need to be closed there regardless.
  4. Migrate the whole skill to gws (existing #411). Adjacent — would solve some of this if it landed — but doesn't address the core question of "should google_api.py itself support SA auth" (we think yes, even with a gws future).

The proposed solution is additive, opt-in, doesn't break anything, and meaningfully expands the autonomous-deployment use case.

Feature Type

New bundled skill / improvement to existing bundled skill (productivity/google-workspace).

Scope

Medium. ~50 lines for SA auth, ~80–120 lines for the four create endpoints. All in the existing google_api.py, no new modules. Scope estimate excludes Slides (#15600 covers that separately).

Contribution

Happy to PR this — context is fresh. Two questions to settle before I open one, to avoid wasted review:

  1. Auth precedence: GOOGLE_SERVICE_ACCOUNT_JSON (env-only, like proposed above) vs. a config-file knob in ~/.hermes/config.yaml under a skills.google-workspace.service_account block? Env-only is simpler; config-block is more discoverable via hermes config. Either is fine, prefer to match Hermes conventions.
  2. Slides: roll #15600 into the same PR or keep separate? Same author can do both.

Let me know either by comment or with a label, and I'll send the PR.

extent analysis

TL;DR

To support autonomous Hermes deployments, add service-account authentication and create/update endpoints to the google_api.py script in the productivity/google-workspace skill.

Guidance

  • Implement service-account authentication by checking for the GOOGLE_SERVICE_ACCOUNT_JSON environment variable in the get_credentials() function, allowing for opt-in SA auth.
  • Add create/update endpoints to match the existing read surface, including docs_create, docs_update, drive_create_folder, and sheets_create.
  • Consider using a config-file knob in ~/.hermes/config.yaml for service account configuration, or stick with the proposed env-only approach, depending on Hermes conventions.
  • Decide whether to roll the Slides-related issue (#15600) into the same PR or keep it separate.

Example

def get_credentials():
    sa_payload = os.getenv("GOOGLE_SERVICE_ACCOUNT_JSON", "").strip()
    if sa_payload:
        # ... (rest of the service account auth implementation)
    # ... (existing OAuth flow unchanged)

Notes

The proposed solution aims to address the gaps in the current implementation, making it more suitable for autonomous deployments. However, the implementation details, such as the auth precedence and Slides integration, need to be settled before proceeding with the PR.

Recommendation

Apply the proposed workaround by adding service-account authentication and create/update endpoints to the google_api.py script, as it provides a more comprehensive solution for autonomous deployments.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix [Feature]: Service-account auth + Docs/Drive create endpoints in google-workspace skill (for autonomous deployments) [1 participants]