Google Workspace
nodyn connects to Google Workspace (Gmail, Sheets, Drive, Calendar, Docs) via OAuth 2.0. No third-party packages required — uses native fetch() against Google REST APIs.
1. Create a GCP Project
Section titled “1. Create a GCP Project”- Go to Google Cloud Console
- Create a new project (or use an existing one)
- Enable the following APIs:
- Gmail API
- Google Sheets API
- Google Drive API
- Google Calendar API
- Google Docs API
2. Create OAuth Credentials
Section titled “2. Create OAuth Credentials”- Go to APIs & Services > Credentials
- Click Create Credentials > OAuth client ID
- Application type: Desktop app (for CLI) or Web application (if using a proxy)
- Note the Client ID and Client Secret
3. Configure OAuth Consent Screen
Section titled “3. Configure OAuth Consent Screen”- Go to APIs & Services > OAuth consent screen
- User type: External (or Internal for Google Workspace domains)
- Add scopes:
https://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/gmail.sendhttps://www.googleapis.com/auth/gmail.modifyhttps://www.googleapis.com/auth/spreadsheetshttps://www.googleapis.com/auth/drivehttps://www.googleapis.com/auth/calendar.eventshttps://www.googleapis.com/auth/documents
- Add test users (required while app is in “Testing” status)
4. Configure nodyn
Section titled “4. Configure nodyn”Option A: Environment variables
export GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.comexport GOOGLE_CLIENT_SECRET=your-client-secretOption B: Config file (~/.nodyn/config.json)
{ "google_client_id": "your-client-id.apps.googleusercontent.com", "google_client_secret": "your-client-secret"}Option C: Setup wizard
nodyn init# Follow prompts — Google section is step 55. Authenticate
Section titled “5. Authenticate”/google authThis starts a localhost redirect OAuth flow:
- nodyn opens a temporary local server and launches the Google consent screen in your browser
- Grant the requested permissions
- Google redirects back to localhost with the auth code
- nodyn exchanges the code for tokens and stores them encrypted in the vault (
NODYN_VAULT_KEYrequired)
Tokens auto-refresh. Run /google status to check connection.
Service Account (Docker/Headless)
Section titled “Service Account (Docker/Headless)”For headless deployments (Docker, background tasks), use a service account instead of OAuth:
- Go to IAM & Admin > Service Accounts in GCP Console
- Create a service account
- Download the JSON key file
- Set the environment variable:
export GOOGLE_SERVICE_ACCOUNT_KEY=/path/to/service-account.jsonKey file requirements:
- Must be an absolute path (no relative paths)
- File permissions must be
0600or0400(warns if too loose) - Must contain valid JSON with
type: "service_account",project_id,private_key,client_email
Service accounts don’t require interactive authentication but need domain-wide delegation for accessing user data in Google Workspace domains.
CLI Commands
Section titled “CLI Commands”| Command | Description |
|---|---|
/google auth | Start OAuth device flow |
/google status | Show connection status, scopes, token expiry |
/google disconnect | Revoke tokens and remove stored credentials |
5 tools are registered when Google credentials are configured:
google_gmail— Email: search, read, send, reply, draft, archive, labelsgoogle_sheets— Spreadsheets: read, write, append, create, list, formatgoogle_drive— Files: search, read, upload, create docs, list, move, sharegoogle_calendar— Events: list, create, update, delete, free/busygoogle_docs— Documents: read, create, append, find & replace
See tools.md for full action reference.
Scopes
Section titled “Scopes”Default OAuth scopes are read-only for security. Write scopes are opt-in:
READ_ONLY_SCOPES(default): Gmail read, Sheets read, Drive read, Calendar read, Docs readWRITE_SCOPES(opt-in): Gmail send/modify, Sheets write, Drive write, Calendar events, Docs write
To enable write scopes, set google_oauth_scopes in config:
{ "google_oauth_scopes": [ "https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.send", "https://www.googleapis.com/auth/spreadsheets" ]}Alternatively, the agent can request additional scopes at runtime via requestScope(), which triggers re-authentication with the new scope set.
Permission Model
Section titled “Permission Model”- Read-only actions (search, read, list) work immediately after auth
- Write actions (send, write, upload, create, delete) require user confirmation in interactive mode and the corresponding write scope
- Scope escalation: If write scope is missing, the tool returns an error with instructions to re-auth. Use
requestScope()to upgrade incrementally
Security
Section titled “Security”Credential Protection
Section titled “Credential Protection”- OAuth tokens encrypted in SecretVault (
GOOGLE_OAUTH_TOKENSkey, requiresNODYN_VAULT_KEY) - Tokens auto-refresh via refresh token — no re-authentication needed
/google disconnectrevokes tokens at Google and deletes vault entry- Service account key files validated: absolute path, 0o600/0o400 permissions, valid JSON structure
- OAuth tokens (
ya29.*) and JWTs masked in debug output viamaskTokenPatterns() - No credentials are ever logged, stored in memory, or sent to external services
- Gmail blocks sending emails that contain detected secrets (API keys, bearer tokens)
Prompt Injection Defense (3-Layer)
Section titled “Prompt Injection Defense (3-Layer)”Google Workspace data is external and attacker-controlled (anyone can send you an email, share a doc, or create a calendar invite). All read results are defended against indirect prompt injection:
- Tool-level: All read handlers wrap external content via
wrapUntrustedData()— marks data as untrusted before the LLM sees it. Boundary-escape tags (</untrusted_data>) in content are neutralized - Agent-level: All 5 Google tools are in
EXTERNAL_TOOLS— every response is scanned viascanToolResult()for 17 injection patterns (12 categories) (tool invocation, instruction overrides, ChatML/Llama tokens, role impersonation, exfiltration, boundary escape) - Behavioral:
ToolCallTrackerdetects suspicious tool call sequences: Google read → email send (data exfiltration), Google read → HTTP POST (data exfiltration), Google read → sensitive file read (credential harvesting)
Gmail HTML Hardening
Section titled “Gmail HTML Hardening”stripHtml() removes content that could hide injection payloads:
- HTML comments (
<!-- hidden instructions -->) - CDATA sections (
<![CDATA[...]]>) - Hidden elements (
display:none,visibility:hidden,opacity:0) - Script and style blocks (including their content)
Write Protection
Section titled “Write Protection”- All write actions require interactive user confirmation (fail-safe: blocked if no prompt available)
- All write actions hard-blocked in autonomous mode via
permission-guard.ts - Default OAuth scopes are read-only — write scopes require explicit opt-in