Guide

Gmail API Limits for AI Agents

The Gmail API was designed for web applications with interactive users, not for autonomous AI agents. OAuth consent screen setup takes 30+ minutes, tokens expire every 3,600 seconds, rate limits cap at 250 quota units per second, and each send costs 100 units. Nylas CLI replaces all of that with 2 commands and works across Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP.

Written by Hazik Director of Product Management

Reviewed by Caleb Geene

VerifiedCLI 3.1.1 · Gmail · last tested April 11, 2026

Problem 1: OAuth consent screen maze

The Gmail API requires 9 discrete setup steps before an AI agent can make its first API call. Google's OAuth consent screen alone involves choosing between internal and external user types, selecting scopes, uploading a privacy policy URL, and — for external apps — submitting for a verification review that takes 1 to 6 weeks according to Google's OAuth verification documentation.

Each step adds friction that an autonomous agent can't handle on its own. You need a Google Cloud project, an OAuth consent screen configuration, and credential creation — all before writing a single line of agent code. Here is what the full setup sequence looks like:

# Gmail API: the setup you need before writing a single line of agent code
#
# 1. Create a GCP project at console.cloud.google.com
# 2. Enable the Gmail API
# 3. Configure OAuth consent screen (internal or external)
# 4. Add scopes: gmail.readonly, gmail.send, gmail.modify
# 5. Create OAuth2 credentials (client ID + secret)
# 6. If external: submit for verification review (1-6 weeks)
# 7. Implement the OAuth2 authorization flow
# 8. Handle token storage and refresh
# 9. Now you can make API calls... for Gmail only

Nylas CLI reduces this 9-step process to 2 commands. The CLI handles OAuth token exchange, scope selection, and credential storage internally, so there is no consent screen to configure and no GCP project to create.

# Nylas CLI: complete setup
brew install nylas/nylas-cli/nylas
nylas auth config

# Done. Read, send, and search email immediately.
nylas email list
nylas email send --to "user@example.com" --subject "Hello" --body "Hi there."
nylas email search "important"

Problem 2: Token refresh failures

Gmail OAuth access tokens expire after 3,600 seconds (1 hour), and Google caps refresh token grants at 50 per account per client according to the Google OAuth2 documentation. An AI agent must detect expiration, exchange the refresh token for a new access token, handle revocation, and retry the original request — a state machine that every Gmail API integration must implement correctly or risk silent failures.

# What token refresh looks like in agent code (pseudocode)
#
# try:
#     response = gmail.users().messages().list(userId="me").execute()
# except HttpError as e:
#     if e.status_code == 401:
#         try:
#             credentials.refresh(Request())
#             # Retry the original request
#             response = gmail.users().messages().list(userId="me").execute()
#         except RefreshError:
#             # Refresh token revoked or expired
#             # Need to re-authenticate from scratch
#             # How does an autonomous agent do this?
#             raise AgentAuthenticationError("Re-authentication required")

Token refresh introduces at least 4 distinct failure modes that an agent must handle individually:

  • Refresh token revoked — the user changed their Google password or revoked access in their account settings. The agent cannot recover without human intervention.
  • Token storage corruption — the token file or database entry gets corrupted. The agent needs error handling for deserialization failures.
  • Race conditions — multiple agent processes refreshing the same token simultaneously can cause one to overwrite the other's refresh token.
  • Scope changes — if you add a new scope, all existing tokens are invalid. Every user must re-authorize.

Nylas CLI handles token storage, refresh, and retry logic internally. Credentials are stored in the system keychain rather than in a flat file, which eliminates the corruption and race-condition classes of failure. If a grant expires and cannot be refreshed, the CLI returns an actionable error message instead of a raw HTTP 401.

# Nylas CLI handles token refresh automatically
# If re-authentication is needed, you get a clear message:
nylas email list
# Error: Grant expired. Run 'nylas auth config' to re-authenticate.

# Check authentication status at any time
nylas auth list

Problem 3: Rate limits and quotas

The Gmail API enforces 3 quota layers simultaneously: a per-user rate limit of 250 quota units per second, a per-project daily sending cap (500 for consumer accounts, 2,000 for Google Workspace), and per-method costs that vary by up to 20x depending on the endpoint. According to the Gmail API quota reference, a single messages.send call costs 100 units while messages.list costs only 5. An agent that exceeds any layer receives a 429 error and must implement exponential backoff with jitter.

Gmail API limitQuotaImpact on agents
Per-user rate limit250 quota units / secondBurst searches can trigger throttling
Daily sending limit500 emails (consumer) / 2,000 (Workspace)Agents managing notifications can hit this
messages.list5 quota units per callFrequent polling burns quota fast
messages.send100 quota units per callSending is 20x more expensive than listing

Building a correct backoff implementation means tracking cumulative quota consumption, parsing Retry-After headers, and adding randomized jitter to avoid thundering-herd collisions when multiple agent processes share the same project quota. Nylas CLI handles rate limiting and retry logic internally, so agent code doesn't need to implement any of this.

# Nylas CLI handles rate limits internally
# No need to implement backoff in your agent code

# These commands work reliably without quota tracking
nylas email list --limit 50 --json
nylas email search "*" --from team@company.com --json
nylas email send --to "user@example.com" --subject "Update" --body "Status report attached."

Problem 4: Scope management headaches

Gmail API scopes are locked at OAuth consent screen creation time, and Google lists over 12 individual Gmail scopes in its scope reference. Adding a new scope after deployment forces every connected user to re-authorize manually. For an agent managing 50 accounts, that means 50 separate re-authorization flows — each requiring human interaction that an autonomous agent can't perform on its own.

# Gmail API scopes an agent typically needs:
# - gmail.readonly          (read messages)
# - gmail.send              (send messages)
# - gmail.modify            (labels, mark read/unread)
# - gmail.metadata          (headers only)
# - gmail.labels            (manage labels)
#
# Problem: add one new scope later, and ALL users
# must re-authorize. For an agent managing 50 accounts,
# that means 50 manual re-authorization flows.

Nylas CLI authenticates with the appropriate scopes for full email access in a single step. The CLI requests the scopes needed for read, send, and search operations during initial authentication. There is no scope selection screen and no re-authorization when the CLI adds new capabilities in a future release.

# One authentication step, full email capability
nylas auth config

# Immediately use any email operation
nylas email list          # read
nylas email send          # send
nylas email search        # search
nylas email read          # full message with headers

Problem 5: Provider lock-in

The Gmail API only works with Gmail, which holds roughly 30% of global email market share according to Litmus email client data. An AI agent that needs to handle Outlook, Exchange, Yahoo, or iCloud accounts requires a separate integration for each provider — each with its own OAuth flow, message format, rate limits, and error codes. Supporting Gmail and Outlook alone means maintaining 2 completely independent authentication and API layers.

# With direct APIs, every provider is a separate integration:
#
# Gmail:     OAuth2 + gmail.googleapis.com + MIME encoding
# Outlook:   OAuth2 + graph.microsoft.com + Microsoft format
# Exchange:  EWS or Graph API + different auth flow
# Yahoo:     IMAP + app passwords (no modern OAuth)
# iCloud:    IMAP + app-specific passwords
#
# Each one: different auth, different API, different message format,
# different rate limits, different error codes.

Nylas CLI provides a single interface across 6 providers: Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP. The same commands and the same JSON output structure work regardless of which provider the account uses, so agent code doesn't branch on provider type.

# Same commands regardless of provider
nylas auth config              # Works for Gmail, Outlook, Exchange, Yahoo, iCloud, IMAP
nylas email list --json       # Same JSON structure from every provider
nylas email send              # Same send interface everywhere
nylas email search            # Same search syntax everywhere

# Check which accounts are authenticated
nylas auth list
# ┌─────────────────────────┬──────────┬─────────┐
# │ Email                   │ Provider │ Status  │
# ├─────────────────────────┼──────────┼─────────┤
# │ work@gmail.com          │ Google   │ Active  │
# │ team@company.com        │ Exchange │ Active  │
# │ personal@outlook.com    │ Microsoft│ Active  │
# └─────────────────────────┴──────────┴─────────┘

Problem 6: MIME message encoding

The Gmail API does not accept a plain subject and body. According to the Gmail API sending guide, every message must be a base64url-encoded RFC 2822 MIME string. A simple plain-text email requires importing a MIME library, constructing headers, encoding the body, and wrapping the result in base64url — roughly 8 lines of Python for what should be a 1-line operation. Adding HTML content, attachments, or CC/BCC fields increases the MIME complexity further.

# Gmail API requires you to build MIME messages manually:
#
# import base64
# from email.mime.text import MIMEText
#
# message = MIMEText("Hello, this is a test.")
# message["to"] = "user@example.com"
# message["subject"] = "Test"
# raw = base64.urlsafe_b64encode(message.as_bytes()).decode()
# gmail.users().messages().send(userId="me", body={"raw": raw}).execute()
#
# For HTML emails, attachments, CC/BCC, reply-to — the MIME
# construction gets significantly more complex.

Nylas CLI accepts plain-text arguments and handles MIME construction, encoding, and header formatting internally. The send command takes --to, --subject, and --body flags directly — no library imports, no encoding step, and no RFC 2822 knowledge required.

# Plain, readable command — no MIME encoding
nylas email send \
  --to "user@example.com" \
  --cc "team@company.com" \
  --subject "Q2 Report" \
  --body "Please find the Q2 report summary below." \
  --reply-to msg_previous123

Side-by-side comparison

The table below compares the Gmail API and Nylas CLI across 8 dimensions that matter most for AI agent integrations. The Gmail API requires manual implementation of OAuth, token refresh, rate limiting, and MIME encoding, while the CLI handles each internally. The most measurable difference is setup time: Gmail API integration typically takes hours to days, while the CLI produces a working email send in under 5 minutes.

CapabilityGmail APINylas CLI
Initial setupGCP project + OAuth app + consent screenbrew install + nylas auth config
AuthenticationCustom OAuth2 flow + token storageBuilt-in OAuth2, handles token refresh
Token refreshManual implementation requiredAutomatic
Rate limitingManual backoff implementationHandled internally
Message formatBase64url MIME encodingPlain text arguments
Providers supportedGmail onlyGmail, Outlook, Exchange, Yahoo, iCloud, IMAP
AI agent integrationCustom tool definitionsnylas mcp install
Time to first emailHours to daysMinutes

Give agents email access with MCP

The Model Context Protocol (MCP) integration gives AI agents native email tools without requiring the agent to shell out to CLI commands. After running 3 setup commands, an MCP-compatible agent like Claude Code, Cursor, or VS Code Copilot receives tool definitions for listing, sending, drafting, and searching email. The agent calls these tools directly through its tool-use interface, which means the agent never constructs a CLI command string or parses raw terminal output.

# Complete setup for AI agent email access
brew install nylas/nylas-cli/nylas
nylas auth config
nylas mcp install --assistant claude-code

# Your agent now has email tools:
# - list_messages (search and retrieve)
# - send_message (with human confirmation)
# - create_draft / update_draft / send_draft
# - list_threads
#
# No Gmail API code. No OAuth flow. No MIME encoding.
# Just ask: "Check my email for the latest from the legal team."

Frequently asked questions

These are the most common questions developers ask when evaluating Nylas CLI as an alternative to direct Gmail API integration. The answers cover licensing, data handling, compatibility with existing Gmail API code, Microsoft Graph differences, and multi-account management.

Is Nylas CLI free to use?

Yes. Nylas CLI is free, open-source, and MIT licensed. The source code is available on GitHub. Install it with brew install nylas/nylas-cli/nylas on macOS or Linux, or use the shell script installer for other platforms.

Does Nylas CLI store my email data?

Nylas CLI authenticates via OAuth and accesses email through the Nylas API. Messages are not stored locally beyond the JSON output of individual commands. Token credentials are stored in the system keychain (macOS Keychain, Windows Credential Manager, or Linux secret service), not in plain-text files.

Can I still use the Gmail API for specific features?

Yes. Nylas CLI and the Gmail API are not mutually exclusive. Use the CLI for agent workflows where simplicity matters, and the Gmail API directly for features that require Google-specific functionality like Gmail labels, push notifications via Pub/Sub, or Google Workspace admin operations.

What about Microsoft Graph API?

Microsoft Graph has the same categories of problems: its own OAuth2 flow with Azure AD app registration, its own token management (access tokens expire after 3,600 seconds by default), its own rate limits (10,000 requests per 10 minutes per mailbox), and its own message format. Nylas CLI abstracts Microsoft Graph the same way it abstracts the Gmail API — one set of commands for both.

How do agents switch between Gmail and Outlook accounts?

Authenticate both accounts with nylas auth config, then use --grant-id to specify which account to use for each command. The CLI command syntax is identical regardless of whether the underlying account is Gmail, Outlook, Exchange, Yahoo, iCloud, or IMAP.


Next steps