This workflow corresponds to n8n.io template #8464 — we link there as the canonical source.
This workflow follows the Agent → Airtable 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 →
{
"id": "6aitusMHY7wAzDBK",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Schedule AI-Formatted Google News Digests with Gmail Approval Workflow",
"tags": [],
"nodes": [
{
"id": "1dc49b96-e6c8-4c38-858b-4865238423ba",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1264,
-48
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.2
},
{
"id": "b918c267-c7bf-41e1-9396-eebd5c49fefb",
"name": "Google_news search",
"type": "n8n-nodes-serpapi.serpApi",
"position": [
-944,
-48
],
"parameters": {
"q": "AI",
"operation": "google_news",
"requestOptions": {},
"additionalFields": {}
},
"credentials": {
"serpApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "a1b70090-7672-457b-9324-ee2957ecf814",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
336,
-224
],
"parameters": {
"color": 6,
"height": 200,
"content": "### \ud83d\udc4d Send Approval Email"
},
"typeVersion": 1
},
{
"id": "eb7547c8-064f-42b3-befb-47e0ef27085f",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-448,
-240
],
"parameters": {
"color": 5,
"width": 740,
"height": 400,
"content": "### \u2709\ufe0f Prepare Approval Email"
},
"typeVersion": 1
},
{
"id": "965db1e6-1721-41ba-90a4-cf86557cac7c",
"name": "Prepare Content Review Email",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
48,
-176
],
"parameters": {
"text": "=Generate clean, modern HTML email content from the provided JSON data with these requirements:\n- Use table-based layout with inline CSS for email compatibility\n- Create card sections for each platform containing:\n \u2022 Title header (20px) \n- Structure using:\n \u2022 600px max-width container\n \u2022 20px padding between cards\n \u2022 Left-aligned text hierarchy\n \u2022 Arial/sans-serif font stack\n \u2022 Email-safe colors (#333 text, #555 secondary)\n\nInput data: {{ $('Extract Details').item.json.out.toJsonString() }}\n\nRemove ALL code blocks and comments. Output ONLY the raw HTML with:\n- Platform cards in JSON order\n- All data elements represented\n- Mobile-responsive tables\n- W3C-valid markup\n\n## Example HTML:\n<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\"\n style=\"background-color:#fbfcfe;border:1px solid #dbdfe7;border-radius:8px\">\n <tbody>\n <tr>\n <td align=\"center\" style=\"padding:24px 0\">\n <table width=\"448\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"\n style=\"width:100%;max-width:448px;background-color:#ffffff;border:1px solid #dbdfe7;border-radius:8px;padding:24px\">\n <tbody>\n <tr>\n <td\n style=\"text-align:center;padding-top:8px;font-family:Arial,sans-serif;font-size:14px;color:#7e8186\">\n <p style=\"white-space:pre-line\"></p>\n <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\"\n style=\"background-color:#f9f9f9;margin-bottom:20px;padding:20px;border-radius:8px\">\n <tbody>\n <tr>\n <th style=\"font-size:16px;padding-bottom:10px\">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</th>\n </tr>\n <tr>\n <td>Source: AP News, Author: John Doe</td>\n </tr>\n <tr>\n <td> \n <a href=\"http://apnews.com/news/lorem-ipsum\"\n target=\"_blank\">\n Read more...\n </a>\n </td>\n </tr>\n </tbody>\n </table>\n <p></p>\n </td>\n </tr>\n </tbody>\n </table>\n </td>\n </tr>\n </tbody>\n</table>",
"agent": "conversationalAgent",
"options": {},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "e76c4c98-24d9-49bf-b3b5-c58b331c1804",
"name": "Create Counter",
"type": "n8n-nodes-base.airtable",
"position": [
-1088,
256
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "appWOGRfXfKYuXtdO",
"cachedResultUrl": "https://airtable.com/appWOGRfXfKYuXtdO",
"cachedResultName": "n8n Base"
},
"table": {
"__rl": true,
"mode": "list",
"value": "tblmhlqwgnmwZd6hj",
"cachedResultUrl": "https://airtable.com/appWOGRfXfKYuXtdO/tblmhlqwgnmwZd6hj",
"cachedResultName": "n8n_Counters"
},
"columns": {
"value": {
"Counter": 0,
"Workflow ID": "={{ $workflow.id }}"
},
"schema": [
{
"id": "Workflow ID",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Workflow ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Counter",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Counter",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "create"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "b4cc767d-8826-4e9a-b113-dfc5b3b61102",
"name": "Get Counter",
"type": "n8n-nodes-base.airtable",
"position": [
-656,
272
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "appWOGRfXfKYuXtdO",
"cachedResultUrl": "https://airtable.com/appWOGRfXfKYuXtdO",
"cachedResultName": "n8n Base"
},
"table": {
"__rl": true,
"mode": "list",
"value": "tblmhlqwgnmwZd6hj",
"cachedResultUrl": "https://airtable.com/appWOGRfXfKYuXtdO/tblmhlqwgnmwZd6hj",
"cachedResultName": "n8n_Counters"
},
"options": {
"fields": [
"Counter"
]
},
"operation": "search",
"filterByFormula": "={Workflow ID} = '{{ $workflow.id }}'"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "748e5a3f-1b8b-4d9d-86aa-66833c1789b6",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1008,
-112
],
"parameters": {
"color": 6,
"width": 228,
"height": 208,
"content": "### \ud83e\uddd1\u200d\ud83e\uddb1 Get Google News"
},
"typeVersion": 1
},
{
"id": "29e9059b-c773-40ba-a36f-5fb93120065b",
"name": "Update Counter",
"type": "n8n-nodes-base.airtable",
"position": [
-208,
272
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "appWOGRfXfKYuXtdO",
"cachedResultUrl": "https://airtable.com/appWOGRfXfKYuXtdO",
"cachedResultName": "n8n Base"
},
"table": {
"__rl": true,
"mode": "list",
"value": "tblmhlqwgnmwZd6hj",
"cachedResultUrl": "https://airtable.com/appWOGRfXfKYuXtdO/tblmhlqwgnmwZd6hj",
"cachedResultName": "n8n_Counters"
},
"columns": {
"value": {
"Counter": "={{ $json.counter }}",
"Workflow ID": "={{ $workflow.id }}"
},
"schema": [
{
"id": "id",
"type": "string",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "id",
"defaultMatch": true
},
{
"id": "Workflow ID",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Workflow ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Counter",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Counter",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Workflow ID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "5500d97e-16f7-4ff3-b6b0-0c40f777f93a",
"name": "Approved?",
"type": "n8n-nodes-base.if",
"position": [
608,
-48
],
"parameters": {
"options": {
"ignoreCase": true
},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "eb6bdb7f-61ad-4821-b1b4-d72acf045af0",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.approved }}",
"rightValue": "true"
}
]
},
"looseTypeValidation": true
},
"typeVersion": 2.2
},
{
"id": "26be266b-211f-4281-9df0-9439c127187f",
"name": "gpt-4o-mini",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
80,
16
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {
"responseFormat": "text"
}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "885e1631-7112-45e7-aced-60e38a246501",
"name": "Delete Counter",
"type": "n8n-nodes-base.airtable",
"position": [
848,
288
],
"parameters": {
"id": "={{ $('Get Counter').item.json.id }}",
"base": {
"__rl": true,
"mode": "list",
"value": "appWOGRfXfKYuXtdO",
"cachedResultUrl": "https://airtable.com/appWOGRfXfKYuXtdO",
"cachedResultName": "n8n Base"
},
"table": {
"__rl": true,
"mode": "list",
"value": "tblmhlqwgnmwZd6hj",
"cachedResultUrl": "https://airtable.com/appWOGRfXfKYuXtdO/tblmhlqwgnmwZd6hj",
"cachedResultName": "n8n_Counters"
},
"operation": "deleteRecord"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "773d85a2-a25c-4596-8f1c-a30389c14cf5",
"name": "Extract Details",
"type": "n8n-nodes-base.code",
"position": [
-416,
-176
],
"parameters": {
"jsCode": "const results = $('Google_news search').first().json.news_results || [];\nconsole.log(\"results: \" + results.length);\nconst out = [];\n\nconst batchSize = 10;\n\nconst url = \"http://localhost:5678/webhook-test/news?p=\";\n\nlet indNews = Number($input.first().json.Counter);\nconsole.log(\"indNews start: \" + indNews);\nconsole.log(\"indNews after: \" + Number(indNews + batchSize));\n\nlet ind = 0;\nfor (const res of results) {\n\n if (ind >= indNews && ind < (indNews + batchSize)) {\n const src = res.source || {};\n if (src && Object.keys(src).length === 0 && src.constructor === Object) {\n const stories = res.stories || {};\n const src1 = stories[0].source || {};\n out.push({\n json: {\n position: Number(res.position),\n title: res.title,\n source: src1.name || null,\n authors: (src1.authors || []).join(\", \"), \n link2: url + res.position,\n link1: src1.link,\n }\n }); \n } else {\n out.push({\n json: {\n position: Number(res.position),\n title: res.title,\n source: src.name || null,\n authors: (src.authors || []).join(\", \"), \n link2: url + Number(res.position),\n link1: res.link,\n }\n }); \n } \n } \n ind++;\n //else {\n // break;\n //}\n}\n\nconsole.log(\"ind end: \" + Number(indNews + batchSize));\n\n// optional: sort by parent position then story pos\nout.sort((a, b) =>\n (a.json.position ?? Infinity) - (b.json.position ?? Infinity)\n);\nreturn { out: out, counter: Number(indNews + batchSize) };\n"
},
"typeVersion": 2
},
{
"id": "f18a1663-7f81-4f2d-bf31-c198ea0ea0c8",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-752,
-304
],
"parameters": {
"color": 3,
"height": 128,
"content": "### \nUse the SerpApi to obtain the latest Google News about a topic of interest.\nAbout 100 news_results are returned."
},
"typeVersion": 1
},
{
"id": "733d502d-ad00-4efb-8955-3d4fcee3357c",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1328,
-160
],
"parameters": {
"color": 3,
"height": 96,
"content": "### \nThe workflow is triggered based on its schedule (ie: once a day)."
},
"typeVersion": 1
},
{
"id": "3a309b0d-f0f4-4fda-8ec3-03e9ea8c2aeb",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1120,
416
],
"parameters": {
"color": 3,
"width": 150,
"height": 96,
"content": "### \nCreate a AirTable record to use as a counter."
},
"typeVersion": 1
},
{
"id": "2415c29a-31ee-4b3f-83e7-7132d237f367",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1152,
208
],
"parameters": {
"color": 4,
"width": 2276,
"height": 224,
"content": "### \ud83d\udd04 Manage Iteration Counter in AirTable"
},
"typeVersion": 1
},
{
"id": "89568542-67b4-46f7-8d5f-042e6c8b9ad4",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-672,
432
],
"parameters": {
"color": 3,
"width": 150,
"height": 80,
"content": "### \nGet the current counter."
},
"typeVersion": 1
},
{
"id": "4821e915-f774-403b-93cd-ea29357fa230",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-224,
432
],
"parameters": {
"color": 3,
"width": 150,
"height": 80,
"content": "### \nIncrement the counter."
},
"typeVersion": 1
},
{
"id": "5fa7edbe-38dd-44c1-86f0-8ee1f95cd78a",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
816,
432
],
"parameters": {
"color": 3,
"width": 150,
"height": 80,
"content": "### \nDelete the AirTable record."
},
"typeVersion": 1
},
{
"id": "b4620a10-5e09-4028-b398-5a066b38ce02",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
784,
160
],
"parameters": {
"color": 3,
"width": 150,
"height": 80,
"content": "### \nIf Approved:"
},
"typeVersion": 1
},
{
"id": "8ea522c5-d674-4a20-8f5d-48d2b2d9d102",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
352,
48
],
"parameters": {
"color": 3,
"width": 198,
"height": 112,
"content": "### \nIf Declined:\nprepare the next 10 news and send another Approval email."
},
"typeVersion": 1
},
{
"id": "c84ffedf-a255-4584-ac2e-f61b7d43edb1",
"name": "Sticky Note13",
"type": "n8n-nodes-base.stickyNote",
"position": [
-288,
-208
],
"parameters": {
"color": 3,
"height": 80,
"content": "### \nSome code to extract only the \"headers\" and a few details of each news."
},
"typeVersion": 1
},
{
"id": "4fca75f0-6aa5-4f16-9c1f-a831aa51716b",
"name": "Sticky Note14",
"type": "n8n-nodes-base.stickyNote",
"position": [
64,
-416
],
"parameters": {
"color": 3,
"height": 80,
"content": "### \nUse an AI Agent to generate the HTML email with the 10 news, based on our template."
},
"typeVersion": 1
},
{
"id": "85629d41-7596-44c7-b67d-e50610bb79fb",
"name": "Sticky Note15",
"type": "n8n-nodes-base.stickyNote",
"position": [
592,
-448
],
"parameters": {
"color": 3,
"height": 80,
"content": "### \nSend email and wait for Approve/Decline input."
},
"typeVersion": 1
},
{
"id": "99bc090d-150d-4050-9b60-4b3c22814700",
"name": "Sticky Note16",
"type": "n8n-nodes-base.stickyNote",
"position": [
-752,
-160
],
"parameters": {
"color": 3,
"height": 240,
"content": "### example news_results\n\n"
},
"typeVersion": 1
},
{
"id": "28de9ed5-5234-4561-a6ae-e77b29211688",
"name": "Sticky Note17",
"type": "n8n-nodes-base.stickyNote",
"position": [
-288,
-112
],
"parameters": {
"color": 3,
"height": 256,
"content": "### example extracted headers\n\n"
},
"typeVersion": 1
},
{
"id": "1e18d14e-a3cb-4c42-83e6-5e6384d8c6a8",
"name": "Sticky Note18",
"type": "n8n-nodes-base.stickyNote",
"position": [
64,
-320
],
"parameters": {
"color": 3,
"height": 112,
"content": "### example html email\n\n"
},
"typeVersion": 1
},
{
"id": "50dda84c-f8c7-4a2a-a6cb-d842711bde6b",
"name": "Sticky Note19",
"type": "n8n-nodes-base.stickyNote",
"position": [
592,
-352
],
"parameters": {
"color": 3,
"height": 288,
"content": "### example approval email\n\n"
},
"typeVersion": 1
},
{
"id": "c906fbd0-bd7f-407c-8a31-93cfe43c0ff1",
"name": "Gmail Approval News",
"type": "n8n-nodes-base.gmail",
"position": [
384,
-176
],
"parameters": {
"sendTo": "={{ $env.EMAIL_ADDRESS_ME }} ",
"message": "=Select the news article to repost:\n\n{{ $('Prepare Content Review Email').item.json.output }}",
"options": {
"limitWaitTime": {
"values": {
"resumeUnit": "minutes",
"resumeAmount": 45
}
}
},
"subject": "=\ud83d\udd25FOR APPROVAL\ud83d\udd25Latest 10 Google News",
"operation": "sendAndWait",
"approvalOptions": {
"values": {
"approvalType": "double"
}
}
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "68d37fec-62cc-4e90-b7cf-43dba0840997",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1792,
-160
],
"parameters": {
"color": 3,
"width": 416,
"height": 768,
"content": "###\nKeep up to date with the latest news about your favorite topics.\n\nSave time in selecting the next news to repost on social media or blog about, with this scheduled workflow.\n\n\n## How it works\n\n- Get the latest Google News about your topics\n- Pass them in batches of 10 to an AI Agent to be formatted in a neat HTML.\n- Send the message with the HTML results to your Gmail for approval.\n- If you Decline the batch, the next batch will be prepared and a new approval email sent.\n- The workflow uses a global counter (a record in AirTable), used also by a code node to manage the batches.\n\n## Set up steps\n\n1. Connect to SerpApi, AirTable, OpenAI and Gmail accounts\n2. Execute the workflow and check your email!\n\n## Notes\n\nYou can swap the AI Agent from OpenAI to other n8n Chat Models, or replacing the Gmail approval node with a generic \"Send message and wait for response\" node to another email provider, or replacing the AirTable counter with a Google Sheet.\n\n"
},
"typeVersion": 1
}
],
"active": true,
"settings": {
"timezone": "Europe/Riga",
"callerPolicy": "workflowsFromSameOwner",
"executionOrder": "v1"
},
"versionId": "a5f1888b-ed5e-485d-9dc9-705044fe8618",
"connections": {
"Approved?": {
"main": [
[
{
"node": "Delete Counter",
"type": "main",
"index": 0
}
],
[
{
"node": "Get Counter",
"type": "main",
"index": 0
}
]
]
},
"Get Counter": {
"main": [
[
{
"node": "Extract Details",
"type": "main",
"index": 0
}
]
]
},
"gpt-4o-mini": {
"ai_languageModel": [
[
{
"node": "Prepare Content Review Email",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Create Counter": {
"main": [
[
{
"node": "Google_news search",
"type": "main",
"index": 0
}
]
]
},
"Update Counter": {
"main": [
[
{
"node": "Prepare Content Review Email",
"type": "main",
"index": 0
}
]
]
},
"Extract Details": {
"main": [
[
{
"node": "Update Counter",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Create Counter",
"type": "main",
"index": 0
}
]
]
},
"Google_news search": {
"main": [
[
{
"node": "Get Counter",
"type": "main",
"index": 0
}
]
]
},
"Gmail Approval News": {
"main": [
[
{
"node": "Approved?",
"type": "main",
"index": 0
}
]
]
},
"Prepare Content Review Email": {
"main": [
[
{
"node": "Gmail Approval News",
"type": "main",
"index": 0
}
]
]
}
}
}
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.
airtableTokenApigmailOAuth2openAiApiserpApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
<img src="https://massimobensi.com/shared/main-img.png">
Source: https://n8n.io/workflows/8464/ — 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 automation workflow automates the creation, scripting, production, and posting of YouTube videos. It leverages AI (OpenAI), image generation (PIAPI), video rendering (Shotstack), and platform
This n8n-powered workflow automates the entire lifecycle of real estate lead intake, qualification, routing, assignment, and reporting across multiple channels. It brings WhatsApp inquiries and websit
V2 (2026) available! An intelligent, fully automated news aggregation system that collects articles from multiple sources (RSS feeds + Google Search), uses AI to classify and summarize the most import
Schedules automated vendor pricing analysis across multiple sources. Fetches delivery reliability and contract data, analyzes vendor performance using Claude AI, then distributes consolidated reports
Automate sales opportunity discovery by continuously analyzing Reddit discussions for real buying intent using AI. 🔍🤖 This workflow runs every two hours, searches Reddit posts via Google, evaluates ea