Maestro

Gmail

The Gmail skill lets Maestro read your inbox and send paced outreach using your own Gmail account, over the official Gmail API. Authentication uses OAuth — Maestro never sees or stores your password.

What this skill does

OperationPurposeStatus
list_inboxReturn recent threads matching a query (sender, label, time window).Shipped
read_threadFetch the full message contents for one thread — headers, decoded text + html bodies, labels.Shipped
send_emailSend a single message immediately. Pass thread_id + in_reply_to_message_id to thread replies correctly.Shipped
label_threadAdd or remove Gmail labels on a thread by name (auto-creates missing labels).Shipped
queue_paced_sendQueue a batch of messages and pace sends across a time window so you don’t trigger sender-reputation flags.Planned — pairs with a persistent send queue and scheduler.

What you’ll set up

Connecting Gmail to Maestro takes about 15 minutes the first time. You’ll:

  1. Create a Google Cloud project (free, no billing required).
  2. Enable the Gmail API on that project.
  3. Configure the OAuth consent screen so Google knows what your app is.
  4. Create OAuth 2.0 client credentials.
  5. Paste those credentials into Maestro’s secrets vault.
  6. Click Connect Gmail in Maestro and authorize the connection.

After that, the connection is persistent. Maestro refreshes access tokens automatically; you re-authorize only if you revoke the connection from your Google account or change scopes.


Prerequisites

  • A Google account that owns the inbox you want to connect. For team installs use a workspace email, not a personal one.
  • A running Maestro instance you can reach in a browser. (For local development this is http://localhost:3000. For a self-hosted production install it’s whatever domain you put Maestro on.)
  • Admin access to that Maestro instance — you need to write to the secrets vault.

Step 1 — Create a Google Cloud project

  1. Open console.cloud.google.com.
  2. In the project picker at the top of the page, click New Project.
  3. Name it something memorable like maestro-gmail (the name is internal and only you see it).
  4. Leave Organization at No organization unless you have a Google Workspace and want this project under it.
  5. Click Create.

You don’t need to enable billing. The Gmail API has a free quota that comfortably covers a single design-partner workload.

Step 2 — Enable the Gmail API

  1. With your new project selected, open the navigation menu (☰) → APIs & ServicesLibrary.
  2. Search for Gmail API.
  3. Click the Gmail API result, then Enable.

You only need to do this once per project.

This is the screen your users (probably just you) will see when authorizing Maestro.

  1. APIs & ServicesOAuth consent screen.

  2. Choose External as the user type. (Internal is only available for Google Workspace organizations.) Click Create.

  3. Fill in the required fields:

    • App name: Maestro (or whatever you want shown on the consent screen).
    • User support email: your email.
    • Developer contact information: your email.
  4. Click Save and continue.

  5. Scopes screen: click Add or remove scopes and add the following:

    • https://www.googleapis.com/auth/gmail.readonly — read messages and threads.
    • https://www.googleapis.com/auth/gmail.send — send messages on your behalf.
    • https://www.googleapis.com/auth/gmail.labels — read and apply labels.
    • https://www.googleapis.com/auth/gmail.modify — required by label_thread to attach Maestro labels to threads.

    Maestro requests only the scopes the operations you actually use require. Adding the broader gmail.modify is the safest path — without it, label_thread will fail at runtime.

  6. Save and continue through the Test users screen. Add your own Google account as a test user. While the consent screen is in Testing mode, only listed test users can complete the OAuth flow — that’s fine for self-host.

  7. Review and finish.

Publishing status. Leaving the app in Testing is correct for self-host. You only need to Publish the app (which triggers Google’s verification) if you want users outside your Google Workspace to authorize without being added as test users — that’s a v2+ concern.

Step 4 — Create OAuth 2.0 credentials

  1. APIs & ServicesCredentials.

  2. Click Create credentialsOAuth client ID.

  3. Application type: Web application.

  4. Name: Maestro (internal, only you see it).

  5. Authorized redirect URIs: add the callback URL for your Maestro instance.

    • Local development: http://localhost:3001/api/oauth/google/callback
    • Self-hosted production: https://your-maestro-domain.com/api/oauth/google/callback

    The path /api/oauth/google/callback is what Maestro listens on. Only the protocol + host changes between dev and prod.

  6. Click Create.

  7. Google shows you a Client ID and Client secret. Copy both — you’ll paste them into Maestro in the next step. The secret is only shown once; if you lose it, regenerate and update Maestro.

Step 5 — Add the credentials to Maestro

  1. Open Maestro and navigate to Secrets.

  2. Click + Add secret and create two entries:

    Secret nameKindValue
    google_oauth_client_idstringThe Client ID from step 4.
    google_oauth_client_secretapi_keyThe Client secret from step 4.
  3. Save. The values are encrypted with AES-256-GCM before they hit the database; the master key lives in your .env and never in the DB. See Secrets for the threat model.

Step 6 — Connect your Gmail account

  1. Navigate to SkillsGmail in Maestro.
  2. Click Connect Gmail.
  3. You’ll be redirected to Google’s consent screen. Sign in with the account that owns the inbox you want to connect.
  4. Google will warn you that Maestro (the app you just configured) hasn’t been verified by Google. This is expected for an app in Testing mode — click AdvancedGo to Maestro (unsafe). (Google labels every unverified app this way; it’s not a comment on Maestro specifically.)
  5. Review the requested scopes and click Allow.
  6. Google redirects you back to Maestro. The Gmail skill detail page now shows Connected as [your email].

Maestro stores the OAuth bundle (access_token, refresh_token, expires_at, granted scopes) as a single secret of kind oauth2 named gmail_oauth. The access token is short-lived (~1 hour); the refresh token doesn’t expire unless you revoke access. Maestro refreshes automatically on 401.


Verifying the connection

Run a list_inbox test from the SkillsGmail page:

  1. Click Test next to the list_inbox operation.
  2. Leave the query blank and set max_results: 5.
  3. Click Run. You should see five recent threads with subjects + sender info.

If that works, your Gmail integration is healthy. The Test UI for individual operations lands when the Skills detail page gets its full operation runner (currently a placeholder); for now, attach the Gmail skill to an agent and trigger a run to exercise the operations end-to-end.

You’re done. Cold-leads and reply-triage agents that depend on the Gmail skill will now find it configured.


Troubleshooting

“Access blocked: This app’s request is invalid” Your redirect URI doesn’t match what’s registered in Google Cloud. Confirm Step 4’s redirect URI exactly matches the URL Maestro is reachable on, including protocol and port.

“This app isn’t verified” warning every time That’s the Testing status warning. Click AdvancedGo to Maestro (unsafe). To suppress it, you’d need to publish the app and go through Google’s verification flow — only worth it for cloud SaaS or large team installs.

401 Unauthorized on operations after connecting The access token expired and refresh failed. Common causes:

  • The refresh token was revoked from your Google account permissions.
  • The OAuth client secret was rotated in Google Cloud but not updated in Maestro’s secrets.

Reconnect from SkillsGmailReconnect.

insufficient_permission on label_thread The OAuth flow didn’t request the gmail.modify scope. Re-run Step 3.5 to add the scope, then Reconnect in Maestro to capture the new scope.

Quota exceeded The free Gmail API quota is generous (1 billion quota units per day, ~250 quota units per send_email). If you hit it, either wait 24 hours or enable billing on your Cloud project. For typical design-partner workloads this is not a concern.


Permissions & data handling

Maestro requests the smallest scope set that supports its operations. Specifically:

ScopeWhy Maestro needs it
gmail.readonlyRead inbox messages for the reply-triage agent.
gmail.sendSend outreach drafted by the cold-leads agent.
gmail.labelsDiscover existing labels so label_thread can apply them by name.
gmail.modifyApply labels to threads. Does not allow deleting messages.

Maestro does not request gmail.compose (drafts), gmail.settings.basic, or any account-management scopes. It cannot delete messages, change account settings, or read mail outside your inbox.

OAuth tokens live in the encrypted secrets vault. The master key is in your .env, not the database. See Secrets for the full threat model.

You can revoke Maestro’s access at any time from myaccount.google.com/permissions. Revoking there immediately invalidates Maestro’s tokens; the next operation will fail with a 401 and the skill UI will prompt you to reconnect.