Aileron ControlPlane

Google

The Google suite gives your agent twenty-one capabilities against the user’s authenticated Google account, spanning five surfaces: Gmail, Calendar, Contacts, Drive, and Docs. Read paths run without prompting because they touch only the user’s own data. Write paths split: irreversible writes (send-email, send-draft) and third-party-observable writes (move-file) are gated by per-call user approval; reversible writes (draft-email, create-calendar-event, create-doc, update-doc, upload-file, rename-file) run without a runtime prompt because the API itself provides the safety net (Drafts folder, Docs revision history, Drive trash).

The suite is published from the aileron-connector-google repo. The connector runs as a sandboxed WASM module talking only to gmail.googleapis.com, www.googleapis.com, people.googleapis.com, and docs.googleapis.com; the user’s OAuth token lives in the Aileron vault and is injected host-side at the network boundary — the connector code never sees the token bytes.

Install

aileron action add-suite github://ALRubinger/aileron-connector-google/suite.toml@latest

Individual actions

Pick whichever actions you actually want exposed to the agent. Grouped by surface:

# Gmail
aileron action add github://ALRubinger/aileron-connector-google/actions/list-recent-emails@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/get-email@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/list-drafts@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/get-draft@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/draft-email@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/send-email@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/send-draft@latest
# Calendar
aileron action add github://ALRubinger/aileron-connector-google/actions/list-upcoming-events@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/create-calendar-event@latest
# Contacts
aileron action add github://ALRubinger/aileron-connector-google/actions/search-contacts@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/get-contact@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/list-contacts@latest
# Drive
aileron action add github://ALRubinger/aileron-connector-google/actions/search-files@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/get-file-metadata@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/get-file-content@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/upload-file@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/rename-file@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/move-file@latest
# Docs
aileron action add github://ALRubinger/aileron-connector-google/actions/create-doc@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/get-doc-structure@latest
aileron action add github://ALRubinger/aileron-connector-google/actions/update-doc@latest

Gmail

list-recent-emails

Lists recent Gmail messages, ordered most-recent first. Returns the raw users.messages.list response: id/threadId pairs plus paging metadata. The agent typically resolves bodies by following up with get-email.

InputRequiredDescription
querynoGmail search query, e.g. is:unread or from:[email protected]. Empty fetches the most recent without filtering.
max_resultsnoPage size. Default 10, max 100.

Idempotent. Read-only. No approval prompt.

get-email

Fetches headers and a body snippet for a single Gmail message. Uses format=metadata so the call returns Subject / From / To / Date / labelIds / snippet without pulling the full MIME body — a fast call cost for “what does this email say at a glance” agent flows.

InputRequiredDescription
idyesGmail message id, as returned by list-recent-emails.

Idempotent. Read-only. No approval prompt.

list-drafts

Lists Gmail drafts, ordered most-recent first. Returns the raw users.drafts.list response: {id, message: {id, threadId}} entries with paging metadata. The list shape carries ids only; pair with get-draft to resolve headers and a snippet, then send-draft to dispatch.

InputRequiredDescription
querynoGmail search query, e.g. subject:invoice or to:[email protected].
max_resultsnoPage size. Default 10, max 100.
page_tokennoContinuation token from a prior call’s nextPageToken.

Idempotent. Read-only. No approval prompt.

get-draft

Fetches headers and a body snippet for a single Gmail draft. Returns the raw users.drafts.get?format=metadata response. Useful immediately before send-draft so the user sees what is about to dispatch — and that’s exactly how send-draft’s approval preview is wired.

InputRequiredDescription
idyesGmail draft id (as returned by draft-email in the response’s id field — distinct from message ids).

Idempotent. Read-only. No approval prompt.

draft-email

Creates an email draft in Gmail. The draft lands in the user’s Drafts folder, where they review and send manually from Gmail’s UI or via send-draft. This is the safer write path because it inserts a human review step naturally.

InputRequiredDescription
toyesComma-separated recipient addresses.
subjectyesEmail subject line.
bodyyesPlain-text body.
ccnoComma-separated Cc addresses.
bccnoComma-separated Bcc addresses.

Not idempotent: invoking twice creates two drafts. No runtime-level approval prompt — the natural Gmail review step (or send-draft’s approval) is what gates send.

send-email

Sends an email from the user’s Gmail account. Unlike draft-email, the message leaves the outbox immediately.

InputRequiredDescription
toyesComma-separated recipient addresses.
subjectyesEmail subject line.
bodyyesPlain-text body. The user will be asked to approve this exact text before send.
ccnoComma-separated Cc addresses.
bccnoComma-separated Bcc addresses.

Approval-gated (ADR-0009). The runtime asks the user via the launch-comms channel before Gmail is contacted; on denial nothing is sent and no quota is burned. Not idempotent — the runtime’s retry layer is configured to honor that and will not double-send on transient failure.

draft-email is the safer default for unattended flows; reach for send-email only when skipping the manual click is worth the approval prompt.

send-draft

Dispatches an existing draft from the user’s Gmail Drafts folder. The draft’s recipients, subject, and body are already set in Gmail — this action takes only the draft id and tells Gmail to send. Pairs naturally with draft-email: the agent (or the user) drafts first, reviews, then sends without reconstructing the body.

InputRequiredDescription
draft_idyesGmail draft id to dispatch.

Approval-gated with an authoritative preview (ADR-0016). Before showing the prompt the runtime calls get-draft against the supplied id and renders To, Subject, and the body snippet pulled straight from Gmail — not from the agent. Not idempotent: a second invocation against the same draft_id will fail with 404 (the draft no longer exists after a successful send).

Calendar

list-upcoming-events

Lists upcoming events on a Google Calendar, chronological. Recurring events are expanded; timeMin is set to “now” so past events don’t surface.

InputRequiredDescription
calendar_idnoCalendar id. Default primary.
max_resultsnoPage size. Default 10, max 100.

Idempotent. Read-only. No approval prompt.

create-calendar-event

Inserts a new event into a Google Calendar.

InputRequiredDescription
titleyesEvent title (Calendar’s “summary” field).
start_timeyesRFC3339 timestamp, e.g. 2026-05-04T15:00:00-07:00.
end_timeyesRFC3339 timestamp.
timezonenoIANA timezone, e.g. America/New_York.
descriptionnoLong-form description.
locationnoPhysical or virtual location.
attendeesnoArray of email addresses, or comma-separated string.
calendar_idnoCalendar id. Default primary.

Approval-gated. Not idempotent — invoking twice creates two events.

Contacts

search-contacts

Searches the authenticated user’s Google Contacts via the People API’s people:searchContacts endpoint. Match is fuzzy across names, email addresses, phone numbers, organizations, and other searchable fields — “alice”, “[email protected]”, and “Acme Corp” are all valid queries.

InputRequiredDescription
queryyesSearch string. Empty queries are rejected before dispatch.
read_masknoComma-separated People API person fields to return on each match. Default names,emailAddresses,phoneNumbers,birthdays.
max_resultsnoDefault 10; clamped to 30 (the People API’s documented per-request cap).

Returns the raw people:searchContacts response. Each result’s person.resourceName (e.g. people/c123456789) feeds get-contact if a wider field set is needed.

Idempotent. Read-only. No approval prompt.

get-contact

Fetches a single contact by resource_name and returns the wide field set requested in person_fields. Pair with search-contacts or list-contacts when the lean field shape returned by those is not enough.

InputRequiredDescription
resource_nameyesGoogle-issued resource name of the form people/<id>.
person_fieldsnoComma-separated People API person fields. Default covers names, emails, phone numbers, birthdays, addresses, organizations, biographies, urls.

Idempotent. Read-only. No approval prompt.

list-contacts

Enumerates the authenticated user’s Google Contacts via people/me/connections. Returns the raw people.connections.list response. Use when the agent doesn’t yet know who it’s looking for (e.g. “show me everyone whose birthday is this month”) and filtering happens client-side after the fetch. For keyword discovery prefer search-contacts.

InputRequiredDescription
person_fieldsnoComma-separated People API person fields. Default names,emailAddresses,phoneNumbers.
max_resultsnoPage size. Default 100, max 100. Use page_token to walk past the cap.
page_tokennoContinuation token from a prior call’s nextPageToken.
sort_ordernoOne of LAST_MODIFIED_ASCENDING, LAST_MODIFIED_DESCENDING, FIRST_NAME_ASCENDING, LAST_NAME_ASCENDING.

Idempotent. Read-only. No approval prompt.

Drive

search-files

Searches Google Drive via the v3 files.list endpoint. The query argument is Drive’s full query language passed through unchanged — name matching, content matching, mimeType filtering, folder scoping, date ranges. Examples: name contains 'budget', mimeType='application/vnd.google-apps.document', '<folderId>' in parents, trashed=false.

InputRequiredDescription
querynoDrive query expression. Omit for an unfiltered list.
max_resultsnoPage size. Default 25, max 100.
order_bynoSort key, e.g. modifiedTime desc, name.
page_tokennoContinuation token from a prior call’s nextPageToken.
fieldsnoDrive partial-response field mask. Default covers id, name, mimeType, modifiedTime, parents, webViewLink.

Returns the raw files.list response. Each files[].id feeds get-file-content, get-file-metadata, get-doc-structure, update-doc, rename-file, or move-file.

Idempotent. Read-only. No approval prompt.

get-file-metadata

Fetches a single Drive file’s properties without downloading its content. Returns the raw files.get response. This action also powers the authoritative approval preview on move-file.

InputRequiredDescription
file_idyesDrive file id.
fieldsnoDrive partial-response field mask. Default covers id, name, mimeType, parents, modifiedTime, owners, webViewLink.

Idempotent. Read-only. No approval prompt.

get-file-content

Reads the text content of a Drive file. Handles two paths transparently: Google native files (Docs / Sheets / Slides) are exported via Drive’s /export endpoint (default targets: text/plain for Docs and Slides, text/csv for Sheets). Non-native files with text-shaped mimeTypes (text/*, application/json, application/xml, application/yaml, etc.) are downloaded directly via alt=media.

InputRequiredDescription
file_idyesDrive file id.
export_mime_typenoOverride the default text export type for native files. Examples: text/html, application/rtf. Ignored for non-native files.

Returns {name, mimeType, exportedAs, content} where content is the file’s text as a UTF-8 string. v1 scope: text content only — binary files (PDFs, images, archives) are rejected with a clear error. Native types with no text export (Drawings, Forms, Folders) also error unless export_mime_type names a text-compatible target.

Idempotent. Read-only. No approval prompt.

upload-file

Uploads a new text file to Drive via the v3 multipart upload endpoint. The file lands in the user’s Drive — by default in My Drive root, optionally in one or more specified folders.

InputRequiredDescription
nameyesFile name (the Drive display name).
contentyesFile content as UTF-8 text. v1 supports text content only — markdown, code, plain text, JSON / XML / YAML / TOML payloads.
mime_typenoContent mimeType. Default text/plain. Examples: text/markdown, text/csv, application/json.
parentsnoComma-separated parent folder id(s). Omit to land in My Drive root.

For creating a native Google Doc, use create-doc instead — it returns a proper Docs document_id that update-doc and get-doc-structure can target.

Not idempotent — invoking twice creates two files. No approval gate: uploads are reversible (trash from Drive) and private by default.

rename-file

Renames a Drive file (or Google Doc — Docs use the same id space as Drive). Only the display name changes; the file’s id, owners, parents, content, and sharing remain untouched.

InputRequiredDescription
file_idyesDrive file id (or Docs document id).
new_nameyesThe new display name.

Idempotent in effect (renaming to the current name is a no-op). No approval gate: renames are reversible by reissuing with the previous name.

move-file

Moves a Drive file between folders by changing its parent(s). Pass add_parents for the destination and remove_parents for the source. Omitting remove_parents makes the file a multi-parent child of both folders rather than moving it.

InputRequiredDescription
file_idyesDrive file id to move.
add_parentsyesComma-separated parent folder id(s) to add.
remove_parentsnoComma-separated parent folder id(s) to remove — typically the file’s current parent.

Approval-gated with an authoritative preview (ADR-0016). Before showing the prompt the runtime calls get-file-metadata against the supplied id and renders the file name, mimeType, and current parents — pulled straight from Drive, not the agent.

Why approval (when other Drive write actions aren’t gated): moving a file between folders changes its inherited permissions. A file in a folder shared with team-A picks up team-A’s access; moving it to team-B’s folder revokes team-A’s access and grants team-B’s. Even though the move is reversible in principle, the access change is third-party-observable — collaborators may have already opened, copied, or linked from the file during the window. The decision matrix:

ActionReversible?Third-party-observable?Approval?
update-docyes (revisions)no (private edit)no
rename-fileyes (rename back)nono
move-fileyes (move back)yes (permissions)yes
send-emailnoyesyes

Idempotent in effect — re-running with the same args leaves Drive in the same state.

Docs

create-doc

Creates a new Google Doc and (optionally) writes initial body content. The new doc lands in My Drive root, owned by the user, private by default.

InputRequiredDescription
titleyesDocument title. Shown in the Drive picker and Docs window header.
bodynoOptional initial body content (plain text).

When body is supplied the connector issues documents.create followed by documents.batchUpdate with insertText and refetches the doc so the response carries the inserted text — letting the agent compose follow-up update-doc requests against known indices without an extra get-doc-structure call.

Not idempotent — invoking twice creates two docs. No approval gate: doc creation is reversible (trash from Drive) and private by default.

get-doc-structure

Returns the full structured representation of a Google Doc as the Docs API exposes it: body content (paragraphs, tables, section breaks, table of contents), headers and footers, lists, ranges, named styles, and the index positions of every structural element. Pair with update-doc — the indices returned here are the indices update-doc operations target.

InputRequiredDescription
document_idyesGoogle Docs document id (the long alphanumeric in the doc URL).
suggestions_view_modenoOne of DEFAULT_FOR_CURRENT_ACCESS, SUGGESTIONS_INLINE, PREVIEW_SUGGESTIONS_ACCEPTED, PREVIEW_WITHOUT_SUGGESTIONS. Use SUGGESTIONS_INLINE when an update-doc batchUpdate will run against a document carrying user-made suggestions.

This is separate from get-file-content: that action returns exported plain text (useful for reading content for context, but discards index space), while this returns the Docs API’s structured JSON the agent can target via update-doc.

Idempotent. Read-only. No approval prompt.

update-doc

Applies a batch of structured edits to a Google Doc via documents.batchUpdate. The requests array is the Docs API’s own Request union — insertText, replaceAllText, deleteContentRange, updateTextStyle, updateParagraphStyle, insertTable, insertInlineImage, createNamedRange, and the rest. The agent constructs them; the connector passes them through.

InputRequiredDescription
document_idyesGoogle Docs document id.
requestsyesArray of Docs API Request objects to apply in order. Pair with get-doc-structure for accurate indices before constructing range-based requests.

Order-sensitivity: the Docs API processes requests in array order and computes index shifts between them. The conventional safe pattern is to construct requests in descending end-index order so earlier requests do not shift the indices later requests target.

Not idempotent — re-running the same insertText inserts the text twice. No approval gate: Docs revision history makes every edit reversible. ADR-0009 reserves runtime-level approval for irreversible writes (sending mail) and third-party-observable writes (move-file’s permission inheritance change); structured doc edits are neither.

Google’s OAuth consent screen names the connector publisher (ALRubinger) and the requested scope set:

  • Gmail (restricted tier): read messages and drafts; create, send, and dispatch drafts (gmail.metadata, gmail.compose).
  • Calendar (sensitive tier): read events and create events.
  • Contacts (sensitive tier): read the user’s contacts (contacts.readonly).
  • Drive: read, write, and organize files (drive).
  • Docs: read and write document structure (documents).

Per ADR-0002’s OAuth section, the consent screen is a contract between the user and the entity identified on it. The user is granting these scopes to the connector publisher’s OAuth app, not to Aileron itself.

See also