Google Workspace
Gmail, Google Calendar, and Google Drive toolsets.
#Google Workspace connectors
Three connectors cover the most common Google Workspace surfaces:
GmailToolSet— mail.GoogleCalendarToolSet— calendars and events.GoogleDriveToolSet— files.
All three authenticate with a Google-issued OAuth 2.0 bearer token. The recommended pattern is to obtain a refresh token once via the auth-code flow, then plug it into OAuth2Flow.refresh_token_cache(...) so the connector never sees a refresh secret directly.
from maivn_tools import (
OAuth2EndpointConfig,
OAuth2Flow,
GmailToolSet,
GoogleCalendarToolSet,
GoogleDriveToolSet,
)
flow = OAuth2Flow(
client_id=GOOGLE_CLIENT_ID,
client_secret=GOOGLE_CLIENT_SECRET,
endpoints=OAuth2EndpointConfig(
authorize_url="https://accounts.google.com/o/oauth2/v2/auth",
token_url="https://oauth2.googleapis.com/token",
),
)
cache = flow.refresh_token_cache(refresh_token, scope=" ".join([
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/drive",
]))
gmail = GmailToolSet(token=cache)
calendar = GoogleCalendarToolSet(token=cache)
drive = GoogleDriveToolSet(token=cache)Each connector also accepts a static OAuth2Token or a raw token string for one-off scripts.
Agent-ready pattern (Gmail is the reference implementation). Across all three connectors, list / search / lookup tools return compact human-readable summaries by default with a response-local_reffield (message_ref,calendar_ref,event_ref,file_ref,folder_ref). Raw Google IDs are hidden unless you passinclude_ids=True; passinclude_metadata=Falseto get the raw Google response with every field. Default page sizes are small (10 for Gmail's metadata mode, 25 for everything else). Calendar and Drive write tools (get_event,update_event,delete_event,download_file,delete_file,update_file_metadata, ...) accept either a raw ID or the dict from the corresponding list/get tool.
#GmailToolSet tools
#Agent-ready behavior (Gmail — gold-standard)
search_messages is the canonical reference for the agent-ready pattern. By default it returns compact summaries: each match gets a response-local message_ref (message_1, message_2, ...), sender, to, subject, received_at (Date header), snippet, and label_ids. Summary mode caps max_results at 10 because each candidate requires a per-message format=metadata fetch — set include_metadata=False to skip summarization and receive the raw Gmail wire format ({"messages": [{"id": ...}], "nextPageToken": ...}).
Raw Gmail message and thread IDs are omitted by default because they are internal handles, not useful for final-answer text. Set include_ids=True only when a follow-up Gmail tool needs a raw message_id or thread_id (for example before calling get_message, modify_labels, or trash_message). When the summary mode trims max_results, the response carries requestedMaxResults and summaryLimit so the caller can detect the cap.
# Summary mode — safe for final answers, no internal IDs.
gmail.search_messages("is:unread")
# { "messages": [{"message_ref": "message_1",
# "sender": "Alice <alice@example>",
# "subject": "Q3 plan", "received_at": "...",
# "snippet": "...", "label_ids": ["UNREAD", "INBOX"]}],
# "nextPageToken": "...", "resultSizeEstimate": 42 }
# Opt-in raw IDs (only when a follow-up tool needs them).
gmail.search_messages("is:unread", include_ids=True)
# Raw API passthrough (no summarization, no per-message fetch).
gmail.search_messages("is:unread", include_metadata=False)#Destructive tools (Gmail)
trash_message / trash_thread move to Trash (recoverable until purged via untrash_*). delete_draft, delete_label, batch_delete_messages, and delete_filter are tagged destructive=True and are not reversible. batch_delete_messages in particular wipes up to 1000 messages with no Trash hop — confirm with the user before invoking. Filter them out at registration with exclude_tags=["destructive"].
#GoogleCalendarToolSet tools
#Agent-ready behavior (Calendar)
list_calendars returns calendar_ref summaries with display name, description, time zone, access role, and a primary flag. Default max_results is 25. list_events and list_event_instances return event_ref summaries with summary, start/end times, location, organizer, attendees, status, and html_link (which is safe to surface to the user). Default max_results is 25. Raw Google calendar / event IDs are hidden unless include_ids=True; include_metadata=False returns the raw Google response.
Calendar IDs are tolerantly resolved everywhere: calendar_id arguments accept a raw email-like ID, the literal "primary", or the calendar dict from list_calendars(include_ids=True). event_id arguments accept a raw ID or the event dict from list_events.
calendar.list_events(time_min="2026-05-16T00:00:00Z",
time_max="2026-05-17T00:00:00Z")
# { "events": [{"event_ref": "event_1", "summary": "Standup",
# "start_time": "...", "end_time": "...",
# "organizer": "Alice <...>", "attendees": [...],
# "html_link": "https://calendar.google.com/..."}] }#Destructive tools (Calendar)
delete_event, delete_calendar, and delete_acl_rule are tagged destructive=True. delete_calendar refuses to delete the primary calendar. clear_calendar is irreversible in effect (drops every event from the calendar) even though it is a plain WRITE — confirm with the user.
#GoogleDriveToolSet tools
#Agent-ready behavior (Drive)
search_files returns compact summaries by default: each item has a response-local file_ref (or folder_ref for folders), name, mime_type, modified_time, size, and owner. Default page_size is 25. Raw Drive IDs are hidden unless include_ids=True (needed for download_file, delete_file, update_file_metadata, etc.); include_metadata=False returns the raw Google response unchanged. nextPageToken is preserved for pagination.
Most read/write tools (get_file, download_file, export_file, trash_file, untrash_file, rename_file, update_file_metadata, copy_file, move_file, delete_file, revision and permission tools) accept either a raw file_id string or the file dict from search_files(include_ids=True) — the connector extracts the ID for you.
drive.search_files("mimeType='application/vnd.google-apps.spreadsheet'")
# { "files": [{"file_ref": "file_1", "name": "Q3 plan",
# "mime_type": "application/vnd.google-apps.spreadsheet",
# "modified_time": "...", "owner": "Alice"}],
# "nextPageToken": null }#Destructive tools (Drive)
delete_file, empty_trash, delete_revision, and revoke_permission are tagged destructive=True and are not reversible — delete_file is a hard delete (use trash_file for the recoverable equivalent), and empty_trash wipes the entire trash for the user. Confirm with the user before invoking, or filter at registration with exclude_tags=["destructive"].
#Filtering tools at registration
Each toolset above ships its full Gmail/Calendar/Drive tool surface. When an agent only needs a slice, narrow at registration time:
# Read-only Gmail for a summarization agent.
agent.add_toolset(GmailToolSet(token=cache), include_tags=["read"])
# Send-only Gmail for a notification agent.
agent.add_toolset(GmailToolSet(token=cache), include=["send_email"])
# Calendar without the destructive deletes.
agent.add_toolset(
GoogleCalendarToolSet(token=cache),
exclude_tags=["destructive"],
)
# Drive minus exports/downloads (which produce large payloads).
agent.add_toolset(
GoogleDriveToolSet(token=cache),
exclude=["export_file", "download_file"],
)See Writing your own toolset for the full filter API.
#Notes
download_fileandexport_filereturn their payloads as base64-encoded strings so they remain JSON-safe when piped through agent tools.- Google APIs return paginated results via
nextPageToken. The Drive and Gmail tools accept the token directly; combine withPageTokenPaginatorfor unbounded iteration. - For domain-wide delegation, configure the OAuth flow with a service account that has the necessary scope and use the resulting bearer token with these connectors unchanged.