This workflow follows the Chainllm → Gmail 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 →
{
"name": "tpl-scout",
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-16,
-160
],
"id": "91c5706f-4f41-4cf9-8a6a-e2f898ee4793",
"name": "When clicking \u2018Execute workflow\u2019"
},
{
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 8
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.3,
"position": [
-16,
32
],
"id": "049ea3e7-987c-4a3d-a4ed-b830b861fd88",
"name": "Schedule Trigger"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
432,
-48
],
"id": "9712668a-fb97-4fe4-b71d-965ccdf99d58",
"name": "Loop Over Items"
},
{
"parameters": {
"url": "={{ $json.link }}",
"options": {}
},
"type": "n8n-nodes-base.rssFeedRead",
"typeVersion": 1.2,
"position": [
656,
-48
],
"id": "71e42da3-8526-4664-ba36-f188d14fde89",
"name": "RSS Read"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "0ff119b6-bdd7-476c-a960-44a1fe416a87",
"name": "source",
"value": "={{ $('Loop Over Items').item.json.source }}",
"type": "string"
},
{
"id": "bcf4522d-e462-41ef-9b65-eea474a55fab",
"name": "title",
"value": "={{ $json.title }}",
"type": "string"
},
{
"id": "8423669a-6d15-4420-a26a-fd44ecd2e310",
"name": "link",
"value": "={{ $json.link }}",
"type": "string"
},
{
"id": "9be6f9b4-c4ea-4504-9b35-d70a35df3b00",
"name": "content",
"value": "={{ $json.content.trim().slice(0, 350) }}",
"type": "string"
},
{
"id": "e381a2c2-6446-4f38-b525-44ab5c1c6482",
"name": "isoDate",
"value": "={{ $json.isoDate.split(\"T\")[0] }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
944,
-48
],
"id": "488b2162-ca21-4883-9bbc-3af63db41613",
"name": "Edit Fields"
},
{
"parameters": {
"operation": "get",
"dataTableId": {
"__rl": true,
"value": "WigBivLV8CAGPxOg",
"mode": "list",
"cachedResultName": "tpl-sout-rss-links",
"cachedResultUrl": "/projects/uabU37OVTmcWS1JM/datatables/WigBivLV8CAGPxOg"
},
"filters": {
"conditions": [
{
"keyName": "status",
"keyValue": "active"
}
]
},
"returnAll": true
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1.1,
"position": [
208,
-48
],
"id": "6e7b2ab4-654b-4914-8e13-b4af8ee29a6d",
"name": "rss links"
},
{
"parameters": {
"jsCode": "const today = new Date().toISOString().split('T')[0];\nreturn $input.all().filter(flux => flux.json.isoDate === today);"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1232,
32
],
"id": "e28458be-ff41-4de1-a1ab-98f7d6e432f6",
"name": "filter",
"alwaysOutputData": true
},
{
"parameters": {
"jsCode": "return $input.all().filter(flux => Object.keys(flux.json).length > 0);"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
656,
-336
],
"id": "b728f39d-5293-4887-9390-0066260f2909",
"name": "not empty"
},
{
"parameters": {
"promptType": "define",
"text": "=Tu analyses une veille quotidienne de flux RSS pour Tol Product Lab, studio \nd'ing\u00e9nierie produit sp\u00e9cialis\u00e9 en automatisation (n8n), d\u00e9veloppement web, \ndesign UX/UI SaaS, et fonctionnalit\u00e9s IA pour produits.\n\nVoici les entr\u00e9es du jour :\n{{ $input.all().map(item => item.json) }}\n\nPour chaque entr\u00e9e pertinente (ignore les entr\u00e9es hors sujet ou trop mineures \npour justifier un traitement), produis :\n\n1. Un r\u00e9sum\u00e9 factuel en fran\u00e7ais, 2-3 phrases maximum, sans reformulation \n promotionnelle ni jugement de valeur.\n2. Le domaine dominant, une seule valeur parmi : automatisation, ia-generative, \n dev-web, ux-design, geo-seo.\n3. 1 \u00e0 3 id\u00e9es d'angle d'article, chacune avec :\n - un titre de travail (pas d\u00e9finitif, juste une direction)\n - une justification courte : pourquoi ce sujet a une chance r\u00e9elle d'int\u00e9resser \n un lecteur francophone (PME, fondateur SaaS, indie hacker) et pas juste \n \"c'est une actu tech\"\n - le type d'article sugg\u00e9r\u00e9 parmi : opinion, tutoriel, etude-de-cas, build\n Si l'entr\u00e9e ne justifie aucun angle exploitable, laisse ce champ vide plut\u00f4t \n que de forcer une id\u00e9e artificielle.\n\nIgnore toute entr\u00e9e qui ne concerne pas directement l'automatisation, l'IA \nappliqu\u00e9e aux produits, le d\u00e9veloppement web, le design UX/UI ou le SEO/GEO.\n\nR\u00e9ponds uniquement en JSON valide, structure suivante, sans texte avant ni \napr\u00e8s :\n\n[\n {\n \"source\": \"string\",\n \"titre_original\": \"string\",\n \"lien\": \"string\",\n \"resume\": \"string\",\n \"domaine\": \"automatisation | ia-generative | dev-web | ux-design | geo-seo\",\n \"angles\": [\n {\n \"titre_travail\": \"string\",\n \"justification\": \"string\",\n \"type_suggere\": \"opinion | tutoriel | etude-de-cas | build\"\n }\n ]\n }\n]",
"messages": {
"messageValues": []
},
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.9,
"position": [
880,
-448
],
"id": "7f9ebece-3d01-4d30-ab2b-6025a18f915f",
"name": "Basic LLM Chain",
"retryOnFail": true,
"maxTries": 5,
"waitBetweenTries": 1500,
"executeOnce": true
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"typeVersion": 1.1,
"position": [
960,
-224
],
"id": "e8971644-96d7-4140-8d02-cfc23490901d",
"name": "Google Gemini Chat Model",
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "24fc6cc5-576a-41ec-be53-6ebba99ab447",
"leftValue": "={{ $json.text }}",
"rightValue": "[]",
"operator": {
"type": "string",
"operation": "notEquals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
1232,
-336
],
"id": "15539d21-1a48-475c-92eb-fba5781c8589",
"name": "sucedeed ?"
},
{
"parameters": {
"jsCode": "const response = JSON.parse($input.item.json.text);\n\nreturn response.map(item => ({...item}));"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1456,
-336
],
"id": "1ab489e3-8ad4-4d7c-8923-d7bdee51ed3c",
"name": "parser"
},
{
"parameters": {
"sendTo": "eyitolasagbohan@gmail.com",
"subject": "={{ $json.object }}",
"message": "={{ $json.emailHtml }}",
"options": {}
},
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.2,
"position": [
2128,
-144
],
"id": "a154837e-41d3-4a40-a3ed-797eff5d6ba3",
"name": "Send a message",
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"documentId": {
"__rl": true,
"value": "145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0",
"mode": "list",
"cachedResultName": "rssIdeas",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "tpl-scout",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0/edit#gid=0"
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
1680,
-432
],
"id": "49bed0e0-22de-4b3d-b10f-a2d83b8a253e",
"name": "existing rss",
"executeOnce": true,
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0",
"mode": "list",
"cachedResultName": "rssIdeas",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "tpl-scout",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/145smvpaYiKU3v8H6Ll1xMU-jXhEblX1PoQDJaztRsw0/edit#gid=0"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"source": "={{ $json.source }}",
"titre_original": "={{ $json.titre_original }}",
"lien": "={{ $json.lien }}",
"resume": "={{ $json.resume }}",
"domaine": "={{ $json.domaine }}",
"angles": "={{ $json.angles }}"
},
"matchingColumns": [],
"schema": [
{
"id": "source",
"displayName": "source",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "titre_original",
"displayName": "titre_original",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "lien",
"displayName": "lien",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "resume",
"displayName": "resume",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "domaine",
"displayName": "domaine",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "angles",
"displayName": "angles",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
2128,
-336
],
"id": "5d69e64d-7535-461b-b82b-e6e1c22e7e37",
"name": "news rss",
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 3
},
"conditions": [
{
"id": "5aeef6f2-4371-477f-ad61-432ba231fbaa",
"leftValue": "={{ Object.keys($json).length }}",
"rightValue": 0,
"operator": {
"type": "number",
"operation": "gt"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.3,
"position": [
1904,
-336
],
"id": "384459ef-f386-41b0-8512-20af44a3e2f0",
"name": "new rss ?"
},
{
"parameters": {
"jsCode": "const today = new Date().toISOString().split(\"T\")[0];\nconst rssByDomain = Object.groupBy($input.all(), (item) => item.json.domaine);\nconst domaines = Object.keys(rssByDomain);\n\nfunction blocMessageSetter(rssList) {\n const message = rssList.map(item => (\n `<h3><a href=\"${item.lien}\">${item.titre_original}</a></h3>\n <p>${item.resume}</p>\n <p><em>Source : ${item.source}</em></p>\n <ul>\n ${item.angles.map(angle => (`<li><strong>${angle.titre_travail}</strong> \u2014 ${angle.type_suggere}<br>\n <span style=\"color:#666;\">${angle.justification}</span></li>`))}\n </ul>\n <hr><br>`\n ));\n return message;\n}\n\nlet emailHtml = \"\";\nfor (const domaine of domaines){\n const rssList = rssByDomain[domaine].map(item => ({...item.json}));\n const messagePerDomain = `<h2>${domaine.toUpperCase().replace(\"-\", \" \")}</h2>${blocMessageSetter(rssList)}`;\n\n emailHtml += messagePerDomain;\n}\n\nconst object = `Veille tpl-scout \u2014 ${today} (${$input.all().length} ressources)`;\n\nreturn [{json: {emailHtml, object }}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1904,
-144
],
"id": "8e2bc056-f4db-494e-8c3a-d992f39c8e83",
"name": "email maker"
},
{
"parameters": {
"jsCode": "const existing_rss = new Set($('existing rss').all().map(rss => rss.json.lien));\n\nreturn $input.all().filter(rss => !existing_rss.has(rss.json.lien));"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1680,
-240
],
"id": "daf4d308-6302-4c02-80c3-05f779465dfd",
"name": "skip duplication",
"executeOnce": false,
"alwaysOutputData": true
}
],
"connections": {
"When clicking \u2018Execute workflow\u2019": {
"main": [
[
{
"node": "rss links",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "rss links",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "not empty",
"type": "main",
"index": 0
}
],
[
{
"node": "RSS Read",
"type": "main",
"index": 0
}
]
]
},
"RSS Read": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "filter",
"type": "main",
"index": 0
}
]
]
},
"rss links": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"filter": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"not empty": {
"main": [
[
{
"node": "Basic LLM Chain",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "Basic LLM Chain",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Basic LLM Chain": {
"main": [
[
{
"node": "sucedeed ?",
"type": "main",
"index": 0
}
]
]
},
"sucedeed ?": {
"main": [
[
{
"node": "parser",
"type": "main",
"index": 0
}
]
]
},
"parser": {
"main": [
[
{
"node": "existing rss",
"type": "main",
"index": 0
},
{
"node": "skip duplication",
"type": "main",
"index": 0
}
]
]
},
"new rss ?": {
"main": [
[
{
"node": "news rss",
"type": "main",
"index": 0
}
]
]
},
"email maker": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
},
"skip duplication": {
"main": [
[
{
"node": "email maker",
"type": "main",
"index": 0
},
{
"node": "new rss ?",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate",
"availableInMCP": false
},
"versionId": "7899bb85-058e-491a-8088-08d0d8aabac0",
"meta": {
"templateCredsSetupCompleted": true
},
"nodeGroups": [],
"id": "6BPSsL8FNqG6s3Hc",
"tags": []
}
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.
gmailOAuth2googlePalmApigoogleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
tpl-scout. Uses rssFeedRead, dataTable, chainLlm, lmChatGoogleGemini. Event-driven trigger; 18 nodes.
Source: https://github.com/tolproductlab/tpl-scout/blob/main/tpl-scout.json — 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.
This n8n workflow automates the entire lead nurturing process from initial contact through a 3-email follow-up sequence, with intelligent reply detection and personalized AI-generated content. It's de
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
This workflow runs daily to send Gemini-generated cold emails from leads stored in Google Sheets via Gmail, schedules two follow-ups based on time since sending, and continuously monitors Gmail for re
Categories Content Creation AI Automation Publishing Social Media
This workflow collects candidate applications via an n8n form, extracts resume text with Mistral AI, matches the candidate to an open role stored in Google Sheets and Google Docs, scores the fit using