<!-- Generated by `just docs` from catalog/toolkits/gmail.yaml, catalog/expansions/gmail.yaml, catalog/evals/scorecard.json. Edit the source, not this file. -->

# Gmail

Email. Search, read, send, reply to, draft, label, and delete messages and the conversation threads they sit in.

| Property | Value |
| --- | --- |
| Slug | `gmail` |
| Definition version | `0.1.0` |
| Base URL | `https://gmail.googleapis.com/gmail/v1` |
| Auth schemes | `oauth2` |
| Action tools | 28 |
| By class | 9 read, 12 write, 7 destructive |
| Triggers | 1 |
| Provider rate limit | not declared, so outbound calls are unpaced |

## Measured routing accuracy

27 golden cases replayed through the router over the whole index: measured over corpus `ea4f12ad2948` (65 toolkits, 2283 tools indexed and 13 declared uncallable), 15 cases written by hand and 11 cases from the paraphrase pass, plus 1 context case whose intent names no app and is decided by the session. A case counts as top-1 when its gold tool ranked first and top-8 when it reached the slate at all.

| Measure | Cases | Share |
| --- | --- | --- |
| top-1 | 6/27 | 22.2% |
| top-8 | 16/27 | 59.3% |

The sweep is offline: the reranker is a deterministic identity fake that returns candidates in the order retrieval produced them, so top-1 measures retrieval order rather than a reranked slate. `just eval-live` measures the same cases through the live reranker.

## Authentication

Connect an entity with `ConnectionsService.InitiateConnection`, naming this toolkit's slug. Credentials stay in the connections vault; callers hold connected-account ids only.

### `oauth2`

| Property | Value |
| --- | --- |
| Authorization URL | `https://accounts.google.com/o/oauth2/v2/auth` |
| Token URL | `https://oauth2.googleapis.com/token` |
| Default scopes | `https://www.googleapis.com/auth/gmail.modify` |
| Refresh tokens | yes, the refresh daemon renews ahead of expiry |

## Tools

28 action tools. The catalog-wide slug is `gmail.<tool>`, which is what `search_tools` returns and `call_tool` takes.

### `gmail.search_messages`

Search or list emails in the mailbox using Gmail query syntax (from:, to:, subject:, is:unread, label:, has:attachment, newer_than:7d). Use when the user wants to find, look up, or check mail. Returns message and thread ids; results are not sorted by recency. Fetch full content with get_message.

Class `read` (reads only). Scopes `https://www.googleapis.com/auth/gmail.readonly`. Calls `GET /users/me/messages`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `include_spam_trash` | boolean | no | Include SPAM and TRASH messages. Default false. |
| `max_results` | integer | no | Page size, default 100. |
| `page_token` | string | no | Token from a previous page's nextPageToken. |
| `query` | string | no | Gmail search query, e.g. "from:amy@example.com is:unread has:attachment newer_than:7d". The label: operator takes display names. Omit to list all mail. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `messages` | array of object | May be absent when nothing matches. |
| `messages[].id` | string |  |
| `messages[].threadId` | string |  |
| `nextPageToken` | string |  |
| `resultSizeEstimate` | integer |  |

Also retrieved by: "hunt down an email about something", "dig through my inbox for a message", "see if I got anything from someone", "pull up mail mentioning a topic", "track down that old email".

### `gmail.get_message`

Get one email's full content by message id: headers (From, To, Subject), body, snippet, labels, and attachment ids. Use after search_messages to read a specific message. Use internalDate for recency, not the Date header. For a whole conversation use get_thread instead.

Class `read` (reads only). Scopes `https://www.googleapis.com/auth/gmail.readonly`. Calls `GET /users/me/messages/{{params.message_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `format` | string, one of minimal, full, metadata, raw | no | Detail level. Default full. |
| `message_id` | string | **yes** | Gmail message id from search_messages or get_thread. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `internalDate` | string | Epoch milliseconds; authoritative for recency. |
| `labelIds` | array of string |  |
| `payload` | object | MIME tree. headers hold From, To, Subject; body.data is base64url; parts nest for multipart; attachment parts carry body.attachmentId for get_attachment. |
| `sizeEstimate` | integer |  |
| `snippet` | string |  |
| `threadId` | string |  |

Also retrieved by: "pull up that email and show me what it says", "open it up and let me see the whole thing", "show me everything that message contains".

### `gmail.get_attachment`

Download an email attachment by message id and attachment id. Use when the user wants a file, PDF, image, or invoice attached to a message. Attachment ids come from the message payload returned by get_message. Returns base64url-encoded file bytes.

Class `read` (reads only). Scopes `https://www.googleapis.com/auth/gmail.readonly`. Calls `GET /users/me/messages/{{params.message_id}}/attachments/{{params.attachment_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `attachment_id` | string | **yes** | body.attachmentId from the message payload. |
| `message_id` | string | **yes** | Id of the message holding the attachment. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `data` | string | base64url-encoded file bytes. |
| `size` | integer |  |

Also retrieved by: "grab the file they sent me", "save that attachment to my computer", "pull down the PDF from that email", "fetch the file that was attached".

### `gmail.modify_message_labels`

Add or remove labels on a single email: mark read or unread (UNREAD), archive (remove INBOX), star (STARRED), or apply a custom label. Takes label ids, not names; resolve ids with list_labels. For many messages at once use batch_modify_messages; for a whole conversation use modify_thread_labels.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /users/me/messages/{{params.message_id}}/modify`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `add_label_ids` | array of string | no | Label ids to add. Provide this or remove_label_ids. |
| `message_id` | string | **yes** | Message to relabel. |
| `remove_label_ids` | array of string | no | Label ids to remove. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `labelIds` | array of string |  |
| `threadId` | string |  |

Also retrieved by: "flag this one as unread again", "tag it with a category", "sort this email into a folder", "get this out of my inbox without trashing it", "keep it but hide it from my inbox".

### `gmail.batch_modify_messages`

Add or remove labels on up to 1000 emails in one call: bulk archive, mark all read or unread, or label many messages at once. Takes message ids plus label ids from list_labels. For a single message use modify_message_labels.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /users/me/messages/batchModify`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `add_label_ids` | array of string | no | Label ids to add. Provide this or remove_label_ids. |
| `message_ids` | array of string | **yes** | Messages to relabel. |
| `remove_label_ids` | array of string | no | Label ids to remove. |

Also retrieved by: "clean up my inbox by handling a bunch of these at once", "tidy up all these newsletters in one go", "sort a pile of emails into a folder together", "mass update the status on several of these".

### `gmail.trash_message`

Move an email to the trash. Use when the user wants to trash, remove, or get rid of a message. Recoverable for about 30 days via untrash_message. For permanent removal use delete_message; to trash a whole conversation use trash_thread.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `POST /users/me/messages/{{params.message_id}}/trash`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `message_id` | string | **yes** | Message to move to trash. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `labelIds` | array of string |  |
| `threadId` | string |  |

Also retrieved by: "bin that email", "toss this message out", "chuck it in the trash", "send it to the bin".

### `gmail.untrash_message`

Restore an email from the trash back to the mailbox. Use when the user wants to recover, undelete, or un-trash a message they trashed. Only works before the trash is purged.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /users/me/messages/{{params.message_id}}/untrash`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `message_id` | string | **yes** | Trashed message to restore. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `labelIds` | array of string |  |
| `threadId` | string |  |

Also retrieved by: "bring that email back from the trash", "I didn't mean to bin it, get it back", "pull that message out of the trash", "recover the one I just tossed".

### `gmail.delete_message`

Permanently delete one email, bypassing the trash. Unrecoverable; prefer trash_message when the user might want it back. Use only when the user explicitly asks for a message to be gone forever.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). Scopes `https://mail.google.com/`. Calls `DELETE /users/me/messages/{{params.message_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `message_id` | string | **yes** | Message to delete permanently. |

Also retrieved by: "wipe that email for good", "nuke this message completely", "scrub it from my mailbox entirely", "erase it permanently, no recovering it".

### `gmail.batch_delete_messages`

Permanently delete many emails at once by id, bypassing the trash. Unrecoverable; meant for bulk cleanup such as retention enforcement. Verify the id list first. When recovery may be needed, trash messages individually with trash_message instead.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). Scopes `https://mail.google.com/`. Calls `POST /users/me/messages/batchDelete`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `message_ids` | array of string | **yes** | Messages to delete permanently. |

Also retrieved by: "wipe out a bunch of old emails for good", "purge these messages completely", "clear out a pile of emails permanently", "nuke all of these at once".

### `gmail.list_threads`

List email conversations (threads) with Gmail query syntax and pagination. Use when the user thinks in conversations rather than single messages. Spam and trash are excluded unless the query targets them. Returns thread ids and snippets; read one with get_thread.

Class `read` (reads only). Scopes `https://www.googleapis.com/auth/gmail.readonly`. Calls `GET /users/me/threads`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `include_spam_trash` | boolean | no | Include SPAM and TRASH threads. Default false. |
| `max_results` | integer | no | Page size, default 100. |
| `page_token` | string | no | Token from a previous page's nextPageToken. |
| `query` | string | no | Gmail search query, same syntax as search_messages. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `nextPageToken` | string |  |
| `resultSizeEstimate` | integer |  |
| `threads` | array of object |  |
| `threads[].historyId` | string |  |
| `threads[].id` | string |  |
| `threads[].snippet` | string |  |

Also retrieved by: "show me my conversations", "what discussions do I have going", "pull up my email threads", "list out the conversations in my inbox".

### `gmail.get_thread`

Get every message in one email conversation by thread id. Use when the user wants the whole thread, the back-and-forth, or the full history with someone. Message order is not guaranteed; sort by internalDate. For a single message use get_message.

Class `read` (reads only). Scopes `https://www.googleapis.com/auth/gmail.readonly`. Calls `GET /users/me/threads/{{params.thread_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `format` | string, one of minimal, full, metadata | no | Detail level for each message. Default full. |
| `thread_id` | string | **yes** | Thread id from list_threads or search_messages. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `messages` | array of object |  |
| `messages[].id` | string |  |
| `messages[].internalDate` | string |  |
| `messages[].labelIds` | array of string |  |
| `messages[].payload` | object | MIME tree, same shape as get_message. |
| `messages[].snippet` | string |  |

Also retrieved by: "catch me up on this whole conversation", "show me every message in this exchange", "what's the full history on this discussion", "read the entire back and forth".

### `gmail.modify_thread_labels`

Add or remove labels on an entire conversation, affecting all its messages: archive a thread, mark it read, or label it. Takes label ids from list_labels, not display names. For one message only, use modify_message_labels.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /users/me/threads/{{params.thread_id}}/modify`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `add_label_ids` | array of string | no | Label ids to add. Provide this or remove_label_ids. |
| `remove_label_ids` | array of string | no | Label ids to remove. |
| `thread_id` | string | **yes** | Thread to relabel. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `messages` | array of object |  |
| `messages[].id` | string |  |
| `messages[].labelIds` | array of string |  |

Also retrieved by: "mark this whole conversation as handled", "tag the whole exchange", "get this whole discussion out of my inbox".

### `gmail.trash_thread`

Move a whole conversation and all its messages to the trash. Use when the user wants to trash or get rid of an entire thread. Recoverable for about 30 days via untrash_thread. For one message use trash_message; for permanent removal use delete_thread.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). No scopes beyond the connection's defaults. Calls `POST /users/me/threads/{{params.thread_id}}/trash`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `thread_id` | string | **yes** | Thread to move to trash. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |

Also retrieved by: "bin this whole conversation", "toss out this entire discussion", "chuck this exchange in the trash".

### `gmail.untrash_thread`

Restore a trashed conversation and its messages back to the mailbox. Use when the user wants to recover or undelete a thread they trashed.

Class `write` (writes, no confirmation needed). No scopes beyond the connection's defaults. Calls `POST /users/me/threads/{{params.thread_id}}/untrash`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `thread_id` | string | **yes** | Trashed thread to restore. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |

Also retrieved by: "bring this conversation back from the trash", "recover the whole discussion I just tossed", "pull this exchange out of the bin".

### `gmail.delete_thread`

Permanently delete a conversation and every message in it, bypassing the trash. Unrecoverable; prefer trash_thread when the user might want it back. Use only on an explicit request to erase a thread forever.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). Scopes `https://mail.google.com/`. Calls `DELETE /users/me/threads/{{params.thread_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `thread_id` | string | **yes** | Thread to delete permanently. |

Also retrieved by: "wipe out this entire conversation for good", "nuke this whole discussion permanently", "erase this exchange completely, no recovering it".

### `gmail.create_draft`

Create an email draft without sending: compose a message and save it for later review. Takes a base64url-encoded RFC 2822 MIME message; set thread_id to draft a reply inside an existing conversation. Returns a draft id for send_draft. To send immediately use send_email.

Class `write` (writes, no confirmation needed). Scopes `https://www.googleapis.com/auth/gmail.compose`. Calls `POST /users/me/drafts`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `raw` | string | **yes** | Complete RFC 2822 MIME message, base64url-encoded. Include To, Subject, and body, e.g. encode "To: amy@example.com\r\nSubject: Lunch\r\n\r\nNoon works." When drafting a reply, keep the original subject with a Re: prefix and set In-Reply-To and References headers. |
| `thread_id` | string | no | Existing thread to attach the draft reply to. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string | Draft id; pass to send_draft as-is. |
| `message` | object |  |
| `message.id` | string |  |
| `message.threadId` | string |  |

Also retrieved by: "start writing something I'm not ready to send yet", "stash a message for later without sending it", "jot down a note I'll finish later", "put together something I can review first".

### `gmail.list_drafts`

List saved email drafts with pagination. Use when the user asks what drafts exist or wants to find an unsent message. Returns draft ids; read one with get_draft. Ordering is not guaranteed.

Class `read` (reads only). Scopes `https://www.googleapis.com/auth/gmail.readonly`. Calls `GET /users/me/drafts`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `max_results` | integer | no | Page size, default 100. |
| `page_token` | string | no | Token from a previous page's nextPageToken. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `drafts` | array of object |  |
| `drafts[].id` | string |  |
| `drafts[].message` | object |  |
| `drafts[].message.id` | string |  |
| `drafts[].message.threadId` | string |  |
| `nextPageToken` | string |  |
| `resultSizeEstimate` | integer |  |

Also retrieved by: "what unsent messages do I have sitting around", "show me what I haven't sent yet", "pull up what I've started but not finished".

### `gmail.get_draft`

Get one saved draft's content by draft id, to inspect or show the unsent message before sending. Draft ids come from list_drafts or create_draft.

Class `read` (reads only). Scopes `https://www.googleapis.com/auth/gmail.readonly`. Calls `GET /users/me/drafts/{{params.draft_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `draft_id` | string | **yes** | Draft to fetch. |
| `format` | string, one of minimal, full, metadata, raw | no | Detail level. Default full. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `message` | object |  |
| `message.id` | string |  |
| `message.payload` | object | MIME tree, same shape as get_message. |
| `message.snippet` | string |  |
| `message.threadId` | string |  |

Also retrieved by: "pull up that unsent note", "show me what I've written so far", "open the one I saved earlier".

### `gmail.update_draft`

Replace a saved draft's content by draft id. Overwrites the entire draft, not individual fields; supply the complete new MIME message. Use when the user edits, revises, or fixes an unsent draft.

Class `write` (writes, no confirmation needed). Scopes `https://www.googleapis.com/auth/gmail.compose`. Calls `PUT /users/me/drafts/{{params.draft_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `draft_id` | string | **yes** | Draft to replace. |
| `raw` | string | **yes** | Complete replacement RFC 2822 MIME message, base64url-encoded, including all recipients, subject, and body. |
| `thread_id` | string | no | Existing thread the draft replies to. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `message` | object |  |
| `message.id` | string |  |
| `message.threadId` | string |  |

Also retrieved by: "fix up that unsent message", "change what I wrote before I send it", "edit the note I haven't sent yet".

### `gmail.send_draft`

Send an existing saved draft as-is by draft id. Recipients come from the draft's own To, Cc, and Bcc headers and cannot be added here. Immediate and irreversible. If the draft lacks recipients, fix it with update_draft first, or use send_email.

Class `write` (writes, no confirmation needed). Scopes `https://www.googleapis.com/auth/gmail.compose`. Calls `POST /users/me/drafts/send`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `draft_id` | string | **yes** | Draft to send, exactly as returned by create_draft or list_drafts. Synthetic or stale ids fail. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `labelIds` | array of string |  |
| `threadId` | string |  |

Also retrieved by: "go ahead and fire that off", "ship the message I saved earlier", "that one's ready, send it now", "push out the note I put together".

### `gmail.delete_draft`

Permanently delete a saved draft by draft id. Not recoverable; the unsent message is discarded. Only affects drafts, never sent or received mail. Verify the draft id before calling.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). Scopes `https://www.googleapis.com/auth/gmail.compose`. Calls `DELETE /users/me/drafts/{{params.draft_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `draft_id` | string | **yes** | Draft to discard. |

Also retrieved by: "toss that unsent message", "get rid of the one I started", "scrap what I was writing".

### `gmail.list_labels`

List every label in the mailbox, system (INBOX, UNREAD, STARRED, SPAM, TRASH) and user-created, with their ids. Use to resolve a label name to the label id other tools require; display names do not work as ids. Also answers what labels or folders exist.

Class `read` (reads only). Scopes `https://www.googleapis.com/auth/gmail.labels`. Calls `GET /users/me/labels`.

Takes no arguments.

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `labels` | array of object |  |
| `labels[].id` | string | Internal id, e.g. "Label_123" or "INBOX". |
| `labels[].name` | string |  |
| `labels[].type` | string | system or user. |

Also retrieved by: "what folders do I have set up", "show me my categories and tags", "what tags exist in my mailbox", "what are all my organizing labels called".

### `gmail.get_label`

Get one label's details by label id: name, type, unread and total message and thread counts, and visibility. Use list_labels first to resolve the id. Answers questions like how many unread messages a label has.

Class `read` (reads only). Scopes `https://www.googleapis.com/auth/gmail.labels`. Calls `GET /users/me/labels/{{params.label_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `label_id` | string | **yes** | Label id from list_labels. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `labelListVisibility` | string |  |
| `messageListVisibility` | string |  |
| `messagesTotal` | integer |  |
| `messagesUnread` | integer |  |
| `name` | string |  |
| `threadsTotal` | integer |  |
| `threadsUnread` | integer |  |
| `type` | string |  |

Also retrieved by: "how many unread emails are under that folder", "what's the count on this tag", "how many messages are filed under this one".

### `gmail.create_label`

Create a new label (folder or tag) for organizing mail. Use when the user wants a new category, folder, or tag. Returns the label id that labeling tools require; they do not accept display names. Label names must be unique.

Class `write` (writes, no confirmation needed). Scopes `https://www.googleapis.com/auth/gmail.labels`. Calls `POST /users/me/labels`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `label_list_visibility` | string, one of labelShow, labelShowIfUnread, labelHide | no | Visibility in the label list. Default labelShow. |
| `message_list_visibility` | string, one of show, hide | no | Visibility in the message list. Default show. |
| `name` | string | **yes** | Display name, e.g. "Receipts". Use "/" to nest. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `name` | string |  |
| `type` | string |  |

Also retrieved by: "set up a new folder for something", "make a new tag to sort messages", "start a new category for my mail".

### `gmail.update_label`

Rename a user-created label or change its visibility by label id. Use when the user renames a label or folder. System labels such as INBOX or SENT cannot be modified.

Class `write` (writes, no confirmation needed). Scopes `https://www.googleapis.com/auth/gmail.labels`. Calls `PATCH /users/me/labels/{{params.label_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `label_id` | string | **yes** | User-created label to update. |
| `label_list_visibility` | string, one of labelShow, labelShowIfUnread, labelHide | no | Visibility in the label list. |
| `message_list_visibility` | string, one of show, hide | no | Visibility in the message list. |
| `name` | string | no | New display name. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `name` | string |  |
| `type` | string |  |

Also retrieved by: "rename that folder", "change what this tag is called", "give this one a new name".

### `gmail.delete_label`

Permanently delete a user-created label definition, removing it from every message it is applied to; the messages themselves are kept. System labels cannot be deleted. To take a label off specific messages instead, use modify_message_labels.

Class `destructive` (held by the mutation gate until the call's own arguments carry `"confirm": true`). Scopes `https://www.googleapis.com/auth/gmail.labels`. Calls `DELETE /users/me/labels/{{params.label_id}}`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `label_id` | string | **yes** | User-created label to delete. |

Also retrieved by: "get rid of that tag for good", "remove this folder, I don't need it anymore", "delete this category entirely".

### `gmail.send_email`

Send an email immediately. Use when the user wants to email, message, or forward something to someone. Takes a base64url-encoded RFC 2822 MIME message with To, Subject, and body. Irreversible; confirm recipients first. To reply inside an existing conversation use reply_to_thread; to save without sending use create_draft.

Class `write` (writes, no confirmation needed). Scopes `https://www.googleapis.com/auth/gmail.send`. Calls `POST /users/me/messages/send`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `raw` | string | **yes** | Complete RFC 2822 MIME message, base64url-encoded. Include To (plus Cc or Bcc as needed), Subject, and body, e.g. encode "To: amy@example.com\r\nSubject: Lunch\r\n\r\nNoon works." Total size after encoding is capped near 25 MB. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `labelIds` | array of string |  |
| `threadId` | string |  |

Also retrieved by: "fire off a message to someone", "shoot them a quick note", "get a message out to them with the details", "ping them over mail with an update", "drop them a line about something".

### `gmail.reply_to_thread`

Send a reply inside an existing email conversation by thread id. Use when the user wants to reply, respond, or write back on a thread. Keep the original subject with a Re: prefix and set In-Reply-To and References headers in the MIME message, or the reply starts a new thread. For a fresh email use send_email.

Class `write` (writes, no confirmation needed). Scopes `https://www.googleapis.com/auth/gmail.send`. Calls `POST /users/me/messages/send`.

Arguments:

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `raw` | string | **yes** | Reply as a complete RFC 2822 MIME message, base64url-encoded. Subject must match the original with a Re: prefix; set In-Reply-To and References to the original Message-ID header. |
| `thread_id` | string | **yes** | Conversation to reply within. |

Result fields (the payload is trimmed to these before it reaches the model):

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string |  |
| `labelIds` | array of string |  |
| `threadId` | string |  |

Also retrieved by: "write back on this conversation", "answer them in this exchange", "respond to what they said in this discussion", "get back to them on this one".

## Triggers

Triggers are app-initiated. They are not retrievable as tools and cannot be called; subscribe with `TriggersService.CreateSubscription` and events arrive as signed deliveries.

### `new_email`

Fires when a watched mailbox changes, which is how Gmail reports new mail. Carries the Pub/Sub message whose base64 data holds the mailbox address and the history id; read the new messages with search_messages or list_history after it fires.

Payload fields (anything the schema does not declare never reaches a subscriber):

| Field | Type | Notes |
| --- | --- | --- |
| `message` | object |  |
| `message.data` | string |  |
| `message.messageId` | string |  |
| `message.publishTime` | string |  |
| `subscription` | string |  |

## Inbound webhooks

Providers post to `/webhooks/gmail`. Posts that fail verification are rejected before anything is stored, and the ingest path refuses every post while the secret variable is unset.

| Property | Value |
| --- | --- |
| Verification scheme | `token_query` |
| Shared secret | `AUTOMATON_GMAIL_WEBHOOK_TOKEN` (deployment environment) |
| Token query parameter | `token` |

Mappings are tried in order and the first match wins.

| Trigger | Matches when | Entity resolved from |
| --- | --- | --- |
| `new_email` | every remaining post |  |
