{
  "name": "Draft AI replies to incoming Gmail emails with Groq Llama 3.3",
  "tags": [],
  "nodes": [
    {
      "id": "ae007662-9792-46f0-afad-de519c4b9987",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        16
      ],
      "parameters": {
        "width": 480,
        "height": 864,
        "content": "## Draft AI replies to incoming Gmail emails with Groq Llama 3.3\n\n### How it works\n\nThis workflow watches Gmail for newly received emails and sends each message to Groq Llama 3.3 to generate a possible reply. It parses the AI response, checks whether a reply is actually needed, and creates a Gmail draft only when the condition passes. The user can then review and send the drafted response manually from Gmail.\n\n### Setup steps\n\n- Connect Gmail credentials for both the Gmail Trigger and Gmail draft creation node, ensuring permissions include reading messages and creating drafts.\n- Configure the HTTP Request node with a valid Groq API key, typically using an Authorization header such as `Bearer <GROQ_API_KEY>`.\n- Verify the Groq request body uses the intended Llama 3.3 model and includes the desired email fields, such as sender, subject, and body.\n- Review the Parse code node output structure so it matches the fields expected by the `Needs a reply?` condition and the Gmail draft node.\n\n### Customization\n\nAdjust the AI prompt to change tone, length, language, or signature. You can also modify the conditional logic to skip newsletters, automated emails, or messages from specific senders."
      },
      "typeVersion": 1
    },
    {
      "id": "57ab96af-7249-4a8a-96f1-ee8e4409bb7c",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        96
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 368,
        "content": "## Receive incoming email\n\nStarts the workflow when a new Gmail message arrives and passes the email content onward for reply generation."
      },
      "typeVersion": 1
    },
    {
      "id": "a2c4f4e6-7473-4eb9-bc3b-14ecb54e313f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        128
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 336,
        "content": "## Generate and parse draft\n\nSends the incoming email to Groq's OpenAI-compatible chat completion endpoint to create a suggested reply, then parses the AI response into usable workflow fields."
      },
      "typeVersion": 1
    },
    {
      "id": "9732d18f-93d4-4f4e-b477-16c60f273c24",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        704,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 432,
        "content": "## Check and create draft\n\nDetermines whether the parsed AI output indicates a reply is needed, and if so creates a Gmail reply draft for the user to review."
      },
      "typeVersion": 1
    },
    {
      "id": "node-trigger-9",
      "name": "When Email Received",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        0,
        300
      ],
      "parameters": {
        "simple": false,
        "filters": {},
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "node-ai-10",
      "name": "Post to Groq for Reply Draft",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        272,
        304
      ],
      "parameters": {
        "url": "https://api.groq.com/openai/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"llama-3.3-70b-versatile\",\n  \"temperature\": 0.3,\n  \"response_format\": { \"type\": \"json_object\" },\n  \"messages\": [\n    { \"role\": \"system\", \"content\": \"You are the email first-response assistant for [YOUR COMPANY / SHOP NAME].\\nRead the incoming email and reply ONLY with a JSON object with exactly these keys:\\n- should_reply: true | false (true only for real senders that expect a reply; false for newsletters, automated notifications and ads)\\n- reply_draft: a polite reply draft (~120 words). No signature. Never state facts you cannot verify (stock, prices, delivery dates) \u2014 say you will check and follow up instead.\\nOutput nothing but the JSON.\" },\n    { \"role\": \"user\", \"content\": {{ JSON.stringify(($json.text || $json.snippet || \"\").slice(0, 3000)) }} }\n  ]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "none",
        "specifyHeaders": "keypair",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "node-code-11",
      "name": "Parse AI Draft Response",
      "type": "n8n-nodes-base.code",
      "position": [
        512,
        304
      ],
      "parameters": {
        "jsCode": "const item = $input.first().json;\nconst content = item?.choices?.[0]?.message?.content ?? '{}';\nlet data;\ntry { data = JSON.parse(content); } catch (e) { data = { should_reply: false, reply_draft: '' }; }\nconst trig = $('When Email Received').first().json;\nfunction asText(v){\n  if(v == null) return '';\n  if(typeof v === 'string') return v;\n  if(typeof v === 'object'){\n    if(typeof v.text === 'string') return v.text;\n    if(Array.isArray(v.value) && v.value[0]) return v.value[0].address || v.value[0].name || '';\n    if(typeof v.address === 'string') return v.address;\n    return '';\n  }\n  return String(v);\n}\nreturn [{ json: {\n  should_reply: data.should_reply === true,\n  reply_draft: data.reply_draft ?? '',\n  subject: asText(trig.subject ?? trig.Subject),\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "node-if-12",
      "name": "If Reply Needed",
      "type": "n8n-nodes-base.if",
      "position": [
        752,
        304
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-12",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.should_reply ? \"yes\" : \"\" }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "node-draft-13",
      "name": "Send Reply via Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        992,
        176
      ],
      "parameters": {
        "message": "={{ $json.reply_draft }}",
        "options": {},
        "subject": "={{ 'Re: ' + ($json.subject || 'your message') }}",
        "resource": "draft",
        "emailType": "text"
      },
      "typeVersion": 2.1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "If Reply Needed": {
      "main": [
        [
          {
            "node": "Send Reply via Gmail",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "When Email Received": {
      "main": [
        [
          {
            "node": "Post to Groq for Reply Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Draft Response": {
      "main": [
        [
          {
            "node": "If Reply Needed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Groq for Reply Draft": {
      "main": [
        [
          {
            "node": "Parse AI Draft Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}