Gmail outreach reference
How Trinity separates Gmail OAuth, mailbox readiness, aliases, draft creation, sends, replies, ingestion, and approvals.
Gmail role
Gmail is the outreach and reply rail. Trinity treats OAuth, account mailbox connection, project alias selection, draft creation, approved send execution, inbox ingestion, labels, attachments, and replies as separate governed stages.
The current architecture is deliberately not a single global Gmail account. Trinity has one platform Google OAuth app, each account connects its own mailbox, and each project selects the account-owned sending alias it may use. Project secrets do not ask users for Gmail OAuth client secrets, mailbox tokens, or refresh tokens.
| Stage | Record or module | Gate |
|---|---|---|
| Platform OAuth app | Fly/env Google OAuth client settings | Deployment-level app configuration, never project secrets |
| Account OAuth/mailbox |
GoogleOAuthController, GmailMailbox, TokenStore
| Connected account, required scopes, vault-backed token refs |
| Alias readiness |
SendingAlias
| Active alias, account ownership, send cap, owner/team policy |
| Project binding |
ProjectGmailSetting
| Project chooses an account-owned mailbox/alias and fails closed if missing |
| Draft creation |
GmailClient.users.drafts.create through GmailAdapter
| Project scope, alias readiness, ToolRouter, safety review where needed |
| Approved send/reply |
GmailClient.users.drafts.send or users.messages.send
|
LIVE_OUTREACH, project alias, suppression, approval, idempotency
|
| Thread/list/label work |
GmailClient thread and label endpoints
| Account/mailbox token, project/account scope, ToolRouter policy |
| Ingestion |
GmailPollWorker, ThreadIngestor, threads/messages
| Content quarantine and source metadata |
| Attachments |
EmailAttachment and storage refs
| Metadata first; body release requires human review |
Token and project boundary
| Boundary | Stored in Postgres | Stored in credential vault |
|---|---|---|
| OAuth connection | Provider subject, email, scopes, status, token secret refs, expiry | Access token and refresh token values |
| Gmail mailbox | Account id, OAuth connection id, email, provider subject, history id, status | No token values |
| Sending alias | Account id, mailbox id, alias email, caps, status | No token values |
| Project Gmail setting | Account id, project id, mailbox id, alias id, send mode, ingestion mode | No token values |
| ToolRouter/Gmail result | Draft id, message id, thread id, alias id, mailbox id, project setting id | No token values |
Access tokens are resolved by TokenStore.access_token_for_mailbox/3. Expired access tokens refresh server-side using the stored refresh-token ref and update only safe OAuth metadata. Legacy local file:// token refs remain readable for local/dev continuity, but configured environments use the credential vault.
Required Gmail scopes
Trinity needs enough Gmail API authority to do the work an approved operator can do: create drafts, send approved mail, read and ingest relevant threads, modify thread labels, and preserve reply context. The scopes are requested deliberately by the Google OAuth flow and are documented here because Google classifies several Gmail scopes as sensitive or restricted.
| Scope | Why Trinity needs it |
|---|---|
https://www.googleapis.com/auth/gmail.compose
| Create and manage Gmail drafts for human review. |
https://www.googleapis.com/auth/gmail.send
| Send approved direct messages or approved existing drafts. |
https://www.googleapis.com/auth/gmail.modify
|
Read, compose, send, and modify mailbox state without requesting full-delete mail.google.com authority.
|
https://www.googleapis.com/auth/gmail.readonly
| Read messages/settings needed for ingestion, reply matching, and source refs. |
https://www.googleapis.com/auth/gmail.labels
| See and edit labels used for thread state and workflow tracking. |
https://www.googleapis.com/auth/userinfo.email
| Bind the OAuth identity to the connected mailbox email. |
https://www.googleapis.com/auth/userinfo.profile
| Store safe account profile metadata for connection display. |
Google recommends using the narrowest scopes that support the application. Trinity intentionally does not request https://mail.google.com/, which grants broader mailbox authority including permanent deletion behavior. Because Trinity stores token-backed access on the server, production Google app review may require OAuth verification and restricted-scope security assessment depending on the final consent-screen status and scope classification.
Gmail API calls currently wired
| Operation | Gmail endpoint | Trinity path |
|---|---|---|
| Create draft |
users.drafts.create
|
GmailClient.create_draft/2 through ToolRouter/GmailAdapter
|
| Send existing draft |
users.drafts.send
|
GmailClient.send_email/2 with gmail_draft_id
|
| Send composed message |
users.messages.send
|
GmailClient.send_email/2 without a draft id
|
| List threads |
users.threads.list
|
GmailClient.list_threads/2
|
| Get thread |
users.threads.get
|
GmailClient.get_thread/2
|
| Modify labels |
users.threads.modify
|
GmailClient.modify_labels/2
|
Outreach safety
Hermes may draft or propose replies, but live sends require provider readiness, content safety, approval, idempotency, and ToolRouter execution. Inbound email and attachments remain quarantine-aware so indirect prompt injection cannot enter Hermes context before human release.
Project-scoped Gmail execution fails closed when the project has no active Gmail setting. This prevents Hermes or a user action from accidentally using another account or project mailbox.
Primary source links
Official references
| System | Use in Trinity | Official docs |
|---|---|---|
| Gmail | OAuth scope posture | Gmail API scopes |
| Gmail drafts | Draft creation | Gmail drafts guide |
| Gmail sending | Send/reply execution | Gmail sending guide |
Source paths
lib/autonomous_agency/email.exlib/autonomous_agency/google/oauth.exlib/autonomous_agency/google/token_store.exlib/autonomous_agency/email/gmail_client.exlib/autonomous_agency/email/gmail_mailbox.exlib/autonomous_agency/email/sending_alias.exlib/autonomous_agency/email/project_gmail_setting.exlib/autonomous_agency/email/email_draft.exlib/autonomous_agency/email/email_message.exlib/autonomous_agency/email/email_attachment.exlib/autonomous_agency/tools/gmail_adapter.exlib/autonomous_agency/workers/gmail_send_worker.exlib/autonomous_agency/workers/gmail_poll_worker.expriv/repo/migrations/20260629185000_create_project_gmail_settings.exs