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 →
{
"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.
gmailOAuth2googleSheetsOAuth2ApigoogleSheetsTriggerOAuth2ApiopenAiApislackOAuth2Api
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 →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Consultants, agencies, freelancers, and project managers who want to ensure proposals, emails, and tasks are followed up on time.
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
This workflow automates invoice processing directly from your email inbox.
AI Agents Vs AI Workflow. Uses lmChatOpenAi, gmailTrigger, gmail, gmailTool. Event-driven trigger; 30 nodes.
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