AutomationFlowsAI & RAG › Personalized B2b Cold Email Sequence with Gpt-4 + Gmail Auto-reply Detection

Personalized B2b Cold Email Sequence with Gpt-4 + Gmail Auto-reply Detection

ByPeyrichou Maxime @mapey on n8n.io

Stop manually sending follow-ups. This workflow automates your entire cold email outreach with AI-powered personalization, smart scheduling, and automatic reply detection.

Event trigger★★★★★ complexityAI-powered42 nodesOpenAI ChatGmail ToolGoogle SheetsGmail TriggerSlackAgentGoogle Sheets TriggerError Trigger
AI & RAG Trigger: Event Nodes: 42 Complexity: ★★★★★ AI nodes: yes Added:

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

This workflow follows the Agent → Error 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": "0d14bc34-45ce-4662-97c2-47626255899e",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        6688,
        1520
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "c7cf1a6f-3aa1-4c4a-af41-1ba14a2165a3",
      "name": "Gmail Tool - Send Email 1",
      "type": "n8n-nodes-base.gmailTool",
      "position": [
        6880,
        1520
      ],
      "parameters": {
        "sendTo": "={{ $fromAI('to') }}",
        "message": "={{ $fromAI('message_html') }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ $fromAI('subject') }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a08a7f3b-e01c-4523-a0d2-495b1f7a7819",
      "name": "OpenAI Chat Model 2",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        7136,
        1952
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "2ecb0030-2d43-45af-93ae-e5cfd3ad283a",
      "name": "Gmail Tool - Send Email 2",
      "type": "n8n-nodes-base.gmailTool",
      "position": [
        7280,
        1952
      ],
      "parameters": {
        "sendTo": "={{ $fromAI('to') }}",
        "message": "={{ $fromAI('message_html') }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ $fromAI('subject') }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "d83a2b90-71e6-40c5-83a9-23a109217169",
      "name": "OpenAI Chat Model 3",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        7392,
        2368
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "707df043-89f2-49db-9db0-810f9aac121b",
      "name": "Gmail Tool - Send Email 3",
      "type": "n8n-nodes-base.gmailTool",
      "position": [
        7536,
        2384
      ],
      "parameters": {
        "sendTo": "={{ $fromAI('to') }}",
        "message": "={{ $fromAI('message_html') }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ $fromAI('subject') }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e72a9091-3fd7-4562-86fd-70b3119cacf8",
      "name": "Final Update to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        8080,
        2160
      ],
      "parameters": {
        "columns": {
          "value": {
            "Email": "={{ $json.to }}",
            "email3_Statut": "=Sent at {{ $now.toISO() }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Pr\u00e9nom",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Pr\u00e9nom",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Nom",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Nom",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Poste",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Poste",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Entreprise",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Entreprise",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Secteur",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Secteur",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Taille",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Taille",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LinkedIn URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LinkedIn URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email1_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email1_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email2_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email2_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email3_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email3_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email1_Statut",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email1_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email2_Statut",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email2_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email3_Statut",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email3_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Statut Prospect",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Statut Prospect",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit#gid=0",
          "cachedResultName": "Feuille 1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit?usp=drivesdk",
          "cachedResultName": "Data Training 3 touchpoint"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "8636c456-654e-4742-a885-f5b204d0d22e",
      "name": "Gmail Reply Trigger",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        6144,
        2608
      ],
      "parameters": {
        "filters": {
          "labelIds": [
            "INBOX"
          ]
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "2e4e3a49-9e78-4b18-a29a-16da82824828",
      "name": "Mark Prospect as Hot",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        6416,
        2608
      ],
      "parameters": {
        "columns": {
          "value": {
            "Email": "={{ $json.From }}",
            "Statut Prospect": "hot"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Pr\u00e9nom",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Pr\u00e9nom",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Nom",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Nom",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Poste",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Poste",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Entreprise",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Entreprise",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Secteur",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Secteur",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Taille",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Taille",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LinkedIn URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LinkedIn URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email1_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email1_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email2_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email2_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email3_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email3_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email1_Statut",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email1_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email2_Statut",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email2_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email3_Statut",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email3_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Statut Prospect",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Statut Prospect",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit#gid=0",
          "cachedResultName": "Feuille 1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit?usp=drivesdk",
          "cachedResultName": "Data Training 3 touchpoint"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "238fa380-3ea7-4e33-bb9c-0b7d7278d21f",
      "name": "Check Status Before Email 2",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        6304,
        1712
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit#gid=0",
          "cachedResultName": "Feuille 1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "1bb3c08b-3fc4-40b2-a9d0-ea0f49a481d8",
      "name": "Check if Hot After Email 2",
      "type": "n8n-nodes-base.if",
      "position": [
        6480,
        1712
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "id-1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json['Statut Prospect'] }}",
              "rightValue": "hot"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6993dd41-3c79-4143-b7de-161322fc3891",
      "name": "Check Status Before Email 3",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        6320,
        2144
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit#gid=0",
          "cachedResultName": "Feuille 1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit?usp=drivesdk",
          "cachedResultName": "Data Training 3 touchpoint"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "9689ac7a-51db-4044-a7ac-3ef085776a9b",
      "name": "Check if Hot After Email ",
      "type": "n8n-nodes-base.if",
      "position": [
        6608,
        2144
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "id-1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json['Statut Prospect'] }}",
              "rightValue": "hot"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "d9c3fc00-2c42-4760-b57f-08b2b490d518",
      "name": "Send a message",
      "type": "n8n-nodes-base.slack",
      "position": [
        6640,
        2608
      ],
      "parameters": {
        "text": "Test : Bonjour a tous un prospect viens de r\u00e9pondre",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09SL6FPYP8",
          "cachedResultName": "notif-email"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "7dbcffbd-73a1-4fb3-81eb-97c6973fbe86",
      "name": "Agent : Email 1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        6704,
        1296
      ],
      "parameters": {
        "text": "==Prospect profile:\n- First Name: {{ $json[\"First Name\"] }}\n- Last Name: {{ $json[\"Last Name\"] }}\n- Job title: {{ $json.Job_title }}\n- Company: {{ $json.company }}\n- Company size (employees): {{ $json[\"company size\"] }}\n- Sector: {{ $json.Sector }}\n- LinkedIn URL: {{ $json[\"LinkedIn URL\"] }}\n- Email: {{ $json.Email }}\n\nSender / offer:\n- Sender name: {{ $json.senderName }}\n- Sender company: {{ $json.companyName }}\n- Product / service description: {{ $json[\"Description of the companies or product\"] || \"Not provided\" }}\n\nSequence timing:\n- Email 1 scheduled at (ISO): {{ $json.email1_at }}\n- Email 2 scheduled at (ISO): {{ $json.email2_at }}\n- Email 3 scheduled at (ISO): {{ $json.email3_at }}\n",
        "options": {
          "systemMessage": "You are an expert in B2B outbound prospecting and cold email copywriting, running inside an n8n workflow.\n\nYOUR GOAL\n- Analyze the prospect profile and the sender\u2019s offer.\n- Choose the best possible commercial angle for this specific prospect.\n- WRITE and SEND Email 1 using the Gmail tool available in this workflow.\n- Do not just return plain text: you must both call the Gmail tool and then return a JSON summary with the fields `to`, `subject`, and `message_html`.\n\nINPUT DATA (from the user message)\nYou receive:\n- Prospect data: first name, last name, job title, company size, sector, LinkedIn URL, email.\n- Sender data: senderName, companyName, and \"Description of the companies or product\".\n- Sequence timing: email1_at, email2_at, email3_at.\n\nBEHAVIOR\n- Think like a senior B2B strategist and copywriter.\n- Select a credible, relevant angle, for example:\n  - saving time, reducing costs, increasing revenue,\n  - reducing risk, improving processes, boosting team performance.\n- Adapt tone based on company size:\n  - Large enterprises: slightly more formal.\n  - SMEs / startups: more direct and conversational, still professional.\n\nRESEARCH (OPTIONAL)\n- If web / HTTP tools are available, you may:\n  - quickly review the prospect\u2019s company website,\n  - identify 1\u20132 typical challenges or priorities for their sector or role.\n- Use this only to sharpen your angle and personalization, not to write long context paragraphs.\n\nEMAIL 1 REQUIREMENTS\n- Length: 80\u2013120 words.\n- Subject: clear, benefit-oriented, not clickbait.\n- Opening: personalized to the role, sector, and company context.\n- Body:\n  - Focus on ONE main, concrete benefit for the prospect.\n  - Use 1\u20132 simple impact statements (what changes for them).\n- Call to action:\n  - Light, low pressure: propose a short call or ask if this is worth exploring.\n- Style:\n  - No empty jargon.\n  - No aggressive or pushy tone.\n\nLANGUAGE\n- If the prospect clearly appears French-speaking (French company, .fr domain, French name, etc.), write the email in FRENCH.\n- Otherwise, write the email in ENGLISH.\n\nGMAIL TOOL USAGE\n- You have access to a Gmail tool in this workflow (gmailTool / \u201cGmail Tool - Send Email 1\u201d).\n- Once the email is ready, you MUST call this Gmail tool with:\n  - `to` / `sendTo`: the prospect\u2019s email,\n  - `subject`: the subject line you wrote,\n  - `message` / `message_html`: the email body in simple HTML (`<p>`, `<br>`).\n- You must call this tool exactly once per execution.\n\nFINAL OUTPUT FORMAT\nAfter calling the Gmail tool, you must return a single JSON object (no markdown) summarizing what you sent:\n\n{\n  \"to\": \"email_of_the_prospect\",\n  \"subject\": \"Subject of email 1\",\n  \"message_html\": \"<p>Email 1 content in simple HTML</p>\"\n}\n\n- `to` = the prospect\u2019s email (from the input).\n- `subject` = the benefit-driven subject line you wrote.\n- `message_html` = the body of the email in very simple HTML.\n"
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "faabcdd8-b027-44ac-a9b8-3d81a9eed1ec",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5808,
        2560
      ],
      "parameters": {
        "color": 6,
        "width": 1072,
        "height": 208,
        "content": "## \ud83d\udd14 REPLY DETECTION\n\nMonitors Gmail inbox for replies\n\u2192 Matches prospect by email\n\u2192 Updates Sheet: Statut = \"hot\"\n\u2192 Stops future emails automatically\n\u2192 Sends Slack notification\n\nRuns every minute (Gmail Trigger poll)"
      },
      "typeVersion": 1
    },
    {
      "id": "262e7fa2-39a9-4331-893f-9c349b0767cb",
      "name": "Google Sheets Trigger",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "position": [
        5616,
        1296
      ],
      "parameters": {
        "event": "rowAdded",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit#gid=0",
          "cachedResultName": "Feuille 1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit?usp=drivesdk",
          "cachedResultName": "Data Training 3 touchpoint"
        }
      },
      "credentials": {
        "googleSheetsTriggerOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "adf44e05-5c2c-4c2b-a3cc-9d06e40432a6",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        6448,
        1312
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "a04177f6-1fc6-479a-ab22-073d730b6053",
      "name": "Update Statut Email 2",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        7888,
        1728
      ],
      "parameters": {
        "columns": {
          "value": {
            "id": "=",
            "Email": "={{ $json.to }}",
            "email2_at": "=Sent at {{ $now.toISO() }}",
            "email2_Statut": "Send"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Pr\u00e9nom",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Pr\u00e9nom",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Nom",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Nom",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Poste",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Poste",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Entreprise",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Entreprise",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Secteur",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Secteur",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Taille",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Taille",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LinkedIn URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LinkedIn URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email1_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email1_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email2_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email2_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email3_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email3_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email1_Statut",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email1_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email2_Statut",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email2_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email3_Statut",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email3_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Statut Prospect",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Statut Prospect",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit#gid=0",
          "cachedResultName": "Feuille 1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit?usp=drivesdk",
          "cachedResultName": "Data Training 3 touchpoint"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "b9ad028b-c249-4829-837e-7736eba2be86",
      "name": "Entreprise Description",
      "type": "n8n-nodes-base.set",
      "position": [
        5552,
        1984
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "companyName",
              "type": "string",
              "value": "YOUR COMPANY NAME"
            },
            {
              "id": "id-2",
              "name": "senderName",
              "type": "string",
              "value": "YOUR NAME \u2013 YOUR TITLE"
            },
            {
              "id": "0c1cc95a-9978-48a4-8a6d-599996b9e39a",
              "name": "Description of the companies or product",
              "type": "string",
              "value": "YOUR VALUE PROPOSITION (what you help your clients achieve)"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "0e6f4bbe-6892-489c-a5a2-3ef563ebf72f",
      "name": "Merge1",
      "type": "n8n-nodes-base.merge",
      "position": [
        6816,
        1744
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "819e885c-e1e2-4d02-b719-100e118bdf9c",
      "name": "Merge2",
      "type": "n8n-nodes-base.merge",
      "position": [
        6944,
        2144
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "1bbd1262-ef5a-40e7-9c50-7f6b8747bf8f",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5584,
        1008
      ],
      "parameters": {
        "width": 624,
        "height": 464,
        "content": "# \u23f0 SMART SCHEDULING\n\n\u2705 Only sends: Tuesday, Wednesday, Thursday\n\u2705 Time: 9AM (+/- randomization for spam prevention)\n\u2705 Skips weekends automatically\n\u2705 If calculated time already passed \u2192 next allowed day\n\nEdit SEND_HOUR and OFFSETS in code to customize"
      },
      "typeVersion": 1
    },
    {
      "id": "317c4acc-8d45-46bd-9816-45d366391338",
      "name": "Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        7136,
        2592
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "e9854f6e-01a1-42c2-93ea-45dd3c7a5496",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6224,
        960
      ],
      "parameters": {
        "color": 3,
        "width": 1568,
        "height": 720,
        "content": "# \ud83d\udce7 EMAIL 1 - Introduction\n\nTiming: J0 (Day prospect is added)\nGoal: Introduce value proposition\nLength: 80-120 words\nAI-powered personalization based on:\n- Company sector\n- Job title  \n- Company size\n- Recent context (if available)\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4770bb7b-f77e-41e6-aeea-7ff6a7c8f563",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5808,
        1696
      ],
      "parameters": {
        "color": 4,
        "width": 2496,
        "height": 416,
        "content": "# \ud83d\udce7 EMAIL 2 - Follow-up\n\nTiming: J+3 (3 days after Email 1)\nGoal: New angle + concrete example\nLength: 70-90 words\nAdapts based on Email 1 open status\nMentions: case study, use case, or specific benefit"
      },
      "typeVersion": 1
    },
    {
      "id": "c30fd2bd-1937-4681-922d-50b11f0f6436",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5808,
        2128
      ],
      "parameters": {
        "color": 5,
        "width": 2496,
        "height": 416,
        "content": "# \ud83d\udce7 EMAIL 3 - Final Touch\n\nTiming: J+7 (7 days after Email 1)\nGoal: Soft close, respect prospect's time\nLength: 60-100 words\nFinal attempt with lightweight CTA\nImplies this is the last contact"
      },
      "typeVersion": 1
    },
    {
      "id": "13a943a7-8dff-467b-8c58-c4808205a056",
      "name": "Send a message1",
      "type": "n8n-nodes-base.slack",
      "position": [
        7344,
        2592
      ],
      "parameters": {
        "text": "=Error Workflow : {{ $json.execution.url }}\nWorkflow Name : {{ $json.workflow.name }}\nMessage Error : {{ $json.execution.error.message }}\nLast Node Executed : {{ $json.execution.lastNodeExecuted }}",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "905dca04-5997-4e3a-9c66-12fa73eef658",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6880,
        2560
      ],
      "parameters": {
        "color": 3,
        "width": 672,
        "height": 208,
        "content": "## Error Detector\nDetect error\nSend notification on slack"
      },
      "typeVersion": 1
    },
    {
      "id": "6201eaee-cd17-4908-8157-bc7a4afb4117",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4336,
        736
      ],
      "parameters": {
        "width": 656,
        "height": 1760,
        "content": "# \ud83c\udfaf AI-Powered Cold Email Sequence (3 Touchpoints)\n\nAutomated B2B outreach with smart scheduling, AI personalization, and reply detection.\n\n## \u2728 Features\n\n- \u2705 3-email sequence with optimal timing (Tue/Wed/Thu 9AM)\n- \u2705 AI-powered personalization (adapts to sector, role, company)\n- \u2705 Bilingual support (FR/EN auto-detected)\n- \u2705 Reply detection \u2192 auto-stops sequence\n- \u2705 Spam prevention (randomized sending times)\n- \u2705 Full tracking in Google Sheets\n- \u2705 Slack notifications for hot leads\n\n## \ud83d\ude80 Quick Start\n\n1. **Import workflow** to n8n\n2. **Copy Google Sheet template** https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/copy\n\n3. **Configure credentials**: Gmail, Sheets, OpenAI, Slack\n4. **Update \"Entreprise Description\"** with your company info\n5. **Add prospects** to Sheet \u2192 automation starts!\n\n## \ud83d\udcca Expected Results\n\n- 10-15% reply rate (vs 3-8% for generic emails)\n- 2-5 hot leads per 30 prospects\n- Setup time: 30 minutes\n- Cost: ~$0.50 per 100 emails (OpenAI API)\n\n## \u2699\ufe0f Customization\n\n### Change sending times\nEdit `Time Planning` code:\n```javascript\nconst SEND_HOUR = 9;  // Change to your preferred hour\nconst OFFSETS = [0, 3, 7];  // Days between emails\n```\n\n### Modify email tone\nEdit prompts in `Agent` nodes to match your brand voice.\n\n### Add more touchpoints\nDuplicate Email 3 section, adjust timing, update Google Sheet columns.\n\n## \ud83d\udee0\ufe0f Requirements\n\n- n8n (self-hosted or cloud)\n- Google account (free)\n- Gmail account (free)\n- OpenAI API key (~$5/month for 1000 prospects)\n- Slack workspace (optional, for notifications)\n\n\n## \ud83d\udcac Support\n\nQuestions? maxime@b2bleader.fr  \nOr comment on the n8n template page.\n\n## \ud83d\ude4f Credits\n\nCreated by Maxime | B2B Lead Generation Specialist  \n\ud83d\udcbc Need custom implementation? maxime@b2bleader.fr  "
      },
      "typeVersion": 1
    },
    {
      "id": "dd727abb-468a-4555-8127-ec58dabde510",
      "name": "Update Email 1 Send",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        7488,
        1296
      ],
      "parameters": {
        "columns": {
          "value": {
            "id": "=",
            "Email": "={{ $json.to }}",
            "email1_Statut": "=Sent at {{ $now.toISO() }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Pr\u00e9nom",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Pr\u00e9nom",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Nom",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Nom",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Poste",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Poste",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Entreprise",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Entreprise",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Secteur",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Secteur",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Taille",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Taille",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LinkedIn URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LinkedIn URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email1_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email1_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email2_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email2_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email3_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email3_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email1_Statut",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email1_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email2_Statut",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email2_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email3_Statut",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email3_Statut",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Statut Prospect",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Statut Prospect",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit#gid=0",
          "cachedResultName": "Feuille 1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/12BFUMijzPfAuYuIHvgyKAvXw5MF6cQUtOpZ2VEoe84g/edit?usp=drivesdk",
          "cachedResultName": "Data Training 3 touchpoint"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "18e90644-4f46-46ee-b32c-ee3601fc7c2f",
      "name": "Wait Until Time planning Email 2",
      "type": "n8n-nodes-base.wait",
      "position": [
        7536,
        1488
      ],
      "parameters": {
        "resume": "specificTime",
        "dateTime": "={{ $('Smart Time Planning').item.json.email2_at }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "5edf0b66-9279-4df3-aac7-145a522027a7",
      "name": "Wait Until Time planning Email 1",
      "type": "n8n-nodes-base.wait",
      "position": [
        6240,
        1296
      ],
      "parameters": {
        "resume": "specificTime",
        "dateTime": "={{ $('Smart Time Planning').item.json.email1_at }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "3dd0167a-0d23-48ff-9402-093ed738178b",
      "name": "Wait Until Time planning Email 3",
      "type": "n8n-nodes-base.wait",
      "position": [
        7936,
        1920
      ],
      "parameters": {
        "resume": "specificTime",
        "dateTime": "={{ $('Smart Time Planning').item.json.email3_at }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "3c1c537f-1314-4789-ab60-376d78045a5c",
      "name": "Mapping Output",
      "type": "n8n-nodes-base.code",
      "position": [
        7744,
        2160
      ],
      "parameters": {
        "jsCode": "// On part de l'output de l'agent\nconst items = $input.all();\n\nreturn items.map(item => {\n  // Champ o\u00f9 l'agent a mis son JSON en texte\n  // Adapte ici le nom si ce n'est pas \"response\"\n  const raw = item.json.response || item.json.output || item.json.result || item.json.data;\n\n  // On parse la string JSON\n  const parsed = JSON.parse(raw);\n\n  // On renvoie un item propre avec les bons champs\n  return {\n    json: parsed,\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e0bdc947-dfb2-4e3d-b78d-0ebe411399e1",
      "name": "Mapping Output1",
      "type": "n8n-nodes-base.code",
      "position": [
        7600,
        1728
      ],
      "parameters": {
        "jsCode": "// On part de l'output de l'agent\nconst items = $input.all();\n\nreturn items.map(item => {\n  // Champ o\u00f9 l'agent a mis son JSON en texte\n  // Adapte ici le nom si ce n'est pas \"response\"\n  const raw = item.json.response || item.json.output || item.json.result || item.json.data;\n\n  // On parse la string JSON\n  const parsed = JSON.parse(raw);\n\n  // On renvoie un item propre avec les bons champs\n  return {\n    json: parsed,\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "5021296c-63aa-4b2a-b1b6-00f2981d3651",
      "name": "Mapping Output2",
      "type": "n8n-nodes-base.code",
      "position": [
        7200,
        1296
      ],
      "parameters": {
        "jsCode": "// On part de l'output de l'agent\nconst items = $input.all();\n\nreturn items.map(item => {\n  // Champ o\u00f9 l'agent a mis son JSON en texte\n  // Adapte ici le nom si ce n'est pas \"response\"\n  const raw = item.json.response || item.json.output || item.json.result || item.json.data;\n\n  // On parse la string JSON\n  const parsed = JSON.parse(raw);\n\n  // On renvoie un item propre avec les bons champs\n  return {\n    json: parsed,\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "da466e6a-035e-43cb-90a5-29cea1c5c035",
      "name": "Smart Time Planning",
      "type": "n8n-nodes-base.code",
      "position": [
        5824,
        1296
      ],
      "parameters": {
        "jsCode": "// YOUR_AWS_SECRET_KEY_HERE======\n// TIME PLANNING - Cold Email Sequence\n// Objectif : J0, J+3, J+5/7 (avec contraintes jours & random)\n// YOUR_AWS_SECRET_KEY_HERE======\nconst items = $input.all();\n\n// Configuration de base\nconst OFFSETS = [0, 3, 6];  // J0, J+3, J+6 (\u2248 J5\u20137 selon les jours autoris\u00e9s)\nconst MIN_GAP_DAYS = 2;     // au moins 2 jours entre chaque email\nconst SEND_HOUR = 9;\nconst SEND_MIN = 0;\nconst RANDOMIZE = true;\nconst MAX_RANDOM_MIN = 120; // 0\u2013120 min \u2192 9h\u201311h\n\nconst NOW = new Date();\n\n// Jours autoris\u00e9s : mardi (2), mercredi (3), jeudi (4)\nfunction isAllowedDay(date) {\n  const day = date.getDay();\n  return day === 2 || day === 3 || day === 4;\n}\n\nfunction moveToNextAllowedDay(date) {\n  let d = new Date(date);\n  let attempts = 0;\n  while (!isAllowedDay(d) && attempts < 10) {\n    d.setDate(d.getDate() + 1);\n    attempts++;\n  }\n  if (attempts >= 10) throw new Error('No allowed day found');\n  return d;\n}\n\nfunction addDays(date, days) {\n  const d = new Date(date);\n  d.setDate(d.getDate() + days);\n  return d;\n}\n\nfunction setTime(date, hour, min) {\n  const d = new Date(date);\n  d.setHours(hour, min, 0, 0);\n  return d;\n}\n\n// pseudo-random stable par prospect + index d'email\nfunction getRandomOffset(seed, max) {\n  if (!RANDOMIZE) return 0;\n  let hash = 0;\n  for (let i = 0; i < seed.length; i++) {\n    hash = ((hash << 5) - hash) + seed.charCodeAt(i);\n    hash = hash & hash;\n  }\n  return Math.abs(hash) % max;\n}\n\nfunction diffInDays(a, b) {\n  const msPerDay = 24 * 60 * 60 * 1000;\n  return Math.floor((a - b) / msPerDay);\n}\n\nreturn items.map(item => {\n  const json = item.json;\n  const createdAt = json.created_at || NOW.toISOString();\n  const created = new Date(createdAt);\n\n  const baseSeed = json.Email || String(json.id || NOW.getTime());\n  const result = { ...json };\n\n  let prevSend = null;\n\n  OFFSETS.forEach((offsetDays, index) => {\n    // 1) base J+offset\n    let target = addDays(created, offsetDays);\n\n    // 2) si on a d\u00e9j\u00e0 envoy\u00e9 un email, on impose un gap minimum\n    if (prevSend) {\n      const minNextDate = addDays(prevSend, MIN_GAP_DAYS);\n      if (target < minNextDate) {\n        target = minNextDate;\n      }\n    }\n\n    // 3) respecter les jours autoris\u00e9s (mar/mer/jeu)\n    target = moveToNextAllowedDay(target);\n\n    // 4) heure de base 9h00\n    target = setTime(target, SEND_HOUR, SEND_MIN);\n\n    // 5) randomiser l'heure pour cet email\n    const randomMin = getRandomOffset(baseSeed + '_' + (index + 1), MAX_RANDOM_MIN);\n    if (RANDOMIZE) {\n      target.setMinutes(target.getMinutes() + randomMin);\n    }\n\n    // 6) s'assurer que la date est dans le futur\n    if (target <= NOW) {\n      let future = addDays(NOW, 1);\n      future = moveToNextAllowedDay(future);\n      future = setTime(future, SEND_HOUR, SEND_MIN);\n      const futureRandom = getRandomOffset(baseSeed + '_future_' + (index + 1), MAX_RANDOM_MIN);\n      if (RANDOMIZE) {\n        future.setMinutes(future.getMinutes() + futureRandom);\n      }\n      target = future;\n    }\n\n    result[`email${index + 1}_at`] = target.toISOString();\n    prevSend = target;\n  });\n\n  return { json: result };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "0aee5a3e-7ec4-4734-bb08-47e901d6ada3",
      "name": "Agent IA : final follow-up",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        7392,
        2160
      ],
      "parameters": {
        "text": "==Prospect profile:\n- First Name: {{ $json[\"First Name\"] }}\n- Last Name: {{ $json[\"Last Name\"] }}\n- Job title: {{ $json.Job_title }}\n- Company: {{ $json.company }}\n- Company size (employees): {{ $json[\"company size\"] }}\n- Sector: {{ $json.Sector }}\n- LinkedIn URL: {{ $json[\"LinkedIn URL\"] }}\n- Email: {{ $json.Email }}\n\nSender / offer:\n- Sender name: {{ $json.senderName }}\n- Sender company: {{ $json.companyName }}\n- Product / service description: {{ $json[\"Description of the companies or product\"] || \"Not provided\" }}\n\nSequence status:\n- Email 1 sent at (ISO): {{ $json.email1_date || \"unknown\" }}\n- Email 1 status: {{ $json.email1_Statut || \"unknown\" }}\n- Email 2 sent at (ISO): {{ $json.email2_date || \"unknown\" }}\n- Email 2 status: {{ $json.email2_Statut || \"unknown\" }}\n- Reply received: {{ $json.has_replied || \"no\" }}\n\nTiming:\n- Email 3 scheduled at (ISO): {{ $json.email3_at }}\n",
        "options": {
          "systemMessage": "You are an expert in final follow-up emails for B2B cold outreach sequences.\n\nCONTEXT\nThis is Email 3, the third and LAST email in the sequence.\nYou know:\n- The prospect profile.\n- The sender\u2019s product / value proposition.\n- When Emails 1 and 2 were sent.\n- Status indicators for those emails (e.g. email1_Statut, email2_Statut, if provided).\n- Whether any reply has been received (has_replied).\n- When Email 3 is scheduled (email3_at).\n\nYOUR GOAL\n- Send a final, respectful follow-up that maximizes the chance of a reply,\n- while protecting the long-term relationship and not creating pressure,\n- then return a JSON summary with `to`, `subject`, and `message_html`.\n\nINPUT DATA\nYou receive:\n- Prospect data: First Name, Last Name, Job_title, company size, Sector, LinkedIn URL, Email.\n- Sender data: senderName, companyName, \"Description of the companies or product\".\n- Sequence status:\n  - email1_date, email2_date,\n  - email1_Statut, email2_Statut (if present),\n  - has_replied (yes/no),\n  - email3_at.\n\nSTRATEGY\n- If one of the previous emails appears to have been opened but no reply:\n  - Assume there might be some interest, but low priority.\n  - Highlight ONE strong, concrete idea: a very simple use case, result, or small business case.\n- If no emails appear to have been opened (or status is unknown):\n  - Go straight to the core benefit in a very clear way.\n  - Summarize in one sentence what changes for the prospect if they use the solution.\n- In all cases:\n  - Make it clear, explicitly or implicitly, that this is the last follow-up.\n  - Use a very light CTA:\n    - e.g. \u201ca quick yes/no will help me know whether to close this on my side\u201d,\n    - or offer a short call only if they are interested.\n\nRESEARCH (OPTIONAL)\n- If web / HTTP tools are available, you may:\n  - check a typical trend or challenge in the prospect\u2019s sector or role,\n  - use it to support one short sentence that strengthens relevance.\n\nEMAIL 3 REQUIREMENTS\n- Length: 60\u2013100 words.\n- Start with one sentence of context (\u201cI\u2019m sending you a last follow-up regarding\u2026\u201d).\n- Focus on ONE key benefit or usage scenario, concrete and specific.\n- End with a very simple CTA:\n  - either for a short conversation,\n  - or to let you know it\u2019s not a priority / not the right time.\n- Tone:\n  - warm, respectful, zero pressure or guilt.\n\nLANGUAGE\n- If the prospect appears French-speaking \u2192 write the email in FRENCH.\n- Otherwise \u2192 write the email in ENGLISH.\n\nGMAIL TOOL USAGE\n1) After deciding on the subject and writing the HTML content of the email:\n   - You MUST call the \u201cGmail Tool - Send Email 3\u201d with:\n     - `to` = the prospect\u2019s Email,\n     - `subject` = the subject line you wrote,\n     - `message_html` = the HTML body you wrote.\n2) Call this tool exactly once per execution.\n\nFINAL OUTPUT FORMAT\nAfter calling the Gmail tool, return a single JSON object (no markdown):\n\n{\n  \"to\": \"email_of_the_prospect\",\n  \"subject\": \"Subject of email 3\",\n  \"message_html\": \"<p>Email 3 content in simple HTML</p>\"\n}\n"
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "bfa4d994-cb57-4e29-9321-771415379789",
      "name": "Agent IA : Follow",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        7136,
        1728
      ],
      "parameters": {
        "text": "==Prospect profile:\n- First Name: {{ $json[\"First Name\"] }}\n- Last Name: {{ $json[\"Last Name\"] }}\n- Job title: {{ $json.Job_title }}\n- Company: {{ $json.company }}\n- Company size (employees): {{ $json[\"company size\"] }}\n- Sector: {{ $json.Sector }}\n- LinkedIn URL: {{ $json[\"LinkedIn URL\"] }}\n- Email: {{ $json.Email }}\n\nSender / offer:\n- Sender name: {{ $json.senderName }}\n- Sender company: {{ $json.companyName }}\n- Product / service description: {{ $json[\"Description of the companies or product\"] || \"Not provided\" }}\n\nSequence status:\n- Email 1 sent at (ISO): {{ $json.email1_date || \"unknown\" }}\n- Email 1 opened: {{ $json.email1_Statut || \"unknown\" }}\n- Reply received: {{ $json.has_replied || \"no\" }}\n\nTiming:\n- Email 2 scheduled at (ISO): {{ $json.email2_at }}\n",
        "options": {
          "systemMessage": "You are a specialist in B2B follow-up emails in multi-step cold outreach sequences.\n\nCONTEXT\nThis is Email 2 in a 3-step sequence.\nEmail 1 has already been sent. You know:\n- When Email 1 was sent.\n- A status or \u201copened\u201d indicator for Email 1 (if provided).\n- Whether there has been any reply so far.\n- When Email 2 is scheduled.\n\nYOUR GOAL\n- Adapt the follow-up based on the engagement with Email 1 (opened / not opened, no reply).\n- Bring NEW value or a slightly different angle versus Email 1.\n- WRITE and SEND Email 2 using the Gmail tool in this n8n workflow.\n- Then return a JSON summary with `to`, `subject`, and `message_html`.\n\nINPUT DATA\nYou receive:\n- Prospect data: First Name, Last Name, Job_title, company size, Sector, LinkedIn URL, Email.\n- Sender data: senderName, companyName, \"Description of the companies or product\".\n- Sequence status:\n  - Email 1 sent at: email1_date.\n  - Email 1 status / opened flag: email1_Statut (if present).\n  - Reply status: has_replied.\n  - Email 2 scheduled at: email2_at.\n\nFOLLOW-UP STRATEGY\n- If Email 1 appears to have been opened and there is n

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

Stop manually sending follow-ups. This workflow automates your entire cold email outreach with AI-powered personalization, smart scheduling, and automatic reply detection.

Source: https://n8n.io/workflows/11037/ — 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

Consultants, agencies, freelancers, and project managers who want to ensure proposals, emails, and tasks are followed up on time.

Google Sheets Trigger, Agent, OpenAI Chat +6
AI & RAG

Streamline customer support with a real-time, AI-powered answer engine that detects incoming support emails, classifies intent, identifies the customer’s GEO region, and generates a tailored reply rea

Slack, Gmail Trigger, OpenAI Chat +5
AI & RAG

This workflow automates invoice processing directly from your email inbox.

Gmail Trigger, HTTP Request, Agent +5
AI & RAG

AI Agents Vs AI Workflow. Uses lmChatOpenAi, gmailTrigger, gmail, gmailTool. Event-driven trigger; 30 nodes.

OpenAI Chat, Gmail Trigger, Gmail +7
AI & RAG

Streamline Facebook Messenger inbox management with an AI-powered categorization and response system. 💬⚙️ This workflow automatically classifies new messages as Lead, Query, or Spam using GPT-4, route

Error Trigger, Slack, Facebook Graph Api +5