AutomationFlowsAI & RAG › Auto-label Gmail Emails Using Gemini 2.5 Pro AI Classification

Auto-label Gmail Emails Using Gemini 2.5 Pro AI Classification

ByAryan Shinde @shindearyan on n8n.io

Automatically organize your Gmail inbox with seamless, dynamic AI classification! This workflow leverages Google Gemini’s latest model to continually sort new emails into your own custom Gmail labels—no manual intervention or tedious setup required. Watches for Unread Emails:…

Event trigger★★★★☆ complexityAI-powered9 nodesGmail TriggerGoogle GeminiGmail
AI & RAG Trigger: Event Nodes: 9 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #8357 — we link there as the canonical source.

This workflow follows the Gmail → Gmail Trigger recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "f5583750-3712-45ab-b80d-e6ef59e1e6dd",
      "name": "Gmail Trigger",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        -384,
        -80
      ],
      "parameters": {
        "filters": {
          "readStatus": "unread"
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "39fb0933-4c78-4209-aa47-4bc2b76aac83",
      "name": "Message a model",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        416,
        -80
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-pro",
          "cachedResultName": "models/gemini-2.5-pro"
        },
        "options": {
          "systemMessage": "=You are an email classifier assistant.\nOnly respond with the most suitable existing Gmail label for this email from the following list: {{ $json.labelList }}.\nNever invent a label\u2014not in the list. Respond with multiple matching label names which are seperated with single comma's make sure every labels are seperated using a comma, and nothing else."
        },
        "messages": {
          "values": [
            {
              "content": "=Below is a new email.\nSubject: {{ $('Gmail Trigger').item.json.Subject }}\nBody: {{ $('Gmail Trigger').item.json.snippet }}\nWhich Gmail label does this email belong to?"
            }
          ]
        }
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4a2fcba6-5e5e-4fea-8a87-94f774a18e54",
      "name": "Add label to message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        976,
        -80
      ],
      "parameters": {
        "labelIds": "={{ $json.labelIds }}",
        "messageId": "={{ $('Gmail Trigger').item.json.id }}",
        "operation": "addLabels"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "4838c10e-bda2-4d72-ad5e-f50090ec4f9d",
      "name": "Get many labels",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -176,
        -80
      ],
      "parameters": {
        "resource": "label",
        "returnAll": true
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "310a8233-f123-473b-90ad-0df5417c66e1",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        240,
        -80
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "9628092d-b702-4543-a3ab-e225641f4b21",
              "name": "labelList",
              "type": "string",
              "value": "={{ $json.labels.map(item => item.name).join(', ') }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "3c2c6444-2a70-414e-92fc-df97b3d2ca27",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        32,
        -80
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "labels"
      },
      "typeVersion": 1
    },
    {
      "id": "5d4dea5a-6117-416a-bbf3-5c9595e479dd",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        768,
        -80
      ],
      "parameters": {
        "jsCode": "// Get all input items (your AI output should be in items[0], and label map in items[0].json.labels)\nconst items = $input.all();\n\n// 1. Parse comma-separated label names returned by the AI node\nlet resultLabels = items[0].json.content.parts[0].text\n  .split(\",\")\n  .map((label) => label.trim())\n  .filter((label) => label.length > 0);\n\n// 2. Get the label mapping array from aggregate node (should be in items[0].json.labels)\nconst labelObjects = $('Aggregate').first().json.labels || [];\nconsole.log(\"LABEL\", labelObjects);\n\n// 3. Map label names to IDs using the mapping array\nconst labelIds = resultLabels\n  .map((lName) => {\n    const match = labelObjects.find((obj) => obj.name === lName);\n    return match ? match.id : null;\n  })\n  .filter(Boolean); // remove nulls\n\n// 4. Output as n8n expects\nreturn [\n  {\n    json: {\n      labelIds,\n    },\n  },\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "2691c250-40e4-41b8-9b5e-f553cd842a2f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1008,
        -256
      ],
      "parameters": {
        "width": 496,
        "height": 480,
        "content": "## \ud83d\udce8 AI Gmail Auto-Labeler: How it Works\n\n#### Trigger:\nWatches for new unread emails.\n\n#### Label Sync:\nFetches all your current Gmail labels (label name + ID).\n\n#### AI Classification:\nSends each new email\u2019s subject & body to Gemini AI,\nPrompt: \u201cWhich Gmail label(s) does this email belong to?\u201d\nAI only uses labels from your real account list.\n\n#### Label Name \u2192 ID Mapping:\nMaps AI-predicted Gmail label names to their label IDs.\n\n#### Label Application:\nAutomatically assigns one or more valid labels to each new email."
      },
      "typeVersion": 1
    },
    {
      "id": "0409c111-441c-4ff5-99e6-39098ca775a8",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1248,
        -192
      ],
      "parameters": {
        "width": 464,
        "height": 336,
        "content": "## \ud83d\udee0\ufe0f How to Use\n- Connect your Gmail and Gemini API credentials.\n- Customize your allowed Gmail labels in your mailbox (no need to update nodes).\n- AI will NEVER suggest a label not present in your Gmail.\n- Works best if label names are clear and differ from system labels.\n- Monitors for unread emails only (edit trigger if you want all).\n- AI can assign multiple labels (comma-separated, mapped automatically).\n- Everything is dynamic and needs no manual updating of label lists for new labels.\n- You may add filters or extra conditions as desired before/after AI classification."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Code": {
      "main": [
        [
          {
            "node": "Add label to message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Message a model",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail Trigger": {
      "main": [
        [
          {
            "node": "Get many labels",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get many labels": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Message a model": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Automatically organize your Gmail inbox with seamless, dynamic AI classification! This workflow leverages Google Gemini’s latest model to continually sort new emails into your own custom Gmail labels—no manual intervention or tedious setup required. Watches for Unread Emails:…

Source: https://n8n.io/workflows/8357/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Complete AI-powered sales system Automates lead capture, qualification, and follow-up from multiple channels. AI INTELLIGENCE:

Gmail Trigger, Google Sheets, OpenAI +3
AI & RAG

An automated quote generation system that monitors your inbox, classifies quote requests using AI, calculates intelligent pricing based on historical data, and provides a professional dashboard for re

Gmail Trigger, OpenAI, Supabase +2
AI & RAG

This workflow serves as a complete "AI Receptionist" for mortgage brokers or high-ticket service providers. It automates the messy process of qualifying leads, getting internal approval, and collectin

Google Gemini, Gmail, Google Drive +3
AI & RAG

This n8n workflow — HRMate — streamlines your entire recruitment process by automatically parsing incoming job applications, evaluating candidate fit using AI, and sending personalized acceptance or r

HTTP Request, Gmail Trigger, OpenAI +2
AI & RAG

Overview

Gmail Trigger, Google Drive, OpenAI +4