ConnectOnionConnectOnion
DocsGoogle Integration

Google Integration

Send emails via Gmail and read calendar events from your AI agents. 30-second setup.

Quick Start

Terminal
$co auth google

What happens:

  1. Opens browser to Google OAuth consent screen
  2. You authorize Gmail Send + Calendar Read permissions
  3. Credentials saved to .env (both local and global ~/.co/keys.env)
  4. Ready to use Gmail and Calendar tools immediately

That's it. Your agents can now send emails and read your calendar.

Prerequisites

Before running co auth google, you must authenticate with OpenOnion:

Terminal
$co auth

This creates your OPENONION_API_KEY which is required for Google OAuth to work.

What Gets Saved

After successful authentication, your .env file contains:

.env
1# Google OAuth Credentials 2GOOGLE_ACCESS_TOKEN=ya29.a0A... 3GOOGLE_REFRESH_TOKEN=1//0g... 4GOOGLE_TOKEN_EXPIRES_AT=2025-12-31T23:59:59 5GOOGLE_SCOPES=gmail.send,calendar.readonly 6GOOGLE_EMAIL=your.email@gmail.com

Security notes

  • Credentials are saved to both local .env and ~/.co/keys.env
  • File permissions set to 0600 (read/write for owner only) on Unix systems
  • Access tokens expire, but refresh tokens allow automatic renewal
  • You can revoke access anytime via Google Account settings or the dashboard

Permissions Requested

When you run co auth google, we request these Google scopes:

ScopePurposeWhat agents can do
gmail.sendSend emails on your behalfUse send_email() tool to send emails
calendar.readonlyRead calendar eventsRead your calendar to check availability
userinfo.emailGet your email addressIdentify which Google account is connected

Privacy First

We only request the minimum permissions needed. We cannot:

  • Read your inbox (use built-in get_emails() for that)
  • Delete or modify calendar events
  • Access your Google Drive or other services

Using Google OAuth in Agents

Once authenticated, your agents can use Google-powered tools:

Send Email via Gmail

gmail_agent.py
1from connectonion import Agent, send_email 2 3def send_gmail(to: str, subject: str, body: str) -> str: 4 """Send email via your Gmail account.""" 5 result = send_email(to, subject, body) 6 return f"Email sent to {to}: {result}" 7 8agent = Agent( 9 "Gmail Assistant", 10 tools=[send_gmail] 11) 12 13agent.input("Send an email to alice@example.com saying hello")

Read Calendar Events

calendar_agent.py
1from connectonion import Agent 2import os 3from google.oauth2.credentials import Credentials 4from googleapiclient.discovery import build 5from datetime import datetime, timedelta 6 7def check_calendar(days_ahead: int = 7) -> str: 8 """Check Google Calendar for upcoming events.""" 9 # Load credentials from environment 10 creds = Credentials( 11 token=os.getenv("GOOGLE_ACCESS_TOKEN"), 12 refresh_token=os.getenv("GOOGLE_REFRESH_TOKEN"), 13 token_uri="https://oauth2.googleapis.com/token", 14 client_id=os.getenv("GOOGLE_CLIENT_ID"), # From backend 15 client_secret=os.getenv("GOOGLE_CLIENT_SECRET"), 16 scopes=["https://www.googleapis.com/auth/calendar.readonly"] 17 ) 18 19 service = build('calendar', 'v3', credentials=creds) 20 21 # Get events from now to days_ahead 22 now = datetime.utcnow().isoformat() + 'Z' 23 end = (datetime.utcnow() + timedelta(days=days_ahead)).isoformat() + 'Z' 24 25 events_result = service.events().list( 26 calendarId='primary', 27 timeMin=now, 28 timeMax=end, 29 maxResults=10, 30 singleEvents=True, 31 orderBy='startTime' 32 ).execute() 33 34 events = events_result.get('items', []) 35 36 if not events: 37 return f"No events in the next {days_ahead} days" 38 39 summary = f"Upcoming events ({len(events)}):\n" 40 for event in events: 41 start = event['start'].get('dateTime', event['start'].get('date')) 42 summary += f"- {start}: {event['summary']}\n" 43 44 return summary 45 46agent = Agent( 47 "Calendar Assistant", 48 tools=[check_calendar] 49) 50 51agent.input("What's on my calendar this week?")

Complete Example: Scheduling Agent

Here's a full agent that can check your calendar and send meeting invites:

scheduling_agent.py
1from connectonion import Agent, send_email 2import os 3from google.oauth2.credentials import Credentials 4from googleapiclient.discovery import build 5from datetime import datetime, timedelta 6 7class SchedulingAssistant: 8 """AI assistant that manages your calendar and sends meeting emails.""" 9 10 def __init__(self): 11 # Initialize Google Calendar API 12 creds = Credentials( 13 token=os.getenv("GOOGLE_ACCESS_TOKEN"), 14 refresh_token=os.getenv("GOOGLE_REFRESH_TOKEN"), 15 token_uri="https://oauth2.googleapis.com/token", 16 client_id=os.getenv("GOOGLE_CLIENT_ID"), 17 client_secret=os.getenv("GOOGLE_CLIENT_SECRET"), 18 scopes=["https://www.googleapis.com/auth/calendar.readonly"] 19 ) 20 self.calendar = build('calendar', 'v3', credentials=creds) 21 22 def check_availability(self, date_str: str) -> str: 23 """Check if a specific date/time is free on calendar.""" 24 # Parse date and check calendar 25 target_date = datetime.fromisoformat(date_str) 26 27 events_result = self.calendar.events().list( 28 calendarId='primary', 29 timeMin=target_date.isoformat() + 'Z', 30 timeMax=(target_date + timedelta(hours=1)).isoformat() + 'Z', 31 singleEvents=True 32 ).execute() 33 34 events = events_result.get('items', []) 35 36 if events: 37 return f"Not available - {len(events)} event(s) scheduled" 38 return "Available" 39 40 def send_meeting_invite( 41 self, 42 to: str, 43 subject: str, 44 datetime_str: str, 45 duration_hours: int = 1 46 ) -> str: 47 """Send meeting invitation email.""" 48 meeting_time = datetime.fromisoformat(datetime_str) 49 50 body = f""" 51Hi, 52 53I'd like to schedule a meeting with you. 54 55Date & Time: {meeting_time.strftime('%A, %B %d, %Y at %I:%M %p')} 56Duration: {duration_hours} hour(s) 57 58Please let me know if this works for you. 59 60Best regards 61""" 62 63 result = send_email(to, subject, body) 64 return f"Meeting invite sent to {to}" 65 66# Create tools from methods 67assistant = SchedulingAssistant() 68 69agent = Agent( 70 "Scheduling Agent", 71 tools=[ 72 assistant.check_availability, 73 assistant.send_meeting_invite 74 ], 75 system_prompt="""You are a scheduling assistant. 76 77You can: 781. Check calendar availability 792. Send meeting invitations via Gmail 80 81When asked to schedule a meeting: 821. First check if the proposed time is available 832. If available, send the meeting invite 843. Report back to the user 85""" 86) 87 88# Use it 89agent.input(""" 90Schedule a 1-hour meeting with bob@example.com 91for tomorrow at 2pm. Subject: Q4 Planning Discussion 92""")

Troubleshooting

"Not authenticated with OpenOnion"

You need to run co auth first to get your OPENONION_API_KEY:

Terminal
$co auth
$co auth google

Authorization Timeout

If the browser window doesn't complete authorization within 5 minutes:

Terminal
$co auth google

The command polls the backend every 2 seconds waiting for your authorization.

Credentials Not Working

Check if credentials are properly saved:

terminal
1# Check local .env 2cat .env | grep GOOGLE_ 3 4# Check global keys 5cat ~/.co/keys.env | grep GOOGLE_

If credentials exist but don't work, re-authenticate:

Terminal
$co auth google