How to Give AI Agents Access to Google Workspace with TapAuth + gws CLI
🤖 AI Agent? You can follow this guide programmatically. The TapAuth CLI handles the full OAuth flow — grant creation, user approval, token caching, and refresh. Pair it with
gws(Google Workspace CLI) and you get full Google Workspace access via one environment variable. No OAuth implementation needed.
Google just open-sourced gws — a Rust-based CLI that covers every Google Workspace API. Drive, Gmail, Calendar, Sheets, Docs, Chat, Admin — all accessible from the command line with structured JSON output. It's built dynamically from Google's Discovery Service, so it stays current automatically.
For AI agents, this is a big deal. Instead of writing custom API calls for each Google service, an agent can use gws drive files list or gws gmail messages list and parse structured JSON. It even ships 40+ agent skills via skills.sh.
But there's a catch: gws needs an OAuth access token. And OAuth was built for humans in browsers — not agents in terminals.
The auth gap
The gws CLI supports multiple auth methods, but the simplest for agents is the GOOGLE_WORKSPACE_CLI_TOKEN environment variable. Set it to a valid Google OAuth access token and every gws command uses it automatically. No interactive login, no browser redirect, no credential file management.
The question is: where does the agent get that token?
Google OAuth requires a browser-based consent flow. The user visits a consent screen, clicks "Allow," and the app receives an authorization code via redirect. For a human developer, that's fine. For an AI agent running in a terminal, a container, or a headless environment — it's a non-starter.
This is exactly the problem TapAuth solves.
TapAuth + gws: the full flow
TapAuth is the token layer for AI agents. One API call creates a grant request with specific Google scopes. The user approves in their browser (once). The agent gets a scoped, time-limited access token. Token refresh is automatic.
Here's the complete flow for an agent that needs to read Google Calendar events:
Step 1: Request access
tapauth grant google/calendar.readonly
This creates a grant request. The user gets a URL to approve in their browser. They see exactly what scopes the agent is requesting and can approve or deny.
Step 2: Get the token
export GOOGLE_WORKSPACE_CLI_TOKEN=$(tapauth token google/calendar.readonly)
Once approved, the agent retrieves the access token. TapAuth handles caching — subsequent calls return the cached token instantly if it hasn't expired, and auto-refresh when it has.
Step 3: Use gws
gws calendar events list --params '{"calendarId": "primary", "maxResults": 10}'
gws drive files list --params '{"q": "mimeType='application/vnd.google-apps.spreadsheet'"}'
gws gmail messages list --params '{"userId": "me", "maxResults": 5}'
That's it. The agent has full, scoped access to Google Workspace via a CLI that outputs structured JSON. No OAuth implementation. No redirect servers. No token storage logic.
Scope mapping: TapAuth scopes → gws commands
TapAuth uses Google's standard OAuth scope names. Here's how they map to gws commands:
| TapAuth Scope | Access | gws Commands |
|---|---|---|
calendar.readonly | Read calendar events | gws calendar events list, gws calendar calendars list |
calendar.events | Full calendar access | gws calendar events * (create, update, delete) |
spreadsheets.readonly | Read Google Sheets | gws sheets spreadsheets get, gws sheets spreadsheets.values get |
spreadsheets | Full Sheets access | gws sheets spreadsheets *, gws sheets spreadsheets.values update |
documents.readonly | Read Google Docs | gws docs documents get |
documents | Full Docs access | gws docs documents * |
drive.readonly | Read Drive files | gws drive files list, gws drive files get |
gmail.readonly | Read Gmail | gws gmail messages list, gws gmail messages get |
gmail.send | Send emails | gws gmail messages send |
Request multiple scopes by comma-separating them:
tapauth grant google/calendar.readonly,spreadsheets.readonly,drive.readonly
Example workflows
List recent Drive files
# Get a token with Drive read access
export GOOGLE_WORKSPACE_CLI_TOKEN=$(tapauth token google/drive.readonly)
# List the 10 most recently modified files
gws drive files list --params '{"orderBy": "modifiedTime desc", "pageSize": 10, "fields": "files(id,name,mimeType,modifiedTime)"}'
Check today's calendar
# Get a token with Calendar read access
export GOOGLE_WORKSPACE_CLI_TOKEN=$(tapauth token google/calendar.readonly)
# List today's events
TODAY_START=$(date -u +%Y-%m-%dT00:00:00Z)
TODAY_END=$(date -u +%Y-%m-%dT23:59:59Z)
gws calendar events list --params "{\"calendarId\": \"primary\", \"timeMin\": \"$TODAY_START\", \"timeMax\": \"$TODAY_END\", \"singleEvents\": true, \"orderBy\": \"startTime\"}"
Send an email
# Get a token with Gmail send access
export GOOGLE_WORKSPACE_CLI_TOKEN=$(tapauth token google/gmail.send)
# Send a message
# Gmail API requires a base64url-encoded RFC 2822 message
MSG=$(printf 'To: team@example.com
Subject: Weekly update
Here is the weekly summary...' | base64)
gws gmail messages send --params '{"userId": "me"}' --json "{"raw": "$MSG"}"
Read a spreadsheet
# Get a token with Sheets read access
export GOOGLE_WORKSPACE_CLI_TOKEN=$(tapauth token google/spreadsheets.readonly)
# Read a range from a sheet
gws sheets spreadsheets.values get --params '{"spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms", "range": "Sheet1!A1:D10"}'
OpenClaw integration: zero-config token delivery
If you're running agents via OpenClaw, token management gets even simpler. OpenClaw's secrets provider can auto-resolve TapAuth tokens at gateway startup, so agents don't need to run tapauth commands at all.
With the tapauth-secrets provider configured, the GOOGLE_WORKSPACE_CLI_TOKEN environment variable is automatically populated from TapAuth. Your agent just uses gws commands directly — no token setup, no environment variable management, no grant flow in the agent's code.
# In your OpenClaw gateway config, add the secrets provider:
# "secrets": { "provider": "tapauth", "scopes": ["google/calendar.readonly", "google/drive.readonly"] }
# Then your agent just uses gws directly:
gws calendar events list --params '{"calendarId": "primary"}'
gws drive files list --params '{"pageSize": 5}'
This is the ideal setup for production agents: the human approves scopes once during setup, and the agent has seamless Google Workspace access from that point forward.
Why this matters for AI agents
Before gws, agents that needed Google Workspace access had to make raw HTTP requests to individual Google APIs — each with its own endpoint structure, pagination model, and query syntax. Or they used language-specific SDKs that required complex initialization.
With gws + TapAuth, the stack simplifies to:
- TapAuth handles auth — delegated, scoped, user-approved, auto-refreshing
- gws handles API access — structured CLI with JSON output across all Workspace services
- The agent focuses on what it's actually good at — understanding context and taking action
No OAuth plumbing. No SDK initialization. No token storage. Just tapauth for auth and gws for everything else.
Getting started
Install both CLIs:
# Install gws
npm install -g @googleworkspace/cli
# Install TapAuth CLI
curl -fsSL https://tapauth.ai/cli/install.sh | bash
Then follow the three-step flow above: tapauth grant → tapauth token → gws commands. Your agent will have secure, scoped Google Workspace access in under a minute.
For agent framework integration, gws also ships agent skills via skills.sh:
npx skills add https://github.com/googleworkspace/cli
This installs 40+ pre-built skills for Google Workspace operations — ready for any agent framework that supports the skills.sh format.
Links: