{
  "id": "Iz9IjSa1g4kMuFiE",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Draft Gmail replies automatically using Google Gemini",
  "tags": [],
  "nodes": [
    {
      "id": "70165031-7473-4801-a3c9-8a7958b84a6e",
      "name": "Template Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        -32
      ],
      "parameters": {
        "color": 4,
        "width": 640,
        "height": 996,
        "content": "## \ud83d\udce7 Draft Gmail Replies Automatically Using Google Gemini\n\n## Who's it for\nFreelancers, founders, and anyone managing a busy inbox who wants AI-drafted replies ready for review, but doesn't want the AI drafting replies to newsletters, automated notifications, or sensitive emails (complaints, contracts, payment disputes) that genuinely need a human's judgment first.\n\n## How it works\nEvery new email is first classified into one of three categories: reply_needed, skip, or needs_human_review. Only reply_needed emails get an AI-drafted reply saved to Gmail as a draft (never sent automatically). Newsletters and automated notifications are skipped entirely, no draft, no label, no noise. Anything sensitive or ambiguous is labeled for manual review instead of getting an AI-written response, so the AI never puts words in your mouth on something that actually needs your judgment.\n\n## How to set up\n1. Connect your Gmail OAuth2 credential to the trigger, draft, and labeling nodes.\n2. Connect your Google Gemini API credential to both AI nodes.\n3. In Gmail, create two labels (e.g. \"AI Drafted\" and \"Needs Manual Reply\") and find their label IDs (Gmail Settings > Labels, or via the Gmail API label list).\n4. Open the Set Configuration node and paste in both label IDs.\n5. Activate the workflow.\n\n## Requirements\n- A Gmail account with OAuth2 credentials in n8n\n- A Google Gemini API key (free tier available)\n\n## How to customize\nEdit the classification prompt to change what counts as needing human review for your inbox (e.g. anything mentioning refunds, legal terms, or specific clients). Edit the reply-generation prompt to match your brand voice."
      },
      "typeVersion": 1
    },
    {
      "id": "0959d7ff-34e5-4e23-b36a-e3f47c0fa86b",
      "name": "Section - Trigger and Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 340,
        "content": "## 1\ufe0f\u20e3 Trigger + Configuration\nFires on every new email. Adjust the poll interval in the trigger's settings. Fill in your Gmail label IDs in Set Configuration before activating."
      },
      "typeVersion": 1
    },
    {
      "id": "04917542-2c9a-4f28-a7da-bfbbe8b8f4e5",
      "name": "Section - Classification",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1008,
        320
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 548,
        "content": "## 2\ufe0f\u20e3 Classify Before Acting\nGemini decides whether this email needs an AI-drafted reply, should be skipped entirely, or needs a human's judgment. Edit the prompt to change what counts as \"needs review\" for your inbox."
      },
      "typeVersion": 1
    },
    {
      "id": "c9c183ff-ae21-431d-8205-2adc3f9e22f7",
      "name": "Section - Reply Branch",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1712,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 844,
        "height": 652,
        "content": "## 3\ufe0f\u20e3 If Reply Needed\nGenerates a draft (never auto-sent) and labels the thread so you can see at a glance which emails already have an AI draft waiting."
      },
      "typeVersion": 1
    },
    {
      "id": "e4faaffd-3e9d-4d56-8b8d-afde523fef31",
      "name": "Section - Review Branch",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1792,
        576
      ],
      "parameters": {
        "color": 7,
        "width": 564,
        "height": 424,
        "content": "## 4\ufe0f\u20e3 If Needs Human Review\nNo AI draft is generated. The email is just labeled so you know to handle it yourself, complaints and sensitive topics shouldn't get an auto-written response."
      },
      "typeVersion": 1
    },
    {
      "id": "e12a60ab-a730-4311-8f39-82d534ab24b2",
      "name": "Classifier Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1104,
        720
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a05a3bd0-0925-466a-aa24-a757d7a39abd",
      "name": "Generate Reply with Gemini",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1760,
        16
      ],
      "parameters": {
        "text": "=You are a helpful assistant drafting email replies. Write a professional, concise reply (under 100 words) to the email below. Match the sender's tone. Do not include a subject line, just the reply body.\n\nSubject: {{ $('New Email Received').item.json.Subject }}\nFrom: {{ $('New Email Received').item.json.From }}\nBody: {{ $('New Email Received').item.json.snippet }}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "850ed28e-70b6-42cf-9ee4-56ac6ba7cd5f",
      "name": "Reply Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1760,
        256
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4873a7f9-f258-4c40-b402-63efc0692f80",
      "name": "Save Reply as Gmail Draft",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2112,
        16
      ],
      "parameters": {
        "message": "={{ $json.output }}",
        "options": {
          "threadId": "={{ $('New Email Received').item.json.threadId }}"
        },
        "subject": "=Re: {{ $('New Email Received').item.json.Subject }}",
        "resource": "draft"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "774b3922-aaf9-4961-98b2-9566a432a5a8",
      "name": "Label Email as AI Drafted",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2352,
        16
      ],
      "parameters": {
        "labelIds": [
          "={{ $('Set Configuration').item.json.ai_drafted_label_id }}"
        ],
        "messageId": "={{ $('New Email Received').item.json.id }}",
        "operation": "addLabels"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ef6ad8cb-44bd-4a5a-a284-1249fc077090",
      "name": "Label Email as Needs Review",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1984,
        784
      ],
      "parameters": {
        "labelIds": [
          "={{ $('Set Configuration').item.json.needs_review_label_id }}"
        ],
        "messageId": "={{ $('New Email Received').item.json.id }}",
        "operation": "addLabels"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b1feb1db-5435-4e30-b0c7-4e3af8549399",
      "name": "New Email Received",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        384,
        528
      ],
      "parameters": {
        "filters": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.4
    },
    {
      "id": "00167c64-1e99-4476-8f73-1754d3ec9982",
      "name": "Set Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        624,
        528
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "94d8ce7e-7dbd-4074-9af8-47f29a7da26a",
              "name": "ai_drafted_label_id",
              "type": "string",
              "value": "REPLACE_WITH_GMAIL_LABEL_ID"
            },
            {
              "id": "200da2df-8205-41b0-ad9d-09716f05d4a7",
              "name": "needs_review_label_id",
              "type": "string",
              "value": "REPLACE_WITH_GMAIL_LABEL_ID"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f23e5942-16b3-4bdf-b340-72fcd39825e2",
      "name": "Classify Email",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1104,
        528
      ],
      "parameters": {
        "text": "=Classify this email into exactly one category:\n- \"reply_needed\": a genuine message from a person that deserves a reply (a question, a request, a normal conversation).\n- \"skip\": a newsletter, automated notification, receipt, or anything that isn't really addressed to a person and doesn't need a reply.\n- \"needs_human_review\": anything sensitive or judgment-heavy, complaints, refund or payment disputes, legal or contract matters, anything you shouldn't auto-draft a response to.\n\nSubject: {{ $json.Subject }}\nFrom: {{ $json.From }}\nBody: {{ $json.snippet }}\n\nAlso give a short reason for the category you picked.",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "50392cbe-f6d7-42a3-9284-c0ca5411610a",
      "name": "Classify Praser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1248,
        736
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"category\": {\n      \"type\": \"string\",\n      \"enum\": [\n        \"reply_needed\",\n        \"skip\",\n        \"needs_human_review\"\n      ]\n    },\n    \"reason\": {\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\n    \"category\",\n    \"reason\"\n  ]\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "169f9cab-f3b7-492d-a19a-18cef96656cb",
      "name": "Route by Classification",
      "type": "n8n-nodes-base.switch",
      "position": [
        1424,
        496
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "be6f2a69-4015-4f87-8565-217d66e1947f",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.output.category }}",
                    "rightValue": "reply_needed"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "0d1b73ae-d8bf-47b4-9bbd-54098f0b5037",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.output.category }}",
                    "rightValue": "needs_human_review"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "6cf9e13a-28ea-4c9b-8fd1-3f6ab675190b",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.output.category }}",
                    "rightValue": "skip"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.4
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "1e1b40e9-34d2-47c7-9c22-96c4fc0cb2ea",
  "nodeGroups": [],
  "connections": {
    "Classify Email": {
      "main": [
        [
          {
            "node": "Route by Classification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Praser": {
      "ai_outputParser": [
        [
          {
            "node": "Classify Email",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Reply Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Reply with Gemini",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Set Configuration": {
      "main": [
        [
          {
            "node": "Classify Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Email Received": {
      "main": [
        [
          {
            "node": "Set Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classifier Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Classify Email",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Route by Classification": {
      "main": [
        [
          {
            "node": "Generate Reply with Gemini",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Label Email as Needs Review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Reply as Gmail Draft": {
      "main": [
        [
          {
            "node": "Label Email as AI Drafted",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Reply with Gemini": {
      "main": [
        [
          {
            "node": "Save Reply as Gmail Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}