# templates

name: Organize Email Attachments from Gmail to Structured Google Drive Folders
author_name: Michael Gullo
author_username: drdoom
nodes_used: ["n8n-nodes-base.googleDrive","n8n-nodes-base.gmail"]
categories: []
created_at: 2025-06-16T20:30:28.839Z
updated_at: 2025-06-16T20:30:28.839Z
url: https://n8n.io/workflows/4977
scraped_at: 2025-07-06 21:16:30
description:
  Automated Binary Data Extraction from Gmail to Google Drive Folder


  This workflow is designed to automate the process of handling emails with binary attachments. It triggers when a new email arrives in a specified Gmail account (or can be configured with a similar email trigger) and is set to download any binary attachments. The workflow then filters the email to confirm it contains binary data (attachments). If attachments are present, it proceeds to retrieve the full email details, including all binary data.

  A crucial step is the creation of a new Google Drive folder. This folder is dynamically named using the email's subject and the current timestamp, for example, "[Email Subject] - [Current Timestamp]". Following this, the workflow separates each individual attachment from the email. Finally, these attachments are uploaded into the newly created Google Drive folder, with their original filenames preserved. The overall purpose of this workflow is to automatically organize and store email attachments into a structured Google Drive folder system. This workflow is compatible with any type of binary data found in an email, as the filter is designed to detect any binary data, not just PDFs.


  How It Works

  Trigger: The workflow initiates when a new email arrives in a specified Gmail account. Alternatively, it can be configured with a similar email trigger.

  Download Attachments: The workflow is set to automatically download any binary attachments from the incoming email.

  Filter Attachments: The workflow then filters the email to confirm it contains binary data (attachments).

  Retrieve Full Email Details: If attachments are present, the workflow proceeds to retrieve the complete details of the email, including all binary data.

  Create Google Drive Folder: A new folder is created in Google Drive. This folder is dynamically named using the email's subject and the current timestamp (e.g., "[Email Subject] - [Current Timestamp]").

  Split Out Attachments: Each individual binary attachment from the email is separated into its own item within the workflow.

  Upload to Google Drive: Finally, these separated attachments are uploaded into the newly created Google Drive folder, retaining their original filenames.


  Need Help? Have Questions?
  For consulting and support, or if you have questions, please feel free to connect with me on LinkedIn  or email michael.gullo@outlook.com. 

workflow_json:
  {"id":"9rIwaQlNKOLLs6Yi","meta":{"instanceId":"6304e8877aa0fde3913b14034debe07006963fb497d63f280a91bbd75c6c24e1","templateCredsSetupCompleted":true},"name":"Email to Folder","tags":[],"nodes":[{"id":"f0c308d6-9347-441b-a78b-b25de884f942","name":"Gmail Trigger","type":"n8n-nodes-base.gmailTrigger","position":[-340,220],"parameters":{"simple":false,"filters":{},"options":{"downloadAttachments":true},"pollTimes":{"item":[{"mode":"everyMinute"}]}},"credentials":{"gmailOAuth2":{"id":"B0oVer8pX52LHrvw","name":"Gmail account 2"}},"typeVersion":1.2},{"id":"54a70814-0185-420b-a7e7-66ed811fae3c","name":"Google Drive1","type":"n8n-nodes-base.googleDrive","position":[1040,220],"parameters":{"name":"={{ $json.id }}","driveId":{"__rl":true,"mode":"list","value":"My Drive"},"options":{},"folderId":{"__rl":true,"mode":"id","value":"={{ $node[\"Create Folder\"].json.id }}"},"inputDataFieldName":"={{ $binary.keys()[0] }}"},"credentials":{"googleDriveOAuth2Api":{"id":"0Fpa71OWKyUgnl7d","name":"Google Drive account"}},"typeVersion":3},{"id":"435c21d8-7d23-447d-a081-a4991ba42a41","name":"Create Folder","type":"n8n-nodes-base.googleDrive","position":[380,160],"parameters":{"name":"=Motion - {{ $node[\"Gmail Trigger\"].json.subject || \"Untitled\" }} - {{ $now }}","driveId":{"__rl":true,"mode":"list","value":"My Drive"},"options":{},"folderId":{"__rl":true,"mode":"list","value":"root","cachedResultName":"/ (Root folder)"},"resource":"folder"},"credentials":{"googleDriveOAuth2Api":{"id":"0Fpa71OWKyUgnl7d","name":"Google Drive account"}},"executeOnce":true,"typeVersion":3},{"id":"3acb5376-3528-4a30-9612-67bd1a509adc","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-420,-20],"parameters":{"color":6,"width":1700,"height":660,"content":"Take PDF from Email and create a new folder with PDF "},"typeVersion":1},{"id":"e4aef0db-b072-4dc7-80e0-cd3658555bda","name":"Filter","type":"n8n-nodes-base.filter","position":[-120,220],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"87e927b3-4f28-4843-b2d0-cf7269437fca","operator":{"type":"object","operation":"exists","singleValue":true},"leftValue":"={{ $('Gmail Trigger').item.binary}}","rightValue":""}]}},"typeVersion":2.2},{"id":"4218230f-ccd0-4b8b-a4b3-54749ce8a738","name":"Gmail1","type":"n8n-nodes-base.gmail","position":[100,220],"webhookId":"e25bd1d4-d39f-4620-a5db-d6d3d9db6843","parameters":{"simple":false,"options":{"downloadAttachments":true},"messageId":"={{ $node[\"Gmail Trigger\"].json.id }}","operation":"get"},"credentials":{"gmailOAuth2":{"id":"B0oVer8pX52LHrvw","name":"Gmail account 2"}},"typeVersion":2.1},{"id":"833ab358-ce62-4acf-847e-0251bfb8e123","name":"Merge","type":"n8n-nodes-base.merge","position":[700,220],"parameters":{"mode":"combine","options":{},"combineBy":"combineAll"},"typeVersion":3.1},{"id":"55de30ff-40de-4b51-b5bd-0c00fbba80be","name":"Split Out","type":"n8n-nodes-base.splitOut","position":[380,360],"parameters":{"options":{"includeBinary":true},"fieldToSplitOut":"$binary"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"5d7c63e5-67f2-483d-8ebe-0c90967a1137","connections":{"Merge":{"main":[[{"node":"Google Drive1","type":"main","index":0}]]},"Filter":{"main":[[{"node":"Gmail1","type":"main","index":0}]]},"Gmail1":{"main":[[{"node":"Split Out","type":"main","index":0},{"node":"Create Folder","type":"main","index":0}]]},"Split Out":{"main":[[{"node":"Merge","type":"main","index":1}]]},"Create Folder":{"main":[[{"node":"Merge","type":"main","index":0}]]},"Gmail Trigger":{"main":[[{"node":"Filter","type":"main","index":0}]]},"Google Drive1":{"main":[[]]}}}


name: Reddit Sentiment Analysis for Apple WWDC25 with Gemini AI and Google Sheets
author_name: Zacharia Kimotho
author_username: imperolq
categories: []
created_at: 2025-06-17T06:55:47.611Z
updated_at: 2025-06-17T06:55:47.611Z
url: https://n8n.io/workflows/4980
scraped_at: 2025-07-06 21:16:30
description:
  This workflow automates sentiment analysis of Reddit posts related to Apple's WWDC25 event. It extracts data, categorizes posts, analyzes sentiment of comments, and updates a Google Sheet with the results. 

  Preliquisites
  Bright Data Account: You need a Bright Data account to scrape Reddit data. Ensure you have the correct permissions to use their API. https://brightdata.com/
  Google Sheets API Credentials: Enable the Google Sheets API in your Google Cloud project and create credentials (OAuth 2.0 Client IDs).
  Google Gemini API Credentials: You need a Gemini API key to run the sentiment analysis. Ensure you have the correct permissions to use their API. https://ai.google.dev/". You can use any other models of choice

  Setup


  Import the Workflow: Import the provided JSON workflow into your n8n instance.",
  Configure Bright Data Credentials:,
  In the 'scrap reddit' and the 'get status' nodes, in Header Parameters find the Authorization field, replace Bearer 1234 with your Bright Data API key. Apply this to every node that utilizes your Bright Data API Key.,
  Set up the Google Sheets API credentials,
         In the 'Append Sentiments' node, set up the Google Sheets API by connecting your Google Sheets account through oAuth 2 credentials. ",
  Configure the Google Gemini Credential ID,
       In the ' Sentiment Analysis per comment' node, set up the Google Gemini API by connecting your Google AI account through the API credentials. ,
  Configure Additional Parameters:,
      In the 'scrap reddit' node, modify the JSON body to adjust the search term, date, or sort method.,
     In the 'Wait' node, alter the 'Amount' to adjust the polling interval for scraping status, it is set to 15 seconds by default.,
     In the 'Text Classifier' node, customize the categories and descriptions to suit the sentiment analysis needs. Review categories such as 'WWDC events' to ensure relevancy.,
     In the 'Sentiment Analysis per comment' node, modify the system prompt template to improve context.
  customization_options

  Bright Data API parameters to adjust scraping behavior.
  Wait node duration to optimize polling.
  Text Classifier categories and descriptions.
  Sentiment Analysis system prompt. 

  Use Case Examples

  Brand Monitoring:** Track public sentiment towards Apple during and after the WWDC25 event.
  Product Feedback Analysis:** Gather insights into user reactions to new product announcements.
  Competitive Analysis:** Compare sentiment towards Apple's announcements versus competitors.
  Event Impact Assessment:** Measure the overall impact of the WWDC25 event on various aspects of Apple's business.
  Target_audiences: 
  Marketing professionals in the tech industry,
  Brand managers,
  Product managers,
  Market research analysts,
  Social media managers

  Troubleshooting: 
  Workflow fails to start.
  Check that all necessary credentials (Bright Data and Google Sheets API) are correctly configured and that the Bright Data API key is valid.
  Data scraping fails.
  Verify the Bright Data API key, ensure the dataset ID is correct, and inspect the Bright Data dashboard for any issues with the scraping job.
  Sentiment analysis is inaccurate.
  Refine the categories and descriptions in the 'Text Classifier' node. Check that you have the correct Google Gemini API key, as the original is a placeholder.
  Google Sheets are not updating.
  Ensure the Google Sheets API credentials have the necessary permissions to write to the specified spreadsheet and sheet. Check API usage limits.
  Workflow does not produce the correct output.
  Check the data connections, by clicking the connections, and looking at which data is being produced. Check all formulas for errors.

  Happy productivity!

nodes_used:
  ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest","@n8n/n8n-nodes-langchain.lmChatGoogleGemini","@n8n/n8n-nodes-langchain.textClassifier","@n8n/n8n-nodes-langchain.sentimentAnalysis"]

workflow_json:
  {"meta":{"instanceId":"db80165df40cb07c0377167c050b3f9ab0b0fb04f0e8cae0dc53f5a8527103ca","templateCredsSetupCompleted":true},"nodes":[{"id":"d003d118-f10d-401b-9b48-642294003248","name":"When clicking ‘Execute workflow’","type":"n8n-nodes-base.manualTrigger","position":[-720,-440],"parameters":{},"typeVersion":1},{"id":"69f49159-25a6-48e4-8040-20e2fd08d7e3","name":"Get status","type":"n8n-nodes-base.httpRequest","position":[-280,-440],"parameters":{"url":"=https://api.brightdata.com/datasets/v3/progress/{{ $json.snapshot_id }}","options":{},"sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer { your api key}}"}]}},"typeVersion":4.2},{"id":"17a043bf-9d13-4515-8b54-3689ff8d636b","name":"Get data","type":"n8n-nodes-base.httpRequest","position":[140,-520],"parameters":{"url":"=https://api.brightdata.com/datasets/v3/snapshot/s_mbtsa7xhm9v2pdx3l","options":{},"sendQuery":true,"sendHeaders":true,"queryParameters":{"parameters":[{"name":"format","value":"json"}]},"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer { your api key}}"}]}},"typeVersion":4.2},{"id":"420403f7-ed02-40ee-b5d7-50d949c41705","name":"Switch","type":"n8n-nodes-base.switch","position":[-80,-440],"parameters":{"rules":{"values":[{"outputKey":"ready","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"cba64afb-644f-4fb2-8f47-f5f0926a31a6","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.status }}","rightValue":"ready"}]},"renameOutput":true},{"outputKey":"running","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"36e3dcef-e634-4cdc-a1df-536b3cfbc552","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.status }}","rightValue":"running"}]},"renameOutput":true}]},"options":{}},"typeVersion":3.2},{"id":"c0bad055-e7fc-4a9e-832a-faaa1fa03a86","name":"scrap reddit","type":"n8n-nodes-base.httpRequest","position":[-500,-440],"parameters":{"url":"https://api.brightdata.com/datasets/v3/trigger","method":"POST","options":{},"jsonBody":"[\n \n  {\n    \"keyword\": \"WWDC25\",\n    \"date\": \"Past month\",\n    \"num_of_posts\": 100,\n    \"sort_by\": \"New\"\n  }\n]","sendBody":true,"sendQuery":true,"sendHeaders":true,"specifyBody":"json","queryParameters":{"parameters":[{"name":"dataset_id","value":"gd_lvz8ah06191smkebj4"},{"name":"include_errors","value":"true"},{"name":"type","value":"discover_new"},{"name":"discover_by","value":"keyword"}]},"headerParameters":{"parameters":[{"name":"Authorization","value":"=Bearer { your api key}}"}]}},"typeVersion":4.2},{"id":"7051599d-a0b4-454b-8a56-49437d43388a","name":"Wait","type":"n8n-nodes-base.wait","position":[140,-320],"webhookId":"f17e6010-2745-4e37-a4e7-d6f73f83c2aa","parameters":{"amount":15},"typeVersion":1.1},{"id":"e319d58e-bb9b-40b3-84ce-1386c2a1adac","name":"Text Classifier","type":"@n8n/n8n-nodes-langchain.textClassifier","position":[620,-320],"parameters":{"options":{},"inputText":"=Post title :{{ $json.title }}\nPost description : {{ $json.description || \" \"}}","categories":{"categories":[{"category":"WWDC events","description":"=This includes all events that relate to the company APPLE and the latest events in WWDC. This excludes anything that does not refer to apple as a company "},{"category":"other","description":"Any post that does not include APPLE company or related products."}]}},"typeVersion":1.1,"alwaysOutputData":false},{"id":"712010c8-688b-4f85-9809-a2489821e9b9","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[640,-140],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"Xp5T9q3YYxBIw2nd","name":"Google Gemini(PaLM) Api account✅"}},"typeVersion":1},{"id":"d5d29fe0-b1b5-4221-8bbd-d074247a1f8f","name":"Edit Fields","type":"n8n-nodes-base.set","position":[980,-420],"parameters":{"options":{},"assignments":{"assignments":[{"id":"72f15471-3e6a-4250-b18e-79e884d8d411","name":"post_id","type":"string","value":"={{ $json.post_id }}"},{"id":"4c66a57a-79ec-4052-b332-822860b874db","name":"url","type":"string","value":"={{ $json.url }}"},{"id":"dc42a5d6-d601-422d-b4b1-48bf3a0e9840","name":"user_posted","type":"string","value":"={{ $json.user_posted }}"},{"id":"842f3fc9-c2da-4eb6-8640-9b101531ec75","name":"title","type":"string","value":"={{ $json.title }}"},{"id":"0a52a894-955d-45c0-8bc0-33a61bb562ef","name":"description","type":"string","value":"={{ $json.description }}"},{"id":"0a7e5448-ffff-4f3c-a108-fae1974433be","name":"num_comments","type":"number","value":"={{ $json.num_comments }}"},{"id":"0d6bdbb2-4735-4103-822f-6e3dcd0d0ff2","name":"comments","type":"array","value":"={{ $json.comments }}"},{"id":"82d7814f-98a5-4b0f-aeda-e68321548bce","name":"community_description","type":"string","value":"={{ $json.community_description }}"},{"id":"1c75b988-9ac6-4715-bbdd-c80856b878aa","name":"community_name","type":"string","value":"={{ $json.community_name }}"}]}},"typeVersion":3.4},{"id":"8d937cba-f73e-4c27-b387-656057a8e38c","name":"Google Gemini Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[1500,-200],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash-lite"},"credentials":{"googlePalmApi":{"id":"Xp5T9q3YYxBIw2nd","name":"Google Gemini(PaLM) Api account✅"}},"typeVersion":1},{"id":"0bb0f19b-6879-4d1c-822d-e3cb2b66c4e4","name":"Split Out","type":"n8n-nodes-base.splitOut","position":[1140,-420],"parameters":{"options":{},"fieldToSplitOut":"comments"},"typeVersion":1},{"id":"06c2dace-86b3-4c42-82b4-2898b1c3701a","name":"Loop Over Items","type":"n8n-nodes-base.splitInBatches","position":[400,-520],"parameters":{"options":{}},"typeVersion":3},{"id":"db7d74db-cb3a-423e-be88-fb2a8d7a2439","name":"format sentiment","type":"n8n-nodes-base.set","position":[2180,-420],"parameters":{"options":{},"assignments":{"assignments":[{"id":"a7b1cb71-adcc-4b7d-a80d-a2f3fecf39e6","name":"title","type":"string","value":"={{ $('Loop Over Items').first().json.title }}"},{"id":"d6203ecb-3c36-41a5-b3c9-13b04a960317","name":"sentimentAnalysis","type":"string","value":"={{ $json.sentimentAnalysis.category }}"},{"id":"379bed7b-f754-4a61-a7e6-bfd7eb2c4430","name":"post_id","type":"string","value":"={{ $('Loop Over Items').first().json.post_id }}"},{"id":"2eb5a2b7-0c37-4162-ad5c-b63b01343161","name":"url","type":"string","value":"={{ $('Loop Over Items').first().json.url }}"},{"id":"cf66442b-5140-403d-a309-8714a19d742e","name":"description","type":"string","value":"={{ $('Loop Over Items').first().json.description }}"},{"id":"9cff7650-8a0a-4f10-b920-1915fdfae3b6","name":"community_name","type":"string","value":"={{ $('Loop Over Items').first().json.community_name }}"},{"id":"20b7a4ec-5be7-4506-b7f6-17adfd464ef2","name":"category","type":"string","value":"={{ $json.category }}"},{"id":"db43d6dc-49f6-4b1b-96c3-6d440a445aac","name":"comment","type":"string","value":"={{ $json.comment }}"}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"e7969e75-f137-4d25-97b1-918549a419e6","name":"Merge","type":"n8n-nodes-base.merge","position":[1940,-480],"parameters":{"numberInputs":6},"typeVersion":3.2},{"id":"3e19ac8e-69e3-40c7-a4a7-7076e52ed0d5","name":"Append Sentiments","type":"n8n-nodes-base.googleSheets","position":[2580,-420],"parameters":{"columns":{"value":{},"schema":[{"id":"comment","type":"string","display":true,"removed":false,"required":false,"displayName":"comment","defaultMatch":false,"canBeUsedToMatch":true},{"id":"user_commenting","type":"string","display":true,"removed":false,"required":false,"displayName":"user_commenting","defaultMatch":false,"canBeUsedToMatch":true},{"id":"url","type":"string","display":true,"removed":false,"required":false,"displayName":"url","defaultMatch":false,"canBeUsedToMatch":true},{"id":"description","type":"string","display":true,"removed":false,"required":false,"displayName":"description","defaultMatch":false,"canBeUsedToMatch":true},{"id":"title","type":"string","display":true,"removed":false,"required":false,"displayName":"title","defaultMatch":false,"canBeUsedToMatch":true},{"id":"sentimentAnalysis","type":"string","display":true,"removed":false,"required":false,"displayName":"sentimentAnalysis","defaultMatch":false,"canBeUsedToMatch":true},{"id":"post_id","type":"string","display":true,"removed":false,"required":false,"displayName":"post_id","defaultMatch":false,"canBeUsedToMatch":true},{"id":"community_name","type":"string","display":true,"removed":false,"required":false,"displayName":"community_name","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"autoMapInputData","matchingColumns":["url"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":47236189,"cachedResultUrl":"https://docs.google.com/spreadsheets/d/192dM77Cyn5Gei9GNLTRvQjmATLmKrVX3vyN03E4mW6Q/edit#gid=47236189","cachedResultName":"Reddit Comments"},"documentId":{"__rl":true,"mode":"list","value":"192dM77Cyn5Gei9GNLTRvQjmATLmKrVX3vyN03E4mW6Q","cachedResultUrl":"https://docs.google.com/spreadsheets/d/192dM77Cyn5Gei9GNLTRvQjmATLmKrVX3vyN03E4mW6Q/edit?usp=drivesdk","cachedResultName":"APPLE #WWDC25 Sentiments "}},"credentials":{"googleSheetsOAuth2Api":{"id":"ZAI2a6Qt80kX5a9s","name":"Google Sheets account✅ "}},"typeVersion":4.6},{"id":"7d73ce32-bea0-4b11-b062-f22752c2463b","name":"Sentiment Analysis per comment","type":"@n8n/n8n-nodes-langchain.sentimentAnalysis","position":[1480,-420],"parameters":{"options":{"categories":"Excited, Disappointed, Impressed, Indifferent, skeptical, Not clear","systemPromptTemplate":"You are highly intelligent and accurate sentiment analyzer. Analyze the sentiment of the provided text. Categorize it into one of the following: {categories}. Use the provided formatting instructions. Only output the JSON.\n\nYou will try as much to relate he comment to the post to try and get more context of the users sentiment"},"inputText":"=title: {{ $('Loop Over Items').first().json.title }}\n\ndescription: {{ $('Loop Over Items').first().json.description }}\n\nComments: {{ $json.comment || \" \"}}"},"typeVersion":1.1},{"id":"c96807b8-c235-4ad7-bc60-c5009fa4f770","name":"Filter","type":"n8n-nodes-base.filter","position":[2380,-420],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"acd98194-7112-4756-9b46-da360559eddb","operator":{"type":"string","operation":"notContains"},"leftValue":"={{ $json.sentimentAnalysis }}","rightValue":"Not clear"}]},"looseTypeValidation":true},"typeVersion":2.2,"alwaysOutputData":true},{"id":"26187370-e043-4e93-9d22-96172fbd9c8e","name":"No category","type":"n8n-nodes-base.set","position":[1000,-200],"parameters":{"options":{},"assignments":{"assignments":[{"id":"04e566e8-020b-44a8-9276-bc387b5a9ce7","name":"response","type":"string","value":"No category"}]}},"typeVersion":3.4},{"id":"156e304d-5493-4416-bf45-0a6ebd267948","name":"edit for Sentiment analysis","type":"n8n-nodes-base.set","position":[1300,-420],"parameters":{"options":{},"assignments":{"assignments":[{"id":"82f0938f-9286-41e7-bd12-23cf54595019","name":"comment","type":"string","value":"={{ $json.comment }}"},{"id":"fc67ea4a-6d4f-46b9-ac97-22f3701ef1a0","name":"user_commenting","type":"string","value":"={{ $json.user_commenting }}"},{"id":"157c0517-d139-4ce3-b916-9f03889d4abf","name":"url","type":"string","value":"={{ $json.url }}"},{"id":"d6e441f9-b96d-4f1d-a5ef-235b25e57690","name":"description","type":"string","value":"={{ $('Edit Fields').item.json.description }}"},{"id":"ce00e4eb-26c5-4969-995b-fbe328b49d21","name":"title","type":"string","value":"={{ $('Edit Fields').item.json.title }}"}]}},"typeVersion":3.4},{"id":"ae9b39de-488b-4cee-a011-285bd344ed50","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-540,-560],"parameters":{"width":200,"height":440,"content":"Scrap Linkedin for all relevant posts"},"typeVersion":1},{"id":"e6de27a3-09a2-4ace-9b0e-63a8d40acd3e","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-320,-560],"parameters":{"color":4,"width":380,"height":440,"content":"Get the status of the scrap, IF running, we wait for a few seconds until the results are returned"},"typeVersion":1},{"id":"b1e97d96-d03f-4bf4-8972-fb501b64cdc6","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[100,-560],"parameters":{"color":5,"width":220,"height":500,"content":"Fetch the response from the API call. This includes a list of all the reddit posts we have"},"typeVersion":1},{"id":"a161c6ea-f338-40f6-bdb8-62ddfd973db8","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[340,-620],"parameters":{"color":4,"width":200,"height":540,"content":"Loop items so as not to overwhelm the AI with multiple searched"},"typeVersion":1},{"id":"c8bc1a9c-00aa-4850-ac84-3b811de0e3b2","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[600,-440],"parameters":{"color":6,"width":300,"height":480,"content":"Text classification for only WWDC related events. We loop No category back to maintain the flow"},"typeVersion":1},{"id":"1c064180-28d5-4490-b9f8-87694eb6b3b5","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[940,-540],"parameters":{"color":4,"width":500,"height":580,"content":"Simple data transformation"},"typeVersion":1},{"id":"2d35e7a8-c43f-4363-9eab-bd6d2a343748","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[1460,-540],"parameters":{"color":2,"width":380,"height":580,"content":"Run Our Sentiment analysis via AI to understand what the users were feeling. This can be broken down into nuanced emotions to capture more details"},"typeVersion":1},{"id":"b7e25c6d-ab06-46b5-9a26-d822c3696108","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[1860,-540],"parameters":{"color":4,"width":260,"height":440,"content":"Merge the paths and sentiments"},"typeVersion":1},{"id":"9f5bdb9f-a0f8-42f5-940f-d83c364053f2","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[2140,-540],"parameters":{"width":600,"height":440,"content":"Filter only items that are of a clear sentiment and updates these to a table"},"typeVersion":1}],"connections":{"Wait":{"main":[[{"node":"Get status","type":"main","index":0}]]},"Merge":{"main":[[{"node":"format sentiment","type":"main","index":0}]]},"Filter":{"main":[[{"node":"Append Sentiments","type":"main","index":0}]]},"Switch":{"main":[[{"node":"Get data","type":"main","index":0}],[{"node":"Wait","type":"main","index":0}]]},"Get data":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Split Out":{"main":[[{"node":"edit for Sentiment analysis","type":"main","index":0}]]},"Get status":{"main":[[{"node":"Switch","type":"main","index":0}]]},"Edit Fields":{"main":[[{"node":"Split Out","type":"main","index":0}]]},"No category":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"scrap reddit":{"main":[[{"node":"Get status","type":"main","index":0}]]},"Loop Over Items":{"main":[[],[{"node":"Text Classifier","type":"main","index":0}]]},"Text Classifier":{"main":[[{"node":"Edit Fields","type":"main","index":0}],[{"node":"No category","type":"main","index":0}]]},"format sentiment":{"main":[[{"node":"Filter","type":"main","index":0}]]},"Append Sentiments":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"Text Classifier","type":"ai_languageModel","index":0}]]},"Google Gemini Chat Model1":{"ai_languageModel":[[{"node":"Sentiment Analysis per comment","type":"ai_languageModel","index":0}]]},"edit for Sentiment analysis":{"main":[[{"node":"Sentiment Analysis per comment","type":"main","index":0}]]},"Sentiment Analysis per comment":{"main":[[{"node":"Merge","type":"main","index":0}],[{"node":"Merge","type":"main","index":1}],[{"node":"Merge","type":"main","index":2}],[{"node":"Merge","type":"main","index":3}],[{"node":"Merge","type":"main","index":4}],[{"node":"Merge","type":"main","index":5}]]},"When clicking ‘Execute workflow’":{"main":[[{"node":"scrap reddit","type":"main","index":0}]]}}}


name: 3D Product Video Generator from 2D Image for E-Commerce Stores
author_name: InfyOm Technologies
author_username: infyom
categories: []
created_at: 2025-06-17T07:39:15.730Z
updated_at: 2025-06-17T07:39:15.730Z
url: https://n8n.io/workflows/4987
scraped_at: 2025-07-06 21:16:30
description:
  ✅ What problem does this workflow solve?

  Shopify and E-Commerce store owners often struggle to create engaging 3D videos from static product images. This workflow automates that entire process—from image upload to video delivery—so store owners can get professional-looking 3D videos without any manual editing or follow-up.

  ⚙️ What does this workflow do?

  Accepts a 2D product image and name via a public n8n form.
  Generates a unique slug and folder in Google Drive for the product.
  Uploads the original image to Google Drive and logs data in a spreadsheet.
  Removes the background from the image using remove.bg API.
  Uploads the cleaned image to Google Drive and updates the spreadsheet.
  Creates a 3D product video using the cleaned image via the Fal.ai API.
  Periodically checks the video creation status.
  Once completed, download the video, upload it to Google Drive, and log the link.
  Notifies the store owner via email with the video download link.

  🔧 Setup

  🟢 Google Services
  Google Drive**: Create and connect a folder where all product assets will be stored.
  Google Spreadsheet**: A spreadsheet to log the product name, original image link, cleaned image link, and final video URL.
  Gmail**: Connect Gmail to send the final notification email to the store owner.

  🔑 API Keys Required
  Remove.bg**: Get an API key from remove.bg.
  Fal.ai**: Sign up at fal.ai and obtain your API key to use the image-to-video generation service.

  🧠 How it Works

  📝 1. Product Form Submission
  A store owner submits the product name and 2D image via a public n8n form.

  🗂 2. Organize in Google Drive
  A unique slug is generated for the product.
  A new folder is created inside Google Drive using that slug.
  The original image is uploaded into the folder.

  📊 3. Record in a Spreadsheet
  The product name and original image URL are stored in a Google Sheet.

  🧹 4. Background Removal
  The uploaded image is processed through remove.bg API to eliminate noisy or cluttered backgrounds.
  The cleaned image is uploaded back into the product’s Drive folder.
  The cleaned image link is updated in the spreadsheet.

  🎥 5. Create 3D Video (via Fal.ai)
  The cleaned image is passed to the Fal.ai video generation API.
  The workflow periodically checks the status until the video is ready.

  ☁️ 6. Store Final Video
  Once the video is ready, the file is downloaded.
  The final video is uploaded into the same Google Drive folder.
  Its link is saved in the spreadsheet next to the respective product entry.

  📧 7. Notify the Store Owner
  An automated email is sent to the store owner with the video link, letting them know it's ready for use—no waiting, no manual follow-up needed.

  👤 Who can use it?

  This workflow is ideal for:
  🛍 Shopify Sellers
  🧺 E-commerce Store Owners
  📸 Product Photographers
  🎬 Marketing Teams
  🤖 Automation Enthusiasts

  If you want to automate 3D product video creation using AI—this is the no-code workflow you’ve been waiting for!

nodes_used:
  ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest","n8n-nodes-base.googleDrive","n8n-nodes-base.gmail","n8n-nodes-base.code"]

workflow_json:
  {"id":"Njfc4Qsoi6p35Bfj","meta":{"instanceId":"fcb622cbd5234c565b9b78babeaf0ea2455df9d2aad0d1adff7c1ef99583e685","templateCredsSetupCompleted":true},"name":"3D Product Video","tags":[],"nodes":[{"id":"a27f6012-7a92-436d-8c28-fa0ffca700f6","name":"Wait","type":"n8n-nodes-base.wait","position":[1120,180],"webhookId":"4d338cdb-1534-43be-97dc-070299cd6278","parameters":{"amount":40},"typeVersion":1.1},{"id":"78761c5e-dfe1-4aab-bd0f-f2812d6c0b4e","name":"On Form Submission","type":"n8n-nodes-base.formTrigger","position":[-1080,80],"webhookId":"7980414e-c599-45fe-98a7-4fd1d121154a","parameters":{"options":{},"formTitle":"Shopify 3D Product Video","formFields":{"values":[{"fieldType":"file","fieldLabel":"Product Photo","multipleFiles":false,"requiredField":true},{"fieldLabel":"Product Title","placeholder":"Product Title","requiredField":true}]},"formDescription":"Give us a product photo, title and we'll get back to you with professional marketing 3D video. "},"typeVersion":2.2},{"id":"1506bc41-d914-4031-bb47-7822c33bddcb","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1080,-160],"parameters":{"width":880,"height":140,"content":"## 3D Product Video\n\nSample Google Sheet\n- https://docs.google.com/spreadsheets/d/18k1Gq2X2J3_cbwJ9XyJoysVuhIpWhgc1cmlTKBnB3Yw/edit?gid=0#gid=0"},"typeVersion":1},{"id":"d615090d-236d-444a-add9-f9a429019088","name":"Give Access to folder","type":"n8n-nodes-base.googleDrive","position":[-420,80],"parameters":{"fileId":{"__rl":true,"mode":"id","value":"={{ $('Create Folder').item.json.id }}"},"options":{},"operation":"share","permissionsUi":{"permissionsValues":{"role":"reader","type":"anyone"}}},"credentials":{"googleDriveOAuth2Api":{"id":"aqCousOTolMFE3cy","name":"Google Drive account"}},"typeVersion":3},{"id":"29230056-71c0-4900-9d00-d017213fe856","name":"Get Image File","type":"n8n-nodes-base.code","position":[-200,80],"parameters":{"jsCode":"let results = [];\nconst items = $(\"On Form Submission\").all()\n\nfor (item of items) {\n    for (key of Object.keys(item.binary)) {\n        results.push({\n            json: {\n                fileName: item.binary[key].fileName\n            },\n            binary: {\n                data: item.binary[key],\n            }\n        });\n    }\n}\n\nreturn results;"},"executeOnce":true,"retryOnFail":true,"typeVersion":2,"alwaysOutputData":true},{"id":"ee55f4d4-475f-4220-843a-4ad8b16bbad8","name":"Upload Remove BG image","type":"n8n-nodes-base.googleDrive","position":[240,180],"parameters":{"name":"=(no-bg){{ $('Create Folder').item.json.name }}","driveId":{"__rl":true,"mode":"list","value":"My Drive"},"options":{},"folderId":{"__rl":true,"mode":"id","value":"={{ $('Create Folder').item.json.id }}"},"inputDataFieldName":"=no-bg.png"},"credentials":{"googleDriveOAuth2Api":{"id":"aqCousOTolMFE3cy","name":"Google Drive account"}},"typeVersion":3},{"id":"33180073-9abe-4a92-9f82-2486a8b58eab","name":"Extract Image ID from URL","type":"n8n-nodes-base.code","position":[680,180],"parameters":{"jsCode":"const url = $input.first().json['BG Remove Image']\n\n// Extract the ID using a regular expression\nconst match = url.match(/\\/d\\/([^/]+)/);\n\nreturn {\n  json: {\n    fileId: match ? match[1] : null,\n  },\n};"},"typeVersion":2},{"id":"88d1f349-959a-498f-8f2f-ab45d3d9b25f","name":"Upload Video","type":"n8n-nodes-base.googleDrive","position":[2220,180],"parameters":{"name":"=Video-file","driveId":{"__rl":true,"mode":"list","value":"My Drive"},"options":{},"folderId":{"__rl":true,"mode":"id","value":"={{ $('Create Folder').item.json.id }}"},"inputDataFieldName":"Video-file"},"credentials":{"googleDriveOAuth2Api":{"id":"aqCousOTolMFE3cy","name":"Google Drive account"}},"typeVersion":3},{"id":"bf26fc49-f91c-40f1-83d3-d2330f242f56","name":"Create Folder","type":"n8n-nodes-base.googleDrive","position":[-640,80],"parameters":{"name":"={{ $json.slug }}","driveId":{"__rl":true,"mode":"list","value":"My Drive"},"options":{},"folderId":{"__rl":true,"mode":"list","value":"root","cachedResultUrl":"https://drive.google.com/drive","cachedResultName":"/ (Root folder)"},"resource":"folder"},"credentials":{"googleDriveOAuth2Api":{"id":"aqCousOTolMFE3cy","name":"Google Drive account"}},"typeVersion":3},{"id":"4eadd7af-a13d-40a8-b886-71c798acc547","name":"Create Slug","type":"n8n-nodes-base.code","position":[-860,80],"parameters":{"jsCode":"const title = $json[\"Product Title\"] || \"default\";\nconst slug = title.toLowerCase().replace(/\\s+/g, '-') + '-' + Math.random().toString(36).substring(2, 8);\nreturn { slug };\n"},"typeVersion":2},{"id":"e53cab81-e81c-412a-a8c1-bf889e6ee063","name":"Create Video","type":"n8n-nodes-base.httpRequest","position":[900,180],"parameters":{"url":"https://queue.fal.run/fal-ai/kling-video/v1/standard/image-to-video","method":"POST","options":{},"sendBody":true,"sendHeaders":true,"bodyParameters":{"parameters":[{"name":"prompt","value":"A product placed on a reflective surface slowly rotates 360 degrees with dramatic studio lighting, soft shadows, and a smooth camera pan. The background is clean, minimal, and cinematic, highlighting the product’s details and elegance"},{"name":"image_url","value":"=https://drive.usercontent.google.com/download?id={{ $json.fileId }}&export=view&authuser=0"}]},"headerParameters":{"parameters":[{"name":"Authorization","value":"Key api_key"}]}},"typeVersion":4.2},{"id":"037d6b30-34fe-4fd7-918a-c7d3025b5bfe","name":"Check Video Status","type":"n8n-nodes-base.httpRequest","position":[1340,105],"parameters":{"url":"={{ $json.status_url }}","options":{},"sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Key api_key"}]}},"typeVersion":4.2},{"id":"2a74bdb2-efcb-4ede-ba3d-e0716a719c96","name":"Get Video Link","type":"n8n-nodes-base.httpRequest","position":[1780,180],"parameters":{"url":"={{ $json.response_url }}","options":{},"sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Key api_key"}]}},"typeVersion":4.2},{"id":"fbf59ebf-991e-4b77-8987-77716c06af0f","name":"Remove Image Background","type":"n8n-nodes-base.httpRequest","position":[20,180],"parameters":{"url":"https://api.remove.bg/v1.0/removebg","method":"POST","options":{"response":{"response":{"responseFormat":"file","outputPropertyName":"no-bg.png"}}},"sendBody":true,"contentType":"multipart-form-data","sendHeaders":true,"bodyParameters":{"parameters":[{"name":"size","value":"auto"},{"name":"image_file","parameterType":"formBinaryData","inputDataFieldName":"=data"}]},"headerParameters":{"parameters":[{"name":"X-API-Key","value":"api_key"}]}},"executeOnce":false,"typeVersion":4.2},{"id":"4c10c26e-3caa-45f0-bf12-9779cd82d87c","name":"Upload Original Image","type":"n8n-nodes-base.googleDrive","position":[20,-20],"parameters":{"name":"={{ $('Create Folder').item.json.name }}","driveId":{"__rl":true,"mode":"list","value":"My Drive"},"options":{},"folderId":{"__rl":true,"mode":"id","value":"={{ $('Create Folder').item.json.id }}"}},"credentials":{"googleDriveOAuth2Api":{"id":"aqCousOTolMFE3cy","name":"Google Drive account"}},"typeVersion":3},{"id":"1b9c83e7-5d77-4477-9518-d72a6c2f624a","name":"Insert New Product","type":"n8n-nodes-base.googleSheets","position":[240,-20],"parameters":{"columns":{"value":{"Slug":"={{ $('Create Slug').item.json.slug }}","Product Title":"={{ $('On Form Submission').item.json['Product Title'] }}","Original Image":"={{ $json.webViewLink }}"},"schema":[{"id":"Original Image","type":"string","display":true,"removed":false,"required":false,"displayName":"Original Image","defaultMatch":false,"canBeUsedToMatch":true},{"id":"BG Remove Image","type":"string","display":true,"removed":true,"required":false,"displayName":"BG Remove Image","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Product Title","type":"string","display":true,"removed":false,"required":false,"displayName":"Product Title","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Video Link","type":"string","display":true,"removed":true,"required":false,"displayName":"Video Link","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Slug","type":"string","display":true,"removed":false,"required":false,"displayName":"Slug","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"append","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/18k1Gq2X2J3_cbwJ9XyJoysVuhIpWhgc1cmlTKBnB3Yw/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"18k1Gq2X2J3_cbwJ9XyJoysVuhIpWhgc1cmlTKBnB3Yw","cachedResultUrl":"https://docs.google.com/spreadsheets/d/18k1Gq2X2J3_cbwJ9XyJoysVuhIpWhgc1cmlTKBnB3Yw/edit?usp=drivesdk","cachedResultName":"3D Product Video"}},"credentials":{"googleSheetsOAuth2Api":{"id":"9JjVrrcwf7D4bsa6","name":"Google Credentials"}},"typeVersion":4.5},{"id":"b3492513-e591-4106-a806-9fb1c43f513b","name":"Update Remove BG URL","type":"n8n-nodes-base.googleSheets","position":[460,180],"parameters":{"columns":{"value":{"Slug":"={{ $('Create Folder').item.json.name }}","BG Remove Image":"={{ $json.webViewLink }}"},"schema":[{"id":"Original Image","type":"string","display":true,"removed":true,"required":false,"displayName":"Original Image","defaultMatch":false,"canBeUsedToMatch":true},{"id":"BG Remove Image","type":"string","display":true,"removed":false,"required":false,"displayName":"BG Remove Image","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Product Title","type":"string","display":true,"removed":true,"required":false,"displayName":"Product Title","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Video Link","type":"string","display":true,"removed":true,"required":false,"displayName":"Video Link","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Slug","type":"string","display":true,"removed":false,"required":false,"displayName":"Slug","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["Slug"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/18k1Gq2X2J3_cbwJ9XyJoysVuhIpWhgc1cmlTKBnB3Yw/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"18k1Gq2X2J3_cbwJ9XyJoysVuhIpWhgc1cmlTKBnB3Yw","cachedResultUrl":"https://docs.google.com/spreadsheets/d/18k1Gq2X2J3_cbwJ9XyJoysVuhIpWhgc1cmlTKBnB3Yw/edit?usp=drivesdk","cachedResultName":"3D Product Video"}},"credentials":{"googleSheetsOAuth2Api":{"id":"9JjVrrcwf7D4bsa6","name":"Google Credentials"}},"typeVersion":4.5},{"id":"cbc141e9-7cf5-4c57-a4b1-d719182cb997","name":"Is In Progress","type":"n8n-nodes-base.if","position":[1560,180],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"8ada0859-b74f-4d48-ae95-30c34340e39f","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.status }}","rightValue":"IN_PROGRESS"}]}},"typeVersion":2.2},{"id":"eb09040d-f4d9-419e-be9c-361a2ef65531","name":"Convert to Binary File","type":"n8n-nodes-base.httpRequest","position":[2000,180],"parameters":{"url":"={{ $json.video.url }}","options":{"response":{"response":{"responseFormat":"file","outputPropertyName":"Video-file"}}}},"typeVersion":4.2},{"id":"b2c905dc-2743-4b5d-b850-facecd489166","name":"Update Video Link","type":"n8n-nodes-base.googleSheets","position":[2440,180],"parameters":{"columns":{"value":{"Slug":"={{ $('Create Folder').item.json.name }}","Video Link":"={{ $('Get Video Link').item.json.video.url }}"},"schema":[{"id":"Original Image","type":"string","display":true,"removed":true,"required":false,"displayName":"Original Image","defaultMatch":false,"canBeUsedToMatch":true},{"id":"BG Remove Image","type":"string","display":true,"removed":true,"required":false,"displayName":"BG Remove Image","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Product Title","type":"string","display":true,"removed":true,"required":false,"displayName":"Product Title","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Video Link","type":"string","display":true,"removed":false,"required":false,"displayName":"Video Link","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Slug","type":"string","display":true,"removed":false,"required":false,"displayName":"Slug","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["Slug"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/18k1Gq2X2J3_cbwJ9XyJoysVuhIpWhgc1cmlTKBnB3Yw/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"18k1Gq2X2J3_cbwJ9XyJoysVuhIpWhgc1cmlTKBnB3Yw","cachedResultUrl":"https://docs.google.com/spreadsheets/d/18k1Gq2X2J3_cbwJ9XyJoysVuhIpWhgc1cmlTKBnB3Yw/edit?usp=drivesdk","cachedResultName":"3D Product Video"}},"credentials":{"googleSheetsOAuth2Api":{"id":"9JjVrrcwf7D4bsa6","name":"Google Credentials"}},"typeVersion":4.5},{"id":"7adb552d-939f-42d1-b425-45b88d52aa71","name":"Send E-Mail Notification","type":"n8n-nodes-base.gmail","position":[2660,180],"webhookId":"346e7266-8fb6-4b86-9b32-2ca6c1258566","parameters":{"sendTo":"example@gmail.com","message":"=<p>Hi there! 👋</p>\n\n<p><b>We’re excited to share our latest product video with you! 🎉<b></p>\n\n<p>Watch it here to see the product video you’ll love:<br>\n<a href=\"{{ $('Get Video Link').item.json.video.url }}\">{{ $('Get Video Link').item.json.video.url }}</a></p>\n\n<p>Don’t miss out—this could be just what you’ve been looking for! ✨</p>\n\n<p><b>Thanks for being part of our community! 🙌<b></p>\n","options":{"appendAttribution":false},"subject":"Product Video"},"credentials":{"gmailOAuth2":{"id":"hLh5uexmYpuaLRC3","name":"Gmail account 2"}},"typeVersion":2.1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"51abcabc-2833-4f0d-a153-404df659bfb6","connections":{"Wait":{"main":[[{"node":"Check Video Status","type":"main","index":0}]]},"Create Slug":{"main":[[{"node":"Create Folder","type":"main","index":0}]]},"Create Video":{"main":[[{"node":"Wait","type":"main","index":0}]]},"Upload Video":{"main":[[{"node":"Update Video Link","type":"main","index":0}]]},"Create Folder":{"main":[[{"node":"Give Access to folder","type":"main","index":0}]]},"Get Image File":{"main":[[{"node":"Upload Original Image","type":"main","index":0},{"node":"Remove Image Background","type":"main","index":0}]]},"Get Video Link":{"main":[[{"node":"Convert to Binary File","type":"main","index":0}]]},"Is In Progress":{"main":[[{"node":"Wait","type":"main","index":0}],[{"node":"Get Video Link","type":"main","index":0}]]},"Update Video Link":{"main":[[{"node":"Send E-Mail Notification","type":"main","index":0}]]},"Check Video Status":{"main":[[{"node":"Is In Progress","type":"main","index":0}]]},"Insert New Product":{"main":[[]]},"On Form Submission":{"main":[[{"node":"Create Slug","type":"main","index":0}]]},"Update Remove BG URL":{"main":[[{"node":"Extract Image ID from URL","type":"main","index":0}]]},"Give Access to folder":{"main":[[{"node":"Get Image File","type":"main","index":0}]]},"Upload Original Image":{"main":[[{"node":"Insert New Product","type":"main","index":0}]]},"Convert to Binary File":{"main":[[{"node":"Upload Video","type":"main","index":0}]]},"Upload Remove BG image":{"main":[[{"node":"Update Remove BG URL","type":"main","index":0}]]},"Remove Image Background":{"main":[[{"node":"Upload Remove BG image","type":"main","index":0}]]},"Extract Image ID from URL":{"main":[[{"node":"Create Video","type":"main","index":0}]]}}}


name: Interview Scheduling Automation with Google Sheets, Calendar, Gmail & GPT-4o'
author_name: Rahul Joshi
author_username: rahul08
categories: []
created_at: 2025-06-17T09:43:54.839Z
updated_at: 2025-06-17T09:43:54.839Z
url: https://n8n.io/workflows/5001
scraped_at: 2025-07-06 21:16:30
description:
  SEO-Optimized Description:

  Streamline your interview scheduling process with this intelligent n8n automation template powered by Google Calendar, Google Sheets, and GPT-4. This workflow reads candidate information from a spreadsheet, automatically schedules interviews in Google Calendar, and sends personalized interview invitation emails—all without manual input.

  What This Template Does:

  📋 Monitors a Google Sheet for new candidate entries every minute
  🕒 Auto-selects the next available interview slot (Mon/Wed/Fri at 3 PM)
  📅 Creates a calendar invite in your Google Calendar
  ✍️ Uses GPT-4 to generate personalized emails based on candidate data
  📧 Sends the email invite with the interview link via Gmail

  Built-in logic ensures:

  Candidates never get same-day interviews
  AI-generated emails are concise, polite, and professionally formatted
  Scheduling remains conflict-free and easy to manage

  Requirements:

  Google Calendar API credentials
  Google Sheets with candidate info (Name, Email, Background)
  Gmail account with OAuth2
  Azure OpenAI API (GPT-4o recommended)

  Perfect For:

   Startups, HR teams, and recruiters looking to automate interview scheduling, eliminate back-and-forth emails, and deliver a professional candidate experience—all with zero hassle.

nodes_used:
  ["n8n-nodes-base.googleCalendar","n8n-nodes-base.gmail","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.outputParserStructured","@n8n/n8n-nodes-langchain.lmChatAzureOpenAi"]

workflow_json:
  {"id":"zQlHcVCTUpdWYRsK","meta":{"instanceId":"70da30c32dfca2c8fe2d688fa1f6bf834f1145a963b1dca87ba81a3c249f0060","templateCredsSetupCompleted":true},"name":"Google Calendar Interview Scheduler","tags":[],"nodes":[{"id":"c5a1438d-dbbf-4d43-b2b5-27e5e4a63886","name":"Google Sheets Trigger","type":"n8n-nodes-base.googleSheetsTrigger","position":[0,0],"parameters":{"options":{},"pollTimes":{"item":[{"mode":"everyMinute"}]},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1jSfGnVPscZGeZvUlvOyPxeghd870am4C3mK73xSRodU/edit#gid=0","cachedResultName":"Foglio1"},"documentId":{"__rl":true,"mode":"list","value":"1jSfGnVPscZGeZvUlvOyPxeghd870am4C3mK73xSRodU","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1jSfGnVPscZGeZvUlvOyPxeghd870am4C3mK73xSRodU/edit?usp=drivesdk","cachedResultName":"Hiring Prospects"}},"credentials":{"googleSheetsTriggerOAuth2Api":{"id":"urpUWZJ4aFXdsXZT","name":"Google Sheets Trigger account"}},"typeVersion":1},{"id":"769172ac-47bb-4da3-931c-e89b92b499a7","name":"Google Calendar","type":"n8n-nodes-base.googleCalendar","position":[440,0],"parameters":{"end":"={{ $json.endSlot }}","start":"={{ $json.nextSlot }}","calendar":{"__rl":true,"mode":"list","value":"itf.jyothiswarup@gmail.com","cachedResultName":"itf.jyothiswarup@gmail.com"},"additionalFields":{}},"credentials":{"googleCalendarOAuth2Api":{"id":"VLYIPKgE2lB0xsHf","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"659d43c2-cee0-4406-9863-bd07787cfa8d","name":"Gmail","type":"n8n-nodes-base.gmail","position":[1036,0],"webhookId":"040572a6-f9d0-4169-8ab9-ff47cf17fde7","parameters":{"sendTo":"={{ $('Google Sheets Trigger').item.json.EMAIL }}","message":"={{ $json.output.body }}","options":{},"subject":"Interview Details","emailType":"text"},"credentials":{"gmailOAuth2":{"id":"2kqgztjt88pXzt6j","name":"Gmail account"}},"typeVersion":2.1},{"id":"02f6765c-e880-4007-87e0-39d1fc57ab55","name":"Basic LLM Chain","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[660,0],"parameters":{"text":"={{ $('Google Sheets Trigger').item.json.NAME }}\n\n{{ $('Google Sheets Trigger').item.json.EDUCATIONAL}}\n\nLink for calendar: {{ $json.htmlLink }}\n\nMy name is Surya, I'm from Techdome","batching":{},"messages":{"messageValues":[{"message":"You are a helpful email writing assistant. You take the information I provide you with and write a personlised email to the candidate we are calling in for an interview. The goal is to send an email with Google Calendar Link. Be straight to the point. The email should start with a 15-20 word opening statement, then details to the link and then signature "}]},"promptType":"define","hasOutputParser":true},"typeVersion":1.7},{"id":"be63e6bc-0645-4e5f-aab8-abd4537b12b5","name":"Azure OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatAzureOpenAi","position":[688,220],"parameters":{"model":"gpt-4o","options":{}},"credentials":{"azureOpenAiApi":{"id":"uwQhp5e5gOORPt5i","name":"Azure Open AI account"}},"typeVersion":1},{"id":"3ac86b4b-67a6-4224-9356-028b409240e3","name":"Structured Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[808,220],"parameters":{"jsonSchemaExample":"{\n\t\"body\": \"\"\n}"},"typeVersion":1.2},{"id":"266dc8e1-f214-4b23-847c-dce9f95e1b58","name":"Code","type":"n8n-nodes-base.code","position":[220,0],"parameters":{"jsCode":"// n8n expects an array of objects as output\n\nconst now = new Date();\n\n// Define the free slots: Monday, Wednesday, Friday at 3:00 PM\n// JavaScript Date: 0=Sunday, 1=Monday, ..., 5=Friday, 6=Saturday\nconst slots = [\n  { day: 1, hour: 15 }, // Monday 3 PM\n  { day: 3, hour: 15 }, // Wednesday 3 PM\n  { day: 5, hour: 15 }, // Friday 3 PM\n];\n\n// Helper to get the next slot after 'now', always in the future (never today)\nfunction getNextSlot(now, slots) {\n  let minDiff = Infinity;\n  let nextSlotDate = null;\n\n  for (const slot of slots) {\n    let daysUntil = (slot.day - now.getDay() + 7) % 7;\n    // Always skip today, even if the slot time hasn't passed\n    if (daysUntil === 0) {\n      daysUntil = 7;\n    }\n\n    const slotDate = new Date(\n      now.getFullYear(),\n      now.getMonth(),\n      now.getDate() + daysUntil,\n      slot.hour,\n      0,\n      0,\n      0\n    );\n\n    if (slotDate - now < minDiff) {\n      minDiff = slotDate - now;\n      nextSlotDate = slotDate;\n    }\n  }\n\n  return nextSlotDate;\n}\n\n// Format as \"YYYY-MM-DD HH:MM:SS\"\nfunction formatDate(date) {\n  const pad = (n) => n.toString().padStart(2, '0');\n  return (\n    date.getFullYear() +\n    '-' +\n    pad(date.getMonth() + 1) +\n    '-' +\n    pad(date.getDate()) +\n    ' ' +\n    pad(date.getHours()) +\n    ':00:00'\n  );\n}\n\nconst nextSlot = getNextSlot(now, slots);\n\n// Create the end time (1 hour after start)\nconst endSlot = new Date(nextSlot.getTime() + 60 * 60 * 1000);\n\nreturn [\n  {\n    json: {\n      nextSlot: formatDate(nextSlot),\n      endSlot: formatDate(endSlot)\n    }\n  }\n];\n"},"typeVersion":2}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"22ca5597-52e0-486b-93c0-5a57979dea68","connections":{"Code":{"main":[[{"node":"Google Calendar","type":"main","index":0}]]},"Basic LLM Chain":{"main":[[{"node":"Gmail","type":"main","index":0}]]},"Google Calendar":{"main":[[{"node":"Basic LLM Chain","type":"main","index":0}]]},"Google Sheets Trigger":{"main":[[{"node":"Code","type":"main","index":0}]]},"Azure OpenAI Chat Model":{"ai_languageModel":[[{"node":"Basic LLM Chain","type":"ai_languageModel","index":0}]]},"Structured Output Parser":{"ai_outputParser":[[{"node":"Basic LLM Chain","type":"ai_outputParser","index":0}]]}}}


name: Generate AI-Powered LinkedIn Posts with Google Gemini and Gen-Imager
author_name: Evoort Solutions
author_username: evoortsolutions
categories: []
created_at: 2025-06-17T10:03:42.215Z
updated_at: 2025-06-17T10:03:42.215Z
url: https://n8n.io/workflows/5002
scraped_at: 2025-07-06 21:16:30
description:
  🚀 AI-Powered LinkedIn Post Automation

  🧩 How It Works

  This workflow automatically generates LinkedIn posts based on a user-submitted topic, including both content creation and image generation, then publishes the post to LinkedIn. Ideal for marketers, content creators, or businesses looking to streamline their social media activity, without the need for manual post creation.

  High-Level Workflow:

  Trigger: The workflow is triggered when a user submits a form with a topic for the LinkedIn post.
  Data Mapping: The topic is mapped and prepared for the AI model.
  AI Content Generation: Calls the Google Gemini AI model to generate engaging post content and a visual image prompt.
  Image Creation: Sends the image prompt to the external API, gen-imager, to generate a professional image matching the topic.
  Post Creation: Publishes the text and image to LinkedIn, automatically updating the user's feed.

  ⚙️ Set Up Steps (Quick Overview)

  🕐 Estimated Setup Time: ~10–20 minutes

  Connect Google Gemini: Set up your Google Gemini API credentials to interact with the AI model for content creation.  
  Set Up External Image API: Configure the external image generation API (gen-imager API) for visual creation based on the post prompt.
  Connect LinkedIn: Set up OAuth2 credentials to authenticate your LinkedIn account and allow publishing posts.
  Form Submission Setup: Create a simple web form for users to submit the topic for LinkedIn posts.
  Activate the Workflow: Once everything is connected, activate the workflow. It will trigger automatically upon receiving form submissions.

  💡 Important Notes:
  The flow uses Google Gemini (PaLM) for generating content based on the user's topic.
  Text to Image: The image generation process involves creating a professional, LinkedIn-appropriate image based on the post’s topic using the **gen-imager API.
  You can customize the visual elements of the posts and adjust the tone of the generated content based on preferences.

  🛠 Detailed Node Breakdown:

  On Form Submission  
     Trigger: Captures the user-submitted topic and initializes the workflow.
     Action: Start the process by gathering the topic information.

  Mapper (Field Mapping)  
     Action: Maps the captured topic to a variable that is passed along for content generation.

  AI Agent (Content Generation)  
     Action: Calls Google Gemini to generate professional LinkedIn post content and an image prompt based on the submitted topic.
     Key: Outputs content in a structured form — post text and image prompt.

  Google Gemini Chat Model  
     Action: AI model that generates actionable insights, engaging copy, and an image prompt for LinkedIn post.

  Normalizer (Data Cleanup)  
     Action: Cleans the output from the AI model to ensure the content and image prompt are correctly formatted for use in the next steps.

  Text to Image (Image Generation)  
     Action: Sends the image prompt to the gen-imager API, which returns a custom image based on the post's topic.

  Decoder (Base64 Decoding)  
     Action: Decodes the image from base64 format for easier uploading to LinkedIn.

  LinkedIn (Post Creation)  
     Action: Publishes the generated text and image to LinkedIn, automatically creating a polished post for the user’s feed.

  ⏱ Execution Time Breakdown:

  Total Estimated Execution Time**: ~15–40 seconds per workflow run.
    On Form Submission: Instant (Trigger)
    Mapper (Field Mapping): ~1–2 seconds
    AI Content Generation: ~5–10 seconds (depending on server load)
    Text to Image: ~5–15 seconds (depends on external API)
    LinkedIn Post Creation: ~2–5 seconds

  🚀 Ready to Get Started?

  Let’s get you started with automating your LinkedIn posts!  
  Create your free n8n account and set up the workflow using this link.

  📝 Notes & Customizations  
  Form Fields**: Customize the form to gather more specific information for the LinkedIn posts (like audience targeting, post category, etc.).
  Image API Customization**: Adjust the image generation prompt to fit your brand’s style, or change the color palette as needed.
  Content Tone**: The tone can be adjusted by modifying the system message sent to Google Gemini for content generation.

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.linkedIn","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatGoogleGemini"]

workflow_json:
  {"id":"vqN5q4DY1j8QQdck","meta":{"instanceId":"60c025075753afcab9f803964b4caaca9402f435deb4efafbb8e3b93b54d8752","templateCredsSetupCompleted":true},"name":"AI-Powered LinkedIn Post Automation","tags":[{"id":"TZGpFRr1DpwFbL3j","name":"LinkedIn","createdAt":"2025-05-29T11:14:22.147Z","updatedAt":"2025-05-29T11:14:22.147Z"},{"id":"QXtLNWbsCSABOTNm","name":"Digital Marketing","createdAt":"2025-05-29T11:14:57.099Z","updatedAt":"2025-05-29T11:14:57.099Z"}],"nodes":[{"id":"ab4282b8-43e9-466a-9986-70e5e449eb5e","name":"On form submission","type":"n8n-nodes-base.formTrigger","position":[0,0],"webhookId":"e06e171b-45cc-4c4f-bbc5-ffedd4d60f47","parameters":{"options":{},"formTitle":"LinkedIn Post Generator ","formFields":{"values":[{"fieldLabel":"Topic","placeholder":"Enter prompt here....","requiredField":true}]}},"typeVersion":2.2},{"id":"e593eb90-b859-499b-8b18-3f8fbe8017da","name":"Mapper","type":"n8n-nodes-base.set","position":[260,0],"parameters":{"options":{},"assignments":{"assignments":[{"id":"694a158d-53fd-425c-9a42-be4288c17ac9","name":"chatInput","type":"string","value":"={{ $json.Topic }}"}]}},"typeVersion":3.4},{"id":"c48b5989-66ed-4fe2-96a2-6b540ac87d54","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[500,0],"parameters":{"options":{"systemMessage":"=I need help creating a professional LinkedIn post for the topic: \"{{ $json.chatInput }}\". The output should include:\n\n1. **LinkedIn Post Content**:\n   - Write an engaging and informative LinkedIn post on the topic \" {{ $json.chatInput }}\".\n   - Start with an attention-grabbing hook that entices readers to read further.\n   - Provide valuable insights or actionable tips related to the topic.\n   - The tone should be professional, clear, and concise, using language that's easy to understand.\n   - End with a call to action (CTA) encouraging the audience to engage, reflect, or share their thoughts.\n   - Include relevant hashtags to increase engagement and visibility on LinkedIn. Make sure these hashtags are specific to the topic and aligned with trending keywords for LinkedIn posts.\n\n2. Image Generation Prompt:\n\nVisual Aesthetic:\nThe image should align with LinkedIn's professional and corporate atmosphere. Make sure it conveys sophistication, modernity, and relevance to the topic. Avoid overly busy designs.\n\nColor Palette:\nStick to corporate tones such as blues, whites, and grays to maintain a professional and clean look. Consider using gradients for depth or subtle contrasts to highlight key elements.\n\nImagery:\n\nFocus on visualizing the topic of the post. For AI in Business, this could involve:\n\nA futuristic office or workspace setting, highlighting cutting-edge technologies.\n\nIcons or symbols that represent data analysis, AI, or automation.\n\nVisuals of humans interacting with AI systems (e.g., robots working alongside humans or using AI tools).\n\nAbstract representations of neural networks or digital data flows.\n\nNo Text Overlay:\n\nDo not include any text in the image, ensuring it remains clean and focuses solely on the visuals.\n\nText overlays or titles are not necessary in this case to keep the professional look intact.\n\nStyle and Tone:\n\nThe design should be minimalist, modern, and sleek. Use a balanced layout with a focus on professional imagery that resonates with business-minded audiences.\n\nAvoid overly complex or distracting backgrounds—keep it clean and visually appealing.\n\nFont Style (if applicable):\n\nIf any text were used in future visuals or branding (though none should appear in this image), use clean, modern fonts like Helvetica, Arial, or Roboto—sans-serif fonts that are readable and professional.\n\nimage prompt can be like this short and simple\nA modern co-working space where AI assistants and human employees brainstorm around a digital whiteboard. The scene shows innovation and teamwork, with a multicultural group, smart gadgets, and subtle futuristic elements. Warm natural lighting and a balanced, professional layout ideal for a LinkedIn audience.\n the JSON output would look like this:\n{\n  \"post_content\": {\n    \"text\": \"The Future of AI in Business: How It is Transforming Industries 🚀\\n\\nAI in Business is no longer just a buzzword; it's revolutionizing the way businesses operate today. From improving efficiency to driving innovation, AI is an essential tool for modern companies.\\n\\nHere are some key insights on how AI in Business is shaping the future of industries:\\n1. Enhanced Data Analytics: AI helps businesses make data-driven decisions with greater accuracy.\\n2. Automation of Tasks: AI is automating repetitive tasks, improving operational efficiency.\\n3. Personalized Experiences: AI is enabling personalized customer experiences in real-time.\\n\\nIs your business ready to embrace AI in Business? Let's discuss how it can help drive growth and innovation.\\n\\n#AIinBusiness #Innovation #FutureOfWork #BusinessGrowth #TechnologyTrends #DigitalTransformation\"\n  },\n  \"image_prompt\": {\n    \"description\": \"Create an image for a LinkedIn post on the topic of AI in Business. The image should:\\n- Feature modern, sleek visuals that align with the corporate tone of LinkedIn.\\n- Visualize AI in Business through elements like a futuristic office, AI-powered systems, or human-robot collaboration.\\n- Use a professional color palette like blues, whites, and grays.\\n- The optional text overlay (if relevant) could be something like 'The Future of AI in Business' or 'Driving Innovation with AI'.\\n- The design should use clean, modern fonts that are easily readable and match the professional style of LinkedIn posts.\"\n  }\n}\n"}},"typeVersion":2},{"id":"e56b669f-caa5-435d-be77-8abf8d79d4fc","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[460,240],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"Xpxt71RcelLLFyE3","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"9af3d1f9-3085-4479-83eb-eab69050b65f","name":"Decoder","type":"n8n-nodes-base.code","position":[1460,0],"parameters":{"jsCode":"// Extract the data field (which is a string) and parse it into a JSON object\nconst dataString = $input.first().json.data;\n\n// Parse the data string into a valid JSON object\nconst dataObject = JSON.parse(dataString);\n\n// Now you can safely extract the base64 image data\nconst base64Image = dataObject.base64_img;\n\n// Decode the base64 string and create a buffer from it\nconst buffer = Buffer.from(base64Image, 'base64');\n\n// You can optionally store this buffer in a temporary file or return the buffer as-is\nreturn {\n  json: {\n    decoded_image_buffer: buffer.toString('base64'), // Returning as base64 for further processing\n    image_length: buffer.length, // Optional: To verify the size of the decoded image\n  }\n};\n"},"typeVersion":2},{"id":"8ebd423c-16da-4a44-8c96-07683fe4659f","name":"Normalizer","type":"n8n-nodes-base.code","position":[880,0],"parameters":{"jsCode":"const input = $input.first().json.output\n\nconst cleanedInput = input.replace(/```json|```/g, '').trim();\n\n// Parse the cleaned JSON\nconst parsedOutput = JSON.parse(cleanedInput);\n\n// Extract the `post_content.text` and `image_prompt.description` details\nconst postContent = parsedOutput.post_content.text;\nconst imagePrompt = parsedOutput.image_prompt.description;\n\n// Prepare the final output in the desired JSON structure\nreturn {\n  post_content: postContent,\n  image_prompt: imagePrompt\n};"},"typeVersion":2},{"id":"bb7ac25e-e584-4737-9aa2-4f7e7ffb9971","name":"Text to image","type":"n8n-nodes-base.httpRequest","position":[1180,0],"parameters":{"url":"https://gen-imager.p.rapidapi.com/genimager/index.php","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","sendHeaders":true,"bodyParameters":{"parameters":[{"name":"Prompt","value":"={{ $json.image_prompt }}"}]},"headerParameters":{"parameters":[{"name":"x-rapidapi-host","value":"gen-imager.p.rapidapi.com"},{"name":"x-rapidapi-key","value":"your gen-imager rapid api key"}]}},"typeVersion":4.2},{"id":"5feeaf28-1efd-4624-ba09-947133b247ec","name":"LinkedIn","type":"n8n-nodes-base.linkedIn","position":[1760,0],"parameters":{"text":"={{ $('Normalizer').item.json.post_content }}","additionalFields":{},"binaryPropertyName":"={{ $json.decoded_image_buffer }}","shareMediaCategory":"IMAGE"},"typeVersion":1},{"id":"a984e557-1239-4905-bca3-ed6040cef517","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-500,-300],"parameters":{"height":700,"content":"> **AI-Powered LinkedIn Post Automation**  \n>  \n> This workflow automates the process of creating LinkedIn posts based on user-submitted topics. It generates both **content** and a **professional image** using AI, and automatically publishes the post to LinkedIn.\n>  \n> - **Trigger**: Activated when a user submits a form with a topic for a LinkedIn post.\n> - **AI Content Generation**: Uses Google Gemini to generate an engaging post and image prompt.\n> - **Image Creation**: The prompt is sent to **[gen-imager API](https://rapidapi.com/PrineshPatel/api/gen-imager)** for image generation.\n> - **Post Creation**: The generated text and image are posted directly to LinkedIn.\n>  \n> **Key Features**:  \n> 1. Automated post creation for LinkedIn.  \n> 2. Professional image generation with an AI-driven prompt.  \n> 3. Instant publishing to your LinkedIn feed.\n"},"typeVersion":1},{"id":"a402ed2c-1970-4e4d-b78d-618d335d6034","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-60,-160],"parameters":{"height":320,"content":"**On Form Submission**  \n> Triggered when a user submits a topic through the form. This starts the workflow and captures the topic to generate a LinkedIn post.\n  "},"typeVersion":1},{"id":"8a027b14-4b84-4efb-b3df-94c29f59ead2","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[200,-160],"parameters":{"height":320,"content":"> **Mapper**  \n> Maps the user-submitted topic from the form and prepares it for the next step by assigning it to a variable (`chatInput`).\n"},"typeVersion":1},{"id":"dcb0b306-9b48-4db9-8bdf-8b39f163d102","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[480,-160],"parameters":{"width":300,"height":320,"content":"**AI Agent**  \n> Uses the **Google Gemini** model to generate professional content for the LinkedIn post, including text and an image prompt based on the given topic.\n"},"typeVersion":1},{"id":"edc1b46c-2ba7-4de9-bcfd-11bb3f750d17","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[820,-160],"parameters":{"height":320,"content":" **Normalizer**  \n> Cleans and formats the AI-generated output into a readable structure for the next steps, extracting both the post text and image prompt.\n"},"typeVersion":1},{"id":"17a43c84-0dbf-4217-bb11-486a58d62c7a","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1100,-160],"parameters":{"height":320,"content":"> **Text to Image**  \n> Sends the image prompt to the **[gen-imager API](https://rapidapi.com/PrineshPatel/api/gen-imager)** to generate a professional image for the LinkedIn post based on the given topic.\n"},"typeVersion":1},{"id":"8c1fa58f-c4c1-4751-8126-814ff0c9dfd1","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[1380,-160],"parameters":{"height":320,"content":"**Decoder**  \n> Decodes the image from its base64 format into a usable binary buffer that can be uploaded to LinkedIn.\n"},"typeVersion":1},{"id":"e1e20396-2fa5-4574-bab6-eb6dbad793fe","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[1680,-160],"parameters":{"height":320,"content":"> **LinkedIn**  \n> Publishes the generated LinkedIn post, including the text and the newly created image, directly to the user's LinkedIn profile.\n"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"398b0e27-ca1f-45e2-a18e-f86b387d8bb2","connections":{"Mapper":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Decoder":{"main":[[{"node":"LinkedIn","type":"main","index":0}]]},"AI Agent":{"main":[[{"node":"Normalizer","type":"main","index":0}]]},"Normalizer":{"main":[[{"node":"Text to image","type":"main","index":0}]]},"Text to image":{"main":[[{"node":"Decoder","type":"main","index":0}]]},"On form submission":{"main":[[{"node":"Mapper","type":"main","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]}}}


name: Daily Email Digest with AI Summarization using Gmail, OpenRouter and LangChain
author_name: Roshan Ramani
author_username: rawsun007
categories: []
created_at: 2025-06-17T11:06:08.281Z
updated_at: 2025-06-17T11:06:08.281Z
url: https://n8n.io/workflows/5003
scraped_at: 2025-07-06 21:16:30
description:
  📧 Morning Mail Summary Ai Agent

  Simplify your mornings with this automated email summary workflow in n8n, designed for teams and individuals who want a quick, actionable snapshot of their inbox—every day, at a glance.

  📌 Features
  Fully Automated**: Triggers daily at 8 AM IST  
  Targeted Extraction**: Fetches messages from specific senders with dynamic date filtering  
  Structured Data Aggregation**: Pulls key fields (sender, recipients, snippet)  
  AI-Powered Summarization**: Uses LangChain + OpenRouter to generate:  
    Insightful summaries  
    Highlighted issues  
    Assigned action items  
  Memory-Enhanced Context**: Maintains continuity across days  
  Stylish HTML Email Output**: Responsive design with:  
    Summary section  
    Action items  
    Branded footer  
  Team-Ready Sharing**: Auto-distributes to team with CC support  

  🛠️ How It Works
  Trigger: Daily schedule in n8n  
  Fetch: Retrieves last 24h emails from target sender  
  Organize: Aggregates email metadata  
  Summarize: AI agent produces structured report:  
     Key updates  
     Critical issues  
     Actionable tasks  
  Send: Emails digest to team  

  🎯 Ideal For
  Project managers needing stakeholder briefings  
  Customer success teams tracking communications  
  Leadership staying informed efficiently  
  Anyone streamlining email review  

  📦 Included Resources
  Complete n8n workflow JSON (6 nodes)  
  Prompt template for structured summarization (Summary, Issues, Actions, Follow‑Ups).
  -Styled HTML email template, with responsive design and branding sections.

  🆓 Get Started

  Import JSON into n8n  
  Configure:  
     Gmail / OpenRouter credentials  
     Recipient lists  
     Custom prompts  
  Modify freely for your use case  

  ⭐ Benefits

  ⏳ Time saved: Skip inbox digging  
  🔍 Focus: See only what matters  
  ✨ Clarity: Structured tasks & deadlines  
  🔄 Consistency: Daily alignment for teams  

nodes_used:
  ["n8n-nodes-base.gmail","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.memoryBufferWindow","@n8n/n8n-nodes-langchain.lmChatOpenRouter"]

workflow_json:
  {"id":"lPYVaz2xbN5zFDIL","meta":{"instanceId":"cbc68f6c587084f6fe53914a07ed22d475640cb7a6f4ade193e6f0c6d7a06ce8"},"name":"My workflow","tags":[{"id":"DaQLpYItTEM2y8Gt","name":"Product","createdAt":"2025-06-17T10:48:17.486Z","updatedAt":"2025-06-17T10:48:17.486Z"},{"id":"6X5c5WbCRWtxJbl2","name":"AI","createdAt":"2025-06-17T10:48:17.367Z","updatedAt":"2025-06-17T10:48:17.367Z"},{"id":"ycHNTMiM8vy98zu1","name":"Building blocks","createdAt":"2025-06-17T10:48:17.563Z","updatedAt":"2025-06-17T10:48:17.563Z"},{"id":"UJ6au0mv063gOupq","name":"Finance","createdAt":"2025-06-17T10:48:17.583Z","updatedAt":"2025-06-17T10:48:17.583Z"},{"id":"CaWiGPzJpyfUHdxp","name":"IT Ops","createdAt":"2025-06-17T10:48:17.388Z","updatedAt":"2025-06-17T10:48:17.388Z"},{"id":"6Uolue5XigSZ2IYx","name":"OpenAI","createdAt":"2025-06-17T10:48:17.508Z","updatedAt":"2025-06-17T10:48:17.508Z"},{"id":"nA8GpDM4XoG5aJ0A","name":"Marketing","createdAt":"2025-06-17T10:48:17.532Z","updatedAt":"2025-06-17T10:48:17.532Z"},{"id":"J4gTJX9lSPm3wByF","name":"Support","createdAt":"2025-06-17T10:48:17.464Z","updatedAt":"2025-06-17T10:48:17.464Z"},{"id":"i294x7TPtUQgJkmv","name":"HR","createdAt":"2025-06-17T10:48:17.426Z","updatedAt":"2025-06-17T10:48:17.426Z"}],"nodes":[{"id":"895894ff-943d-4cd0-9311-791b35e4ca57","name":"Fetch Emails - Past 24 Hours","type":"n8n-nodes-base.gmail","position":[-800,180],"webhookId":"20f1d11d-8a69-43f3-9323-33eaf1b3b600","parameters":{"filters":{"q":"={{ \n (() => {\n const yesterday = new Date();\n yesterday.setDate(yesterday.getDate() - 1);\n return `isb.quantana@quantana.in after:${yesterday.getFullYear()}/${(yesterday.getMonth() + 1).toString().padStart(2, '0')}/${yesterday.getDate().toString().padStart(2, '0')}`;\n })()\n}}"},"operation":"getAll","returnAll":true},"typeVersion":2.1},{"id":"5518a4f6-5d68-46bf-b29b-1830379917a9","name":"Organize Email Data - Morning","type":"n8n-nodes-base.aggregate","position":[-580,180],"parameters":{"include":"specifiedFields","options":{},"aggregate":"aggregateAllItemData","fieldsToInclude":"id, From, To, CC, snippet"},"typeVersion":1},{"id":"d5598f1c-86a2-49b3-b659-bba4d063878c","name":"Send Summary - Morning","type":"n8n-nodes-base.gmail","position":[16,180],"webhookId":"83f2aeb9-7b6c-4336-b5ed-8acfcd259850","parameters":{"sendTo":"team-email@example.com","message":"=<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Email Summary - isbonline@quantana.in</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 0;\n background-color: #f9f9f9;\n color: #333;\n line-height: 1.6;\n }\n .email-container {\n max-width: 600px;\n margin: 20px auto;\n background: #ffffff;\n border: 1px solid #ddd;\n border-radius: 10px;\n box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);\n }\n .email-header {\n background-color: #0073e6;\n color: #fff;\n padding: 20px;\n text-align: center;\n border-top-left-radius: 10px;\n border-top-right-radius: 10px;\n }\n .email-header h1 {\n margin: 0;\n font-size: 24px;\n }\n .email-content {\n padding: 20px;\n }\n .section-title {\n font-size: 20px;\n color: #0073e6;\n margin-bottom: 10px;\n }\n ul {\n list-style: none;\n padding: 0;\n }\n ul li {\n margin: 10px 0;\n padding: 10px;\n background: #f4f4f4;\n border-left: 4px solid #0073e6;\n border-radius: 5px;\n }\n .action-item {\n font-weight: bold;\n margin: 5px 0;\n }\n .action-detail {\n margin-left: 10px;\n }\n .email-footer {\n background-color: #0073e6;\n color: #fff;\n text-align: center;\n padding: 10px;\n font-size: 14px;\n border-bottom-left-radius: 10px;\n border-bottom-right-radius: 10px;\n }\n </style>\n</head>\n<body>\n <div class=\"email-container\">\n <div class=\"email-header\">\n <h1>Email Summary</h1>\n </div>\n <div class=\"email-content\">\n <div>\n <h2 class=\"section-title\">Summary of Emails:</h2>\n <ul>\n {{ $json.message.content.summary_of_emails.map(email => `<li>${email}</li>`).join('') }}\n </ul>\n </div>\n <div>\n <h2 class=\"section-title\">Actions:</h2>\n <ul>\n {{ $json.message.content.actions.map(action => `\n <li>\n <span class=\"action-item\">${action.name}:</span>\n <span class=\"action-detail\">${action.action}</span>\n </li>\n `).join('') }}\n </ul>\n </div>\n </div>\n <div class=\"email-footer\">\n <p>Generated by Quantana ESAgent <br /> A Quantana AI Labs Initiative\n </div>\n </div>\n</body>\n</html>","options":{"ccList":"cc-list@example.com","appendAttribution":false,"replyToSenderOnly":false},"subject":"=ESAgent - {{ new Date(new Date().setDate(new Date().getDate() - 1)).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) }}-00:00 to {{ new Date(new Date().setDate(new Date().getDate())).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) }}-07:00AM"},"typeVersion":2.1},{"id":"7480f9af-2026-437c-800c-be49eef1895b","name":"Daily 8AM Trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-1020,180],"parameters":{"rule":{"interval":[{"triggerAtHour":7}]}},"typeVersion":1.2},{"id":"ab7c5ea2-81a6-4d8d-932c-2de023164304","name":"OpenRouter Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[-332,400],"parameters":{"options":{}},"credentials":{"openRouterApi":{"id":"W9KyGINw1pnCGjLT","name":"OpenRouter account"}},"typeVersion":1},{"id":"ddf9f7ee-630e-4b3d-8e84-d157d129c671","name":"Simple Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[-212,400],"parameters":{},"typeVersion":1.3},{"id":"309bfb47-72e1-4396-ad5f-dc656ea4eefa","name":"Email Summarizer","type":"@n8n/n8n-nodes-langchain.agent","position":[-360,180],"parameters":{"options":{"systemMessage":"Email Processing System\n\nStep 1: Extract Key Details\nRead the email thoroughly and identify:\n\nMain topics discussed\n\nCritical data points (dates, numbers, names)\n\nExplicit requests or requirements\n\nProblems or concerns raised\n\nStep 2: Organize Output\nSummary of Email\nBullet-point list of key takeaways\n\nExample:\n\nProject deadline extended to March 15\n\nNew compliance rules apply to all vendors\n\nIssues Identified\nList problems with context:\n\nIssue: Vendor delay impacting timeline\n\nImpact: Risk to Q2 launch\n\nAction Items\nClear tasks with owners:\n\nTask: Approve revised budget\n\nOwner: Finance Team\n\nDeadline: EOD Friday\n\nFollow-Up Needed\nOpen questions or missing info:\n\n\"Confirm if the client approved the scope change?\"\n\nRules for Clarity\n✔ Be concise – 1 line per point\n✔ Prioritize – Flag urgent items with [!]\n✔ Ownership – Always note who needs to act\n✔ Use plain language – Avoid jargon\n\nExample Output:\n\nSummary\n\nMarketing campaign paused due to budget review\n\nNew analytics tool rollout delayed by 2 weeks\n\nIssues\n\n[!] Budget approval missing – blocking all spend\n\nLow engagement on recent social posts\n\nActions\n\nSend revised budget to CFO (Owner: Alex)\n\nAudit social content (Owner: Marketing, Due: Nov 30)\n\nFollow-Up\n\nIs the budget review meeting scheduled?"},"promptType":"define"},"typeVersion":2},{"id":"5b97bbf7-5259-4554-a81e-330494bdcc45","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1460,-160],"parameters":{"width":1960,"height":860,"content":"# 📧 Email Auto-Summary Flow (n8n)\n\n**Purpose**: Daily digest of `isb.quantana@quantana.in` emails  \n**Runs**: 8AM IST (7AM UTC) weekdays  \n\n## 🔄 Workflow\n1. ⏰ **Trigger**: Scheduled daily run  \n2. 📥 **Input**: Fetch last 24h emails via Gmail API  \n3. 🤖 **Process**:  \n   - Filter non-essential emails  \n   - Extract key metadata (sender, subject, body)  \n4. ✍️ **AI Summary**:  \n   - Langchain analyzes content  \n   - Identifies: Updates/Issues/Actions  \n5. 📤 **Output**: Formatted email to team via Gmail API  \n\n## 🔑 APIs Needed:\n- Gmail API (OAuth2)  \n- OpenRouter API (LLM access)  \n- (Optional) Slack API for alerts  \n\n## ⚙️ Config:\n- `OPENROUTER_KEY` for AI  \n- `GMAIL_CREDS` for email access  \n- Recipient list in flow vars  \n\n💡 Processes ~50 emails/day | Error alerts via email"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"54b5fc42-b14e-4949-8b95-d956680caf69","connections":{"Simple Memory":{"ai_memory":[[{"node":"Email Summarizer","type":"ai_memory","index":0}]]},"Email Summarizer":{"main":[[{"node":"Send Summary - Morning","type":"main","index":0}]]},"Daily 8AM Trigger":{"main":[[{"node":"Fetch Emails - Past 24 Hours","type":"main","index":0}]]},"OpenRouter Chat Model":{"ai_languageModel":[[{"node":"Email Summarizer","type":"ai_languageModel","index":0}]]},"Fetch Emails - Past 24 Hours":{"main":[[{"node":"Organize Email Data - Morning","type":"main","index":0}]]},"Organize Email Data - Morning":{"main":[[{"node":"Email Summarizer","type":"main","index":0}]]}}}


name: AI-Powered Cold Calling Automation with Vapi.ai, GPT-4o & Google Sheets
author_name: Amit Mehta
author_username: amitswba
nodes_used: ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest","n8n-nodes-base.slack"]
categories: []
created_at: 2025-06-17T14:20:22.988Z
updated_at: 2025-06-17T14:20:22.988Z
url: https://n8n.io/workflows/5008
scraped_at: 2025-07-06 21:16:30
description:
  📞AI-Powered Cold Calling Automation with Vapi.ai, GPT-4o & Google Sheets

  Overview

  Transform your lead list into an AI-powered calling machine. This workflow automates your entire cold calling process using Vapi's conversational AI to initiate calls, qualify leads, capture detailed insights, and manage intelligent follow-ups - achieving 10x more calls than manual efforts while maintaining personalized, professional conversations.

  Built for sales teams, recruiters, and customer success professionals who need to scale outreach without sacrificing quality or adding headcount.

  🎯 Use Cases

  Sales & Business Development
  Lead Qualification**: Auto-dial new leads to assess interest and budget
  Demo Scheduling**: Book meetings with qualified prospects automatically
  Re-engagement**: Win back cold leads with personalized outreach
  Product Launches**: Announce new features to your entire customer base

  Recruitment & HR
  Candidate Screening**: Conduct first-round interviews at scale
  Interview Scheduling**: Coordinate availability without back-and-forth
  Reference Checks**: Automate reference verification calls
  Offer Follow-ups**: Ensure candidates received and understood offers

  Customer Success
  Onboarding Calls**: Welcome new customers with consistent messaging
  Renewal Reminders**: Proactively reach out before contract expiration
  Upsell Campaigns**: Identify expansion opportunities through conversations
  NPS Surveys**: Gather voice feedback for authentic insights

  Market Research
  Customer Interviews**: Collect qualitative feedback at scale
  Product Validation**: Test new concepts with target audiences
  Competitive Intelligence**: Understand why customers chose competitors
  Industry Surveys**: Gather market trends through conversational data

  ⚙️ How it Works

  The workflow operates through two parallel processes:

  Process 1: Call Initiation (Manual/On-Demand)
  Trigger: Manual start or scheduled batch processing
  Lead Retrieval: Fetches leads marked "Pending" or "Retry Scheduled" from Google Sheets
  Validation: Checks retry count (max 5 attempts) and routes accordingly
  API Call: Sends request to Vapi with lead details and AI assistant configuration
  Status Update: Marks lead as "Call Initiated" with unique call ID
  Batch Processing: Loops through all eligible leads with controlled pacing

  Process 2: Result Collection (Every 10 Minutes)
  Schedule Trigger: Automatic execution every 10 minutes
  Active Call Check: Identifies all "Call Initiated" records
  Result Fetching: Retrieves call outcomes from Vapi API
  Data Processing: Extracts recordings, transcripts, summaries, and interest scores
  Sheet Update: Writes complete results or schedules retry for missed calls
  Team Notification: Sends Slack alerts on batch completion

  📋 Setup Instructions

  Prerequisites
  n8n Instance**: Version 1.0.0+ (self-hosted or cloud)
  Google Account**: With Sheets API enabled
  Vapi Account**: Active subscription with API access
  Slack Workspace**: Optional, for notifications

  Step 1: Prepare Your Lead Database

  Create a Google Sheet with these exact columns (case-sensitive):
  Customer_id | Name | Phone Number | Email | Status | Recording URL | Transcript | Summary | Interest | Call Duration | Retry count | Last attempt | Call ID

  Initial Setup:
  Customer_id: Unique identifier (e.g., LEAD001)
  Name: Full name for personalization
  Phone Number: International format (+14155551234)
  Email: For follow-up campaigns
  Status: Set to "Pending"
  Retry count: Set to 0
  Other fields: Leave empty (auto-populated)

  Step 2: Configure Vapi AI Assistant

  Create Your AI Voice Agent
     Log into vapi.ai
     Navigate to Assistants → Create New
     Design your conversation flow
     Configure voice settings (gender, accent, speed)
     Set up objection handling
     Save and copy the Assistant ID

  Set Up Phone Number
     Go to Phone Numbers → Purchase/Import
     Select local or toll-free number
     Configure caller ID settings
     Copy the Phone Number ID

  Step 3: Import & Configure Workflow

  Import to n8n
     Download Cold_calling_loop.json
     In n8n: Import → From File
     Select the JSON file

  Connect Credentials
     Google Sheets: OAuth2 authentication
     Vapi API: HTTP Header Auth
       Name: Authorization
       Value: Bearer YOUR_API_KEY
     Slack: OAuth2 (optional)

  Update Configuration
     All Google Sheets nodes: Select your spreadsheet
     HTTP Request nodes: Update assistantId and phoneNumberId
     Slack nodes: Choose notification channels

  Step 4: Test & Deploy

  Add test lead with your phone number
  Execute workflow manually
  Answer call and complete conversation
  Verify results in Google Sheet
  Activate workflow for production

  🔄 Workflow Logic Explained

  Status Flow Diagram
  [New Lead: Pending] → [Call Initiated] → [Completed/Failed]
                                        ↓
                              [Retry Scheduled] ← (if failed & retry &lt; 5)

  Key Decision Points

  Retry Limit Check (If1 Node)
     Condition: Retry count ≤ 5
     True: Proceed with call
     False: Mark as "Max Retries Reached"

  Call Completion Check (If2 Node)
     Validates: Recording exists, transcript available, analysis complete
     Success: Update with full results
     Failure: Schedule retry with incremented counter

  Status Routing (If4 Node)
     "Pending": Direct to call queue
     "Retry Scheduled": Add wait period before calling

  📊 Node Reference Guide

  Core Processing Nodes

  | Node | Type | Purpose | Configuration |
  |------|------|---------|---------------|
  | Get Leads from Sheet1 | Google Sheets | Fetches eligible leads | Filter: Status = "Pending" OR "Retry Scheduled" |
  | HTTP Request | HTTP | Initiates Vapi call | POST to api.vapi.ai/call with assistant config |
  | Loop Over Items | Split In Batches | Processes leads individually | Batch size: 1, ensures sequential processing |
  | Get Call Data | HTTP | Retrieves call results | GET from api.vapi.ai/call?id={callId} |
  | Edit Fields2 | Set | Formats result data | Maps Vapi response to sheet columns |

  Status Management Nodes

  | Node | Updates | Trigger |
  |------|---------|---------|
  | Update Status - Calling1 | "Call Initiated" | After successful API call |
  | Update Status - Calling | "Done" + results | When call completed successfully |
  | Update Status - for Missed call | "Retry Scheduled" | When call failed/no answer |
  | Update Status - Calling3 | "Retry Done" | After retry limit reached |

  Control Flow Nodes

  | Node | Function | Logic |
  |------|----------|-------|
  | If1 | Retry validation | Checks retry count ≤ 5 |
  | If2 | Result validation | Verifies call completion |
  | Wait | Retry delay | Pauses before retry attempt |
  | Merge | Path combination | Unifies success/retry flows |

  🛠️ Customization Guide

  1. Modify Retry Strategy
  // Add to Code node for progressive delays
  const retryCount = $json["Retry count"];
  const delays = {
    1: 30,    // 30 minutes
    2: 120,   // 2 hours
    3: 1440,  // Next day
    4: 2880,  // 2 days
    5: 10080  // 1 week
  };
  return { waitMinutes: delays[retryCount] || 60 };

  2. Add Business Hours Check
  // Add before HTTP Request node
  const now = new Date();
  const hour = now.getHours();
  const day = now.getDay();

  const isWeekday = day &gt;= 1 && day &lt;= 5;
  const isBusinessHours = hour &gt;= 9 && hour &lt;= 17;

  if (!isWeekday || !isBusinessHours) {
    throw new Error('Outside calling hours');
  }

  3. Enhance Lead Context
  {
    "assistantId": "your-assistant-id",
    "phoneNumberId": "your-phone-id",
    "customer": {
      "number": "+{{ $json['Phone Number'] }}",
      "name": "{{ $json.Name }}",
      "customData": {
        "company": "{{ $json.Company }}",
        "lastPurchase": "{{ $json['Last Purchase Date'] }}",
        "accountValue": "{{ $json['Account Value'] }}",
        "preferredProduct": "{{ $json['Product Interest'] }}"
      }
    }
  }

  💡 Sticky Notes Configuration

  Note 1: Status Progression
  Location: Near Google Sheets nodes
  📊 LEAD STATUS FLOW:
  Pending → Call Initiated → Done/Retry Scheduled
  Retry Scheduled → Call Initiated → Done/Failed

  ⚠️ Max retries: 5 attempts
  ❌ Failed = No answer after 5 tries
  ✅ Done = Call completed with results

  Note 2: Phone Format Requirements
  Location: Near HTTP Request nodes
  📱 PHONE NUMBER FORMAT:
  ✅ Correct: +14155551234
  ❌ Wrong: (415) 555-1234
  ❌ Wrong: 415-555-1234

  Must include:
  Plus sign (+)
  Country code
  No spaces or symbols

  Note 3: Vapi Setup Checklist
  Location: At workflow start
  🔧 VAPI CONFIGURATION:
  □ Assistant ID copied from Vapi
  □ Phone Number ID from Vapi
  □ API Key in credentials
  □ Credits available
  □ Assistant tested in playground

  Note 4: Performance Guidelines
  Location: Near Loop nodes
  ⚡ OPTIMIZATION TIPS:
  • Batch size: 10-20 leads
  • Call hours: 9 AM - 5 PM local
  • Delay between calls: 5 seconds
  • Monthly archive old records
  • Monitor Vapi credit usage

  Common Issues & Solutions

  🔴 "Authentication Failed"
  Cause: Expired or invalid credentials
  Fix: 
  Re-authenticate Google Sheets OAuth
  Verify Vapi API key is active
  Check credential permissions

  🔴 "Call Not Initiating"
  Cause: Invalid phone format or Vapi configuration
  Fix:
  Ensure phone includes country code
  Verify Vapi account has credits
  Test assistant in Vapi playground
  Check assistant and phone IDs

  🔴 "Missing Results"
  Cause: Call still processing or webhook failure
  Fix:
  Wait 3-5 minutes for processing
  Check Vapi dashboard directly
  Verify Get Call Data node query
  Review If2 conditions

  🔴 "Infinite Loop"
  Cause: Status not updating correctly
  Fix:
  Check retry count increment logic
  Verify status update mappings
  Clear test data and restart

  🔴 "No Slack Notifications"
  Cause: Bot permissions or channel access
  Fix:
  Invite bot to channel
  Verify OAuth scopes
  Test Slack node individually

  📁 Required Files & Resources

  | File | Description | Location |
  |------|-------------|----------|
  | Cold_calling_loop.json | Complete workflow configuration | Main workflow file |
  | lead_template.xlsx | Google Sheets template with headers | Sample data file |

  🏷️ Tags & Categories

  Primary Category
  Sales & Marketing Automation

  Workflow Tags
  cold-calling vapi-ai voice-automation lead-generation ai-sales google-sheets outbound-calling sales-automation conversational-ai crm-automation

  Use Case Tags
  b2b-sales recruitment customer-success market-research appointment-setting lead-qualification follow-up-automation

  Integration Tags
  vapi google-sheets slack voice-ai telephony

  🚀 Future Enhancements

  Planned Features
  CRM Integration**: Direct sync with Salesforce/HubSpot
  Multi-language**: Support for 10+ languages
  SMS Follow-up**: Automated text after calls
  Analytics Dashboard**: Real-time performance metrics
  Sentiment Analysis**: Emotional intelligence scoring

  Community Roadmap
  Webhook support for real-time updates
  Custom voice training options
  A/B testing for scripts
  Predictive best time to call
  Integration with calendar systems

  📞 Support & Resources

  Support email : amitswba@gmail.com

workflow_json:
  {"id":"w8kzaOLDAa5IlK5X","meta":{"instanceId":"260491e02302632e6a217f5c83135ad573c31ec4f93b05d79785a77df9c4a7e5","templateCredsSetupCompleted":true},"name":"Cold calling loop","tags":[{"id":"BNIuz01albAGQ6Q7","name":"no-webhook","createdAt":"2025-06-05T10:07:49.327Z","updatedAt":"2025-06-05T10:07:49.327Z"},{"id":"Mf7YWG1wbOwM8v1P","name":"vapi","createdAt":"2025-06-04T10:12:06.322Z","updatedAt":"2025-06-04T10:12:06.322Z"},{"id":"VrzKqoq2nlpPmWs2","name":"webhook","createdAt":"2025-06-05T10:40:41.083Z","updatedAt":"2025-06-05T10:40:41.083Z"},{"id":"kfm3hRQJIOK29QrK","name":"cold-calling","createdAt":"2025-06-04T10:12:06.289Z","updatedAt":"2025-06-04T10:12:06.289Z"}],"nodes":[{"id":"sticky-note-1","name":"Sticky Note - Start","type":"n8n-nodes-base.stickyNote","position":[-1660,1775],"parameters":{"content":""},"typeVersion":1},{"id":"sticky-note-2","name":"Sticky Note - Lead Retrieval","type":"n8n-nodes-base.stickyNote","position":[-1490,2075],"parameters":{"content":""},"typeVersion":1},{"id":"sticky-note-3","name":"Sticky Note - Retry Logic","type":"n8n-nodes-base.stickyNote","position":[-1220,1675],"parameters":{"content":""},"typeVersion":1},{"id":"sticky-note-4","name":"Sticky Note - Call Process","type":"n8n-nodes-base.stickyNote","position":[-600,1075],"parameters":{"content":""},"typeVersion":1},{"id":"sticky-note-5","name":"Sticky Note - Scheduled Check","type":"n8n-nodes-base.stickyNote","position":[-1660,2810],"parameters":{"content":""},"typeVersion":1},{"id":"sticky-note-6","name":"Sticky Note - Results Processing","type":"n8n-nodes-base.stickyNote","position":[-600,2435],"parameters":{"content":""},"typeVersion":1},{"id":"sticky-note-7","name":"Sticky Note - Notifications","type":"n8n-nodes-base.stickyNote","position":[-830,1575],"parameters":{"content":""},"typeVersion":1},{"id":"sticky-note-8","name":"Sticky Note - Workflow Features","type":"n8n-nodes-base.stickyNote","position":[600,1475],"parameters":{"content":""},"typeVersion":1},{"id":"c1f5453a-fb9e-473d-ac37-80c7777364c2","name":"Get Leads from Sheet1","type":"n8n-nodes-base.googleSheets","position":[-1140,1875],"parameters":{},"typeVersion":4.4},{"id":"aca0ff2c-b362-47c3-817e-fe42c6cc0b85","name":"Update Status - Calling1","type":"n8n-nodes-base.googleSheets","position":[400,1775],"parameters":{},"typeVersion":4.4},{"id":"ea8964c4-802e-4fe8-9ae9-f52c97d4dfac","name":"When clicking 'Test workflow'","type":"n8n-nodes-base.manualTrigger","position":[-1360,1875],"parameters":{},"typeVersion":1},{"id":"81648e86-b214-461a-a15e-b9c50c52c932","name":"If1","type":"n8n-nodes-base.if","position":[-920,1875],"parameters":{},"typeVersion":2.2},{"id":"d0daea30-3077-418a-be6b-e3bf13aed389","name":"HTTP Request","type":"n8n-nodes-base.httpRequest","position":[180,1675],"parameters":{},"typeVersion":4.2},{"id":"4db18eeb-911f-4376-8b0a-0be54abcabd2","name":"Get Call Data","type":"n8n-nodes-base.httpRequest","position":[-480,2735],"parameters":{},"typeVersion":4},{"id":"3ee501a8-7067-47fd-b090-82311e62a980","name":"Get Leads from Sheet","type":"n8n-nodes-base.googleSheets","position":[-1140,2910],"parameters":{},"typeVersion":4.4},{"id":"0498ef4c-874d-4a55-bab9-3776f3718018","name":"Update Status - Calling","type":"n8n-nodes-base.googleSheets","position":[180,2635],"parameters":{},"typeVersion":4.4},{"id":"e359ca54-8a46-4046-b4aa-014b96f1fa6e","name":"Pending","type":"n8n-nodes-base.if","position":[-700,1475],"parameters":{},"typeVersion":2.2},{"id":"c4cdbd85-0144-4d51-9ab3-44beb10bdc93","name":"Retry","type":"n8n-nodes-base.if","position":[-480,1775],"parameters":{},"typeVersion":2.2},{"id":"6d71e12f-8177-4771-b1e5-e943de2255e9","name":"Loop Over Items","type":"n8n-nodes-base.splitInBatches","position":[-260,1775],"parameters":{},"typeVersion":3},{"id":"0458820e-61c1-4617-bc4c-48a7ca62bf69","name":"Update Status - Calling2","type":"n8n-nodes-base.googleSheets","position":[180,1375],"parameters":{},"typeVersion":4.4},{"id":"f2c8bc74-ea7f-47de-b340-5568a630d1bd","name":"HTTP Request1","type":"n8n-nodes-base.httpRequest","position":[-40,1300],"parameters":{},"typeVersion":4.2},{"id":"577a6e93-a867-4b2c-ada2-04016c1ef7a5","name":"Loop Over Items1","type":"n8n-nodes-base.splitInBatches","position":[-480,1375],"parameters":{},"typeVersion":3},{"id":"21e246fd-8171-4b8a-b66f-81c6614de380","name":"Update Status - Calling3","type":"n8n-nodes-base.googleSheets","position":[-480,2375],"parameters":{},"typeVersion":4.4},{"id":"4bece131-551d-4e27-a80d-f36e644e9dae","name":"Loop Over Items2","type":"n8n-nodes-base.splitInBatches","position":[-700,2325],"parameters":{},"typeVersion":3},{"id":"c45f0732-ffec-47f5-9153-a7544916e49d","name":"Loop Over Items3","type":"n8n-nodes-base.splitInBatches","position":[-700,2810],"parameters":{},"typeVersion":3},{"id":"6e9c15e9-d2d8-439f-b5c2-6986c3290b18","name":"If2","type":"n8n-nodes-base.if","position":[-260,2735],"parameters":{},"typeVersion":2.2},{"id":"15a70bb7-ae86-4607-9be3-dc696938bbda","name":"Edit Fields2","type":"n8n-nodes-base.set","position":[-40,2635],"parameters":{},"typeVersion":3.4},{"id":"fd452dba-cfba-4041-b0cc-64d2a46fe960","name":"Update Status - for Missed call","type":"n8n-nodes-base.googleSheets","position":[180,2835],"parameters":{},"typeVersion":4.4},{"id":"7d391405-0284-4320-9993-c798eac651a2","name":"If4","type":"n8n-nodes-base.if","position":[-700,1875],"parameters":{},"typeVersion":2.2},{"id":"671fe24d-dc5f-4c40-a417-54e2cc0ad407","name":"Merge","type":"n8n-nodes-base.merge","position":[400,2810],"parameters":{},"typeVersion":3.1},{"id":"886b3685-041d-499a-b9f3-56904f11bd27","name":"If5","type":"n8n-nodes-base.if","position":[-920,2910],"parameters":{},"typeVersion":2.2},{"id":"7b34b530-4f4f-4d84-8033-d8b02d51df0a","name":"Schedule Trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-1360,2910],"parameters":{},"typeVersion":1.2},{"id":"68be2965-c14c-43c1-bde3-0b8dd588ab19","name":"Slack","type":"n8n-nodes-base.slack","position":[-480,1975],"webhookId":"DUMMY-WEBHOOK-ID-001","parameters":{},"typeVersion":2.3},{"id":"823bc807-cdcd-4e39-95de-ce6fe429e5d4","name":"Slack1","type":"n8n-nodes-base.slack","position":[-480,1575],"webhookId":"DUMMY-WEBHOOK-ID-002","parameters":{},"typeVersion":2.3},{"id":"51e38bec-66da-4b97-b03c-044e6521e162","name":"Slack2","type":"n8n-nodes-base.slack","position":[-480,2175],"webhookId":"DUMMY-WEBHOOK-ID-003","parameters":{},"typeVersion":2.3},{"id":"2e7df5a3-2596-478f-a083-b1b14bf66ff8","name":"Slack3","type":"n8n-nodes-base.slack","position":[-700,3010],"webhookId":"DUMMY-WEBHOOK-ID-004","parameters":{},"typeVersion":2.3},{"id":"24532380-147f-4e6e-8d7f-bb97498c78fd","name":"Wait","type":"n8n-nodes-base.wait","position":[-40,1675],"webhookId":"DUMMY-WEBHOOK-ID-005","parameters":{},"typeVersion":1.1},{"id":"a9dc0fb3-2697-477a-b97d-ba09a297bda0","name":"Wait1","type":"n8n-nodes-base.wait","position":[-260,1300],"webhookId":"DUMMY-WEBHOOK-ID-006","parameters":{},"typeVersion":1.1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"aa19a603-1f5a-4438-ac20-c273bf478fec","connections":{"If1":{"main":[[{"node":"Pending","type":"main","index":0},{"node":"If4","type":"main","index":0}],[{"node":"Loop Over Items2","type":"main","index":0}]]},"If2":{"main":[[{"node":"Edit Fields2","type":"main","index":0}],[{"node":"Update Status - for Missed call","type":"main","index":0}]]},"If4":{"main":[[{"node":"Retry","type":"main","index":0}],[{"node":"Slack","type":"main","index":0}]]},"If5":{"main":[[{"node":"Loop Over Items3","type":"main","index":0}],[{"node":"Slack3","type":"main","index":0}]]},"Wait":{"main":[[{"node":"HTTP Request","type":"main","index":0}]]},"Merge":{"main":[[{"node":"Loop Over Items3","type":"main","index":0}]]},"Retry":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Wait1":{"main":[[{"node":"HTTP Request1","type":"main","index":0}]]},"Pending":{"main":[[{"node":"Loop Over Items1","type":"main","index":0}],[{"node":"Slack1","type":"main","index":0}]]},"Edit Fields2":{"main":[[{"node":"Update Status - Calling","type":"main","index":0}]]},"HTTP Request":{"main":[[{"node":"Update Status - Calling1","type":"main","index":0}]]},"Get Call Data":{"main":[[{"node":"If2","type":"main","index":0}]]},"HTTP Request1":{"main":[[{"node":"Update Status - Calling2","type":"main","index":0}]]},"Loop Over Items":{"main":[[],[{"node":"Wait","type":"main","index":0}]]},"Loop Over Items1":{"main":[[],[{"node":"Wait1","type":"main","index":0}]]},"Loop Over Items2":{"main":[[{"node":"Slack2","type":"main","index":0}],[{"node":"Update Status - Calling3","type":"main","index":0}]]},"Loop Over Items3":{"main":[[],[{"node":"Get Call Data","type":"main","index":0}]]},"Schedule Trigger":{"main":[[{"node":"Get Leads from Sheet","type":"main","index":0}]]},"Get Leads from Sheet":{"main":[[{"node":"If5","type":"main","index":0}]]},"Get Leads from Sheet1":{"main":[[{"node":"If1","type":"main","index":0}]]},"Update Status - Calling":{"main":[[{"node":"Merge","type":"main","index":0}]]},"Update Status - Calling1":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Update Status - Calling2":{"main":[[{"node":"Loop Over Items1","type":"main","index":0}]]},"Update Status - Calling3":{"main":[[{"node":"Loop Over Items2","type":"main","index":0}]]},"When clicking 'Test workflow'":{"main":[[{"node":"Get Leads from Sheet1","type":"main","index":0}]]},"Update Status - for Missed call":{"main":[[{"node":"Merge","type":"main","index":1}]]}}}


name: RAG Starter Template using Simple Vector Stores, Form trigger and OpenAI
author_name: n8n Team
author_username: n8n-team
categories: []
created_at: 2025-06-17T19:16:08.694Z
updated_at: 2025-06-17T19:16:08.694Z
url: https://n8n.io/workflows/5010
scraped_at: 2025-07-06 21:16:30
description:
  This template quickly shows how to use RAG in n8n.

  Who is this for?
  This template is for everyone who wants to start giving knowledge to their Agents through RAG.

  Requirements
  Have a PDF with custom knowledge that you want to provide to your agent.

  Setup
  No setup required. Just hit Execute Workflow, upload your knowledge document and then start chatting.

  How to customize this to your needs
  Add custom instructions to your Agent by changing the prompts in it.
  Add a different way to load in knowledge to your vector store, e.g. by looking at some Google Drive files or loading knowledge from a table.
  Exchange the Simple Vector Store nodes with your own vector store tools ready for production.
  Add a more sophisticated way to rank files found in the vector store.

  For more information read our docs on RAG in n8n.

nodes_used:
  ["@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.embeddingsOpenAi","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.vectorStoreInMemory","@n8n/n8n-nodes-langchain.documentDefaultDataLoader"]

workflow_json:
  {"meta":{"instanceId":"257476b1ef58bf3cb6a46e65fac7ee34a53a5e1a8492d5c6e4da5f87c9b82833"},"nodes":[{"id":"83ed351e-90e8-458f-a01b-73001ef1800f","name":"Upload your file here","type":"n8n-nodes-base.formTrigger","position":[220,-120],"webhookId":"82848bc4-5ea2-4e5a-8bb6-3c09b94a8c5d","parameters":{"options":{},"formTitle":"Upload your data to test RAG","formFields":{"values":[{"fieldType":"file","fieldLabel":"Upload your file(s)","requiredField":true,"acceptFileTypes":".pdf, .csv"}]}},"typeVersion":2.2},{"id":"26d63e24-2592-41f9-9b4b-edab81e99f21","name":"Embeddings OpenAI","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[860,360],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"14","name":"OpenAi account"}},"typeVersion":1.2},{"id":"3a69c8a7-bf95-4de2-84b0-ae2cc3d2e4e7","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[660,40],"parameters":{"options":{},"dataType":"binary"},"typeVersion":1.1},{"id":"0b42832b-c9e8-4627-b36c-94fc5e242b33","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-320,-180],"parameters":{"color":4,"width":440,"height":300,"content":"### Readme\nLoad your data into a vector database with the 📚 **Load Data** flow, and then use your data as chat context with the 🐕 **Retriever** flow.\n\n**Quick start**\n1. Click on the `Execute Workflow` button to run the 📚 **Load Data** flow.\n2. Click on `Open Chat` button to run the 🐕 **Retriever** flow. Then ask a question about content from your document(s)\n\n\nFor more info, check our [docs on RAG in n8n](https://docs.n8n.io/advanced-ai/rag-in-n8n/)"},"typeVersion":1},{"id":"f902ab8f-4620-4a95-86f7-c5857c4d6c4f","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[160,-180],"parameters":{"color":7,"width":700,"height":460,"content":"### 📚 Load Data Flow"},"typeVersion":1},{"id":"0f4185ea-d7a9-44a9-a824-98f9dc2c2a5d","name":"Insert Data to Store","type":"@n8n/n8n-nodes-langchain.vectorStoreInMemory","position":[400,-120],"parameters":{"mode":"insert","memoryKey":{"__rl":true,"mode":"list","value":"vector_store_key","cachedResultName":"vector_store_key"}},"typeVersion":1.2},{"id":"ce86b41b-7e1b-458f-ab13-d6b187854ae8","name":"Query Data Tool","type":"@n8n/n8n-nodes-langchain.vectorStoreInMemory","position":[1280,80],"parameters":{"mode":"retrieve-as-tool","toolName":"knowledge_base","memoryKey":{"__rl":true,"mode":"list","value":"vector_store_key"},"toolDescription":"Use this knowledge base to answer questions from the user"},"typeVersion":1.2},{"id":"0039537b-558c-4fe8-9716-f8aa13676f4a","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[1280,-140],"parameters":{"options":{}},"typeVersion":2},{"id":"2669a65e-f0f3-45aa-95c0-621b15a4fc67","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[1060,-140],"webhookId":"4091fa09-fb9a-4039-9411-7104d213f601","parameters":{"options":{}},"typeVersion":1.1},{"id":"d43cf585-4192-4f53-9532-4677923289ba","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1060,80],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"typeVersion":1.2},{"id":"3d1b3f5a-bc35-4739-a618-9c85820d39a0","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[940,-180],"parameters":{"color":7,"width":680,"height":460,"content":"### 🐕 2. Retriever Flow"},"typeVersion":1},{"id":"8d4c68cf-64d1-4b3a-bb19-2f003303c1df","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[1000,320],"parameters":{"color":4,"width":320,"height":240,"content":"### Embeddings\n\nThe Insert and Retrieve operation use the same embedding node.\n\nThis is to ensure that they are using the **exact same embeddings and settings**.\n\nDifferent embeddings might not work at all, or have unintended consequences.\n"},"typeVersion":1}],"connections":{"Query Data Tool":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"Embeddings OpenAI":{"ai_embedding":[[{"node":"Insert Data to Store","type":"ai_embedding","index":0},{"node":"Query Data Tool","type":"ai_embedding","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"Insert Data to Store","type":"ai_document","index":0}]]},"Upload your file here":{"main":[[{"node":"Insert Data to Store","type":"main","index":0}]]},"When chat message received":{"main":[[{"node":"AI Agent","type":"main","index":0}]]}}}


name: Save Costs In RAG Workflows using the Q&A Tool With Multiple Models
author_name: Niklas Hatje
author_username: nik8n
categories: []
created_at: 2025-06-17T19:30:43.009Z
updated_at: 2025-06-17T19:30:43.009Z
url: https://n8n.io/workflows/5011
scraped_at: 2025-07-06 21:16:30
description:
  This template shows how to use the Question and Answer tool to save costs in RAG use cases.

  Who is this for?
  This template is for everyone who wants to start giving knowledge to their Agents through RAG.

  Requirements
  Have a PDF with custom knowledge that you want to provide to your agent.

  Setup
  No setup required. Just hit Execute Workflow, upload your knowledge document and then start chatting.

  How to customize this to your needs
  Add custom instructions to your Agent by changing the prompts in it.
  Add a different way to load in knowledge to your vector store, e.g. by looking at some Google Drive files or loading knowledge from a table.
  Describe your data properly in the Q&A tool
  Exchange the Simple Vector Store nodes with your own vector store tools ready for production.
  Add a more sophisticated way to rank files found in the vector store.

  For more information read our docs on RAG in n8n.

nodes_used:
  ["@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.embeddingsOpenAi","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.vectorStoreInMemory","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.toolVectorStore"]

workflow_json:
  {"meta":{"instanceId":"257476b1ef58bf3cb6a46e65fac7ee34a53a5e1a8492d5c6e4da5f87c9b82833","templateCredsSetupCompleted":true},"nodes":[{"id":"83ed351e-90e8-458f-a01b-73001ef1800f","name":"Upload your file here","type":"n8n-nodes-base.formTrigger","position":[220,-120],"webhookId":"82848bc4-5ea2-4e5a-8bb6-3c09b94a8c5d","parameters":{"options":{},"formTitle":"Upload your data to test RAG","formFields":{"values":[{"fieldType":"file","fieldLabel":"Upload your file(s)","requiredField":true,"acceptFileTypes":".pdf, .csv"}]}},"typeVersion":2.2},{"id":"26d63e24-2592-41f9-9b4b-edab81e99f21","name":"Embeddings OpenAI","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[860,460],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"14","name":"OpenAi account"}},"typeVersion":1.2},{"id":"3a69c8a7-bf95-4de2-84b0-ae2cc3d2e4e7","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[660,40],"parameters":{"options":{},"dataType":"binary"},"typeVersion":1.1},{"id":"0b42832b-c9e8-4627-b36c-94fc5e242b33","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-320,-180],"parameters":{"color":4,"width":440,"height":300,"content":"### Readme\nLoad your data into a vector database with the 📚 **Load Data** flow, and then use your data as chat context with the 🐕 **Retriever** flow.\n\n**Quick start**\n1. Click on the `Execute Workflow` button to run the 📚 **Load Data** flow.\n2. Click on `Open Chat` button to run the 🐕 **Retriever** flow. Then ask a question about content from your document(s)\n\n\nFor more info, check our [docs on RAG in n8n](https://docs.n8n.io/advanced-ai/rag-in-n8n/)"},"typeVersion":1},{"id":"f902ab8f-4620-4a95-86f7-c5857c4d6c4f","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[160,-180],"parameters":{"color":7,"width":700,"height":460,"content":"### 📚 Load Data Flow"},"typeVersion":1},{"id":"0f4185ea-d7a9-44a9-a824-98f9dc2c2a5d","name":"Insert Data to Store","type":"@n8n/n8n-nodes-langchain.vectorStoreInMemory","position":[400,-120],"parameters":{"mode":"insert","memoryKey":{"__rl":true,"mode":"list","value":"vector_store_key","cachedResultName":"vector_store_key"}},"typeVersion":1.2},{"id":"ce86b41b-7e1b-458f-ab13-d6b187854ae8","name":"Query Data Tool","type":"@n8n/n8n-nodes-langchain.vectorStoreInMemory","position":[1300,200],"parameters":{"memoryKey":{"__rl":true,"mode":"list","value":"vector_store_key"}},"typeVersion":1.2},{"id":"0039537b-558c-4fe8-9716-f8aa13676f4a","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[1280,-140],"parameters":{"options":{}},"typeVersion":2},{"id":"2669a65e-f0f3-45aa-95c0-621b15a4fc67","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[1060,-140],"webhookId":"4091fa09-fb9a-4039-9411-7104d213f601","parameters":{"options":{}},"typeVersion":1.1},{"id":"3d1b3f5a-bc35-4739-a618-9c85820d39a0","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[940,-180],"parameters":{"color":7,"width":820,"height":520,"content":"### 🐕 2. Retriever Flow"},"typeVersion":1},{"id":"6553a758-c655-4196-88be-9d93187f9c7b","name":"Answer questions with a vector store","type":"@n8n/n8n-nodes-langchain.toolVectorStore","position":[1440,60],"parameters":{"description":"The data contains custom knowledge"},"typeVersion":1.1},{"id":"d43cf585-4192-4f53-9532-4677923289ba","name":"Expensive model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1060,80],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4.1","cachedResultName":"gpt-4.1"},"options":{}},"credentials":{"openAiApi":{"id":"14","name":"OpenAi account"}},"typeVersion":1.2},{"id":"18dcc49d-9ce0-4746-8135-7e4c77cfa501","name":"Cheap Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1600,200],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4.1-mini"},"options":{}},"credentials":{"openAiApi":{"id":"14","name":"OpenAi account"}},"typeVersion":1.2}],"connections":{"Cheap Model":{"ai_languageModel":[[{"node":"Answer questions with a vector store","type":"ai_languageModel","index":0}]]},"Expensive model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Query Data Tool":{"ai_tool":[[]],"ai_vectorStore":[[{"node":"Answer questions with a vector store","type":"ai_vectorStore","index":0}]]},"Embeddings OpenAI":{"ai_embedding":[[{"node":"Insert Data to Store","type":"ai_embedding","index":0},{"node":"Query Data Tool","type":"ai_embedding","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"Insert Data to Store","type":"ai_document","index":0}]]},"Upload your file here":{"main":[[{"node":"Insert Data to Store","type":"main","index":0}]]},"When chat message received":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Answer questions with a vector store":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]}}}


name: Natural Language Database Queries with Dual-Agent AI & PostgreSQL Integration
author_name: Paul
author_username: diagopl
categories: []
created_at: 2025-06-17T21:17:10.100Z
updated_at: 2025-06-17T21:17:10.100Z
url: https://n8n.io/workflows/5012
scraped_at: 2025-07-06 21:16:30
description:
  AI Database Assistant with Smart Query's & PostgreSQL Integration

  Description:

  🚀 Transform Your Database into an Intelligent AI Assistant

  This workflow creates a smart database assistant that safely handles natural language queries without crashing your system. Features dual-agent architecture with built-in query limits and PostgreSQL optimization – perfect for commercial applications!

  ✅ Ideal for:
  SaaS developers building database search features 🔍
  Database administrators providing safe AI access 🛡️
  Business teams needing user-friendly data queries 📊
  Anyone wanting ChatGPT-like database interaction 🤖

  🔧 How It Works
  1️⃣ User asks a question – "Show me top 10 popular products"
  2️⃣ Main AI Agent – Interprets the request and ensures safety limits
  3️⃣ SQL Sub-Agent – Generates precise PostgreSQL queries
  4️⃣ Database executes – Returns formatted, limited results safely

  ⚡ Setup Instructions

  1️⃣ Prepare Your Database
  Ensure PostgreSQL is accessible from n8n
  Note your table structure and column names
  Set up database connection credentials

  2️⃣ Customize the Templates
  Replace [YOUR_TABLE_NAME] with your actual table name
  Update [YOUR_FIELDS] with your column names
  Modify examples to match your use case
  Important**: Keep all LIMIT clauses intact!

  3️⃣ Configure the Agents
  Copy Main Agent system message to your primary AI node
  Copy Sub-Agent system message to your SQL generator node
  Connect the sub-workflow between both agents

  4️⃣ Test & Deploy
  Test with sample queries like "Show me 5 recent items"
  Verify query limits work (max 50 results)
  Deploy and monitor performance

  🎯 Why Use This Workflow?
  ✔️ System Protection – Built-in limits prevent crashes from large queries
  ✔️ Natural Language – Users ask questions in plain English
  ✔️ Commercial Ready – Generic templates work with any database
  ✔️ Dual-Agent Safety – Smart interpretation + precise SQL generation
  ✔️ PostgreSQL Optimized – Handles complex schemas and data types

  🚨 Critical Features
  Query Limits**: Default 10, maximum 50 results (can be modified)
  Error Prevention**: No unlimited data retrieval
  Smart Routing**: Natural language → Safe SQL → Formatted results
  Customizable**: Works with any PostgreSQL database schema

  🔗 Start building your AI database assistant today – safe, smart, and scalable!

nodes_used:
  ["n8n-nodes-base.postgres","n8n-nodes-base.telegram","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.toolWorkflow","@n8n/n8n-nodes-langchain.openAi","@n8n/n8n-nodes-langchain.memoryPostgresChat","@n8n/n8n-nodes-langchain.lmChatOpenRouter","@n8n/n8n-nodes-langchain.toolThink"]

workflow_json:
  {"id":"XIcKeYYhzG9DdDPN","meta":{"instanceId":"e7ccf4281d5afb175c79c02db95b45f15d5b53862cb6bc357c5e5bc26567f35c","templateCredsSetupCompleted":true},"name":"Template 2","tags":[],"nodes":[{"id":"c4a7b5c1-f74e-4de0-9469-146a197c42f5","name":"When Executed by Another Workflow","type":"n8n-nodes-base.executeWorkflowTrigger","position":[-1560,360],"parameters":{"inputSource":"passthrough"},"typeVersion":1.1},{"id":"1f37374e-3c5c-4dad-bfa0-5e948cfbd6e5","name":"Query agent","type":"@n8n/n8n-nodes-langchain.agent","position":[-1320,360],"parameters":{"text":"={{ $json.query }}","options":{"systemMessage":"# SQL Query Generator - Sub Agent Template\n\nYou are a PostgreSQL query generator. Convert user requests into SELECT queries for the database table.\n\n## CRITICAL: OUTPUT FORMAT\n- Output ONLY the SQL query\n- NO explanations, descriptions, or additional text\n- NO code blocks or formatting\n- Just the raw SQL query string\n\n## DATABASE SCHEMA:\n**[REPLACE WITH YOUR DATABASE SCHEMA]**\n```\n[TABLE_NAME] Table:\nid (bigint, Primary Key)\n[field_name] (data_type)\n[field_name] (data_type)\n...\n```\n\n## STRICT RULES:\n1. ONLY SELECT queries - NO INSERT/UPDATE/DELETE/DROP/ALTER\n2. Table name: \"[YOUR_TABLE_NAME]\" (use double quotes if needed)\n3. Column names with spaces: use double quotes (\"[column name]\")\n4. Boolean columns: use true/false (not 1/0)\n5. Text searches: use ILIKE for case-insensitive matching\n6. Always end query with semicolon\n\n## EXAMPLES:\n**[CUSTOMIZE THESE EXAMPLES FOR YOUR USE CASE]**\nUser: \"Show verified entries\" \nResponse: SELECT * FROM \"[YOUR_TABLE]\" WHERE [verified_field] = true;\n\nUser: \"Top 10 most popular\"  \nResponse: SELECT * FROM \"[YOUR_TABLE]\" ORDER BY [popularity_field] DESC LIMIT 10;\n\nUser: \"Items containing [keyword]\"\nResponse: SELECT * FROM \"[YOUR_TABLE]\" WHERE [description_field] ILIKE '%[keyword]%';\n\nREMEMBER: Output ONLY the SQL query, nothing else."},"promptType":"define"},"typeVersion":2},{"id":"1019eeda-425f-4450-934e-0224c689a801","name":"Think","type":"@n8n/n8n-nodes-langchain.toolThink","position":[-1140,580],"parameters":{"description":"Think if the ouputed query really matches the input message."},"typeVersion":1},{"id":"2219bc4a-cdf2-4297-9bd6-423d0f138319","name":"OpenRouter Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[-1340,560],"parameters":{"model":"anthropic/claude-3.5-sonnet","options":{}},"credentials":{"openRouterApi":{"id":"1t22HwKbMlWsWxcJ","name":"OpenRouter account"}},"typeVersion":1},{"id":"21a65536-abfd-4d19-94c9-9aa8d839db16","name":"Postgres Chat Memory","type":"@n8n/n8n-nodes-langchain.memoryPostgresChat","position":[-280,80],"parameters":{"sessionKey":"C08SU8T0FJ8","sessionIdType":"customKey"},"credentials":{"postgres":{"id":"6uE1gPELXSqR1Wgn","name":"Postgres accou"}},"typeVersion":1.3},{"id":"32cf9699-649c-4781-b27b-c68e7ff306a4","name":"OpenRouter Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[-440,80],"parameters":{"model":"anthropic/claude-3.5-sonnet","options":{}},"credentials":{"openRouterApi":{"id":"1t22HwKbMlWsWxcJ","name":"OpenRouter account"}},"typeVersion":1},{"id":"cacfb298-2ee6-4292-ade7-bb18436df301","name":"Think1","type":"@n8n/n8n-nodes-langchain.toolThink","position":[-140,80],"parameters":{},"typeVersion":1},{"id":"6c979f9c-38df-4b8d-a7c2-be499bd37cd7","name":"Download File1","type":"n8n-nodes-base.telegram","position":[-1040,-280],"webhookId":"00c7755c-cd84-4aa4-89fe-c56f1f0cb50d","parameters":{"fileId":"={{ $json.message.voice.file_id }}","resource":"file"},"credentials":{"telegramApi":{"id":"GX0f93u8bE9meFhE","name":"customer service"}},"typeVersion":1.2},{"id":"578c6f2d-d738-49d3-95f4-6de6a48c5754","name":"Transcribe1","type":"@n8n/n8n-nodes-langchain.openAi","position":[-820,-280],"parameters":{"options":{},"resource":"audio","operation":"transcribe"},"credentials":{"openAiApi":{"id":"OQJASLp1qn1StvpI","name":"OpenAi account"}},"typeVersion":1.6},{"id":"68b40dcf-46a0-47e8-9f63-ce020f08c4c6","name":"Telegram Trigger1","type":"n8n-nodes-base.telegramTrigger","position":[-1480,-180],"webhookId":"75096a78-a466-4f4e-bc0d-f68e9e952231","parameters":{"updates":["message"],"additionalFields":{}},"credentials":{"telegramApi":{"id":"1vaRNATU5x2lDpH2","name":"supachat"}},"typeVersion":1.1},{"id":"e28131b3-4c13-4c5a-b6d1-e9be94970c9f","name":"Voice or Text","type":"n8n-nodes-base.switch","position":[-1260,-180],"parameters":{"rules":{"values":[{"outputKey":"Voice","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"612fa3b1-0e08-47f3-9455-746568546ab6","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $json.message.voice.file_id }}","rightValue":""}]},"renameOutput":true},{"outputKey":"Text","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"8c844924-b2ed-48b0-935c-c66a8fd0c778","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $json.message.text }}","rightValue":""}]},"renameOutput":true}]},"options":{}},"typeVersion":3.2},{"id":"b8d80841-beeb-43f9-a51b-3ea3683c4ba1","name":"Text","type":"n8n-nodes-base.set","position":[-940,-80],"parameters":{"options":{},"assignments":{"assignments":[{"id":"fe7ecc99-e1e8-4a5e-bdd6-6fce9757b234","name":"text","type":"string","value":"={{ $json.message.text }}"}]}},"typeVersion":3.4},{"id":"e5e1508a-ceb2-49fd-b3d2-ef87338a230b","name":"Merge","type":"n8n-nodes-base.merge","position":[-600,-180],"parameters":{},"typeVersion":3.1},{"id":"be9cde2d-e131-406b-a061-49193941e159","name":"Main agent","type":"@n8n/n8n-nodes-langchain.agent","position":[-320,-180],"parameters":{"text":"={{ $json.text }}","options":{"systemMessage":"# Database Assistant - Main Agent\n\nYou are an intelligent database assistant that helps users find and explore information from a structured database. You work with a specialized SQL sub-agent to retrieve data efficiently.\n\n## DATABASE SCHEMA:\n**[REPLACE WITH YOUR DATABASE SCHEMA]**\n```\nExample format:\nid (bigint, Primary Key)\nname (text)\ndescription (text)\ncategory (text)\n...\n```\n\n## CRITICAL OPERATIONAL RULES:\n- **ALWAYS use LIMIT in queries** - Default: 10, Maximum: 50\n- **NEVER request unlimited data** - this breaks the system\n- Use ORDER BY with LIMIT for meaningful results\n- Apply specific filters and conditions to narrow results\n\n## COMMUNICATION WITH SQL SUB-AGENT:\nSend clear, natural language requests:\n- \"Show me the 10 most popular [YOUR_ITEMS] in [CATEGORY_FIELD]\"\n- \"Find 5 newest verified entries containing '[KEYWORD]'\"\n- \"Get top 15 [YOUR_ITEMS] by [ACTIVITY_METRIC]\"\n- \"Search for entries with [PRICE_FIELD] less than [AMOUNT], limit 20\"\n\n## RESPONSE GUIDELINES:\nPresent results in a user-friendly format:\n- Highlight key information ([NAME_FIELD], [DESCRIPTION_FIELD], metrics)\n- Include relevant metadata ([VERIFICATION_FIELD], [POPULARITY_FIELD], [CATEGORIES_FIELD])\n- Provide actionable insights\n- Suggest related searches or refinements\n\n## DATA INTERPRETATION:\n**[CUSTOMIZE THESE FIELD DESCRIPTIONS]**\n- **[POPULARITY_FIELD]**: [Description of what this metric means]\n- **[ACTIVITY_FIELD]**: [Description of recent activity indicator]\n- **[VERIFICATION_FIELD]**: [Description of quality/trust indicator]\n- **[CATEGORY_FIELD]**: [Description of classification system]\n- **[PRICE_FIELD]**: [Description of pricing (0 = free, etc.)]\n\nAlways respect system limits and focus on delivering relevant, targeted results."},"promptType":"define"},"typeVersion":2},{"id":"ec7a16f3-fd62-4952-a074-3c044de6e86f","name":"SEND MESSAGE","type":"n8n-nodes-base.telegram","position":[120,-180],"webhookId":"1aa59dcd-d299-439f-9fdc-96eae710da9d","parameters":{"text":"={{ $json.output }}","chatId":"(YOUR CHAT ID)","additionalFields":{}},"credentials":{"telegramApi":{"id":"1vaRNATU5x2lDpH2","name":"supachat"}},"typeVersion":1.2},{"id":"4dfb46ad-d110-40e6-9a87-3c247fc2d8d3","name":"CALL QUERY AGENT","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[-20,80],"parameters":{"workflowId":{"__rl":true,"mode":"list","value":"Iw7dOCXYbpfRJrlW","cachedResultName":"query agent"},"description":"Call this tool for sql querys in natural language","workflowInputs":{"value":{},"schema":[],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false}},"typeVersion":2.2},{"id":"dd79a9fb-cf29-4266-a51d-114713e030c0","name":"ACCES DATABASE WITH DYNAMIC QUERYS","type":"n8n-nodes-base.postgres","position":[-980,360],"parameters":{"query":"{{ $json.output }}","options":{"largeNumbersOutput":"numbers","replaceEmptyStrings":true},"operation":"executeQuery"},"credentials":{"postgres":{"id":"6uE1gPELXSqR1Wgn","name":"Postgres accou"}},"typeVersion":2.6},{"id":"a302abcd-e6a0-4150-bcd7-84c549c1dc94","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1600,-540],"parameters":{"color":6,"width":1960,"height":800,"content":"# MAIN AGENT"},"typeVersion":1},{"id":"cfcf980f-e037-4c6a-9dd3-7ba4359f6b44","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-1600,260],"parameters":{"color":4,"width":1220,"height":440,"content":"# SUB AGENT"},"typeVersion":1},{"id":"4aaa94db-f919-44d4-9c0f-c703d3838e94","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-2320,-540],"parameters":{"color":2,"width":1780,"height":1760,"content":"# Setup & Configuration Guide\n\n## 📋 **Setup Checklist**\n```\n□ Install N8N workflow platform\n□ Set up PostgreSQL database\n□ Configure AI Agent nodes\n□ Test sub-workflow connection\n□ Validate query limits\n□ Deploy and monitor\n```\n\n---\n\n## 🔧 **Database Configuration**\n```\n🎯 CRITICAL SETUP STEPS:\n1. Create your PostgreSQL table\n2. Replace [YOUR_TABLE_NAME] in templates\n3. Update database schema in both agents\n4. Set connection credentials in N8N\n5. Test database connectivity\n```\n\n---\n\n## 🤖 **Main Agent Setup**\n```\n📍 WHAT TO REPLACE:\n• [YOUR_DATABASE_SCHEMA] → Your actual table structure\n• [YOUR_ITEMS] → What you're querying (products, users, etc.)\n• [CATEGORY_FIELD] → Your category column name\n• [POPULARITY_FIELD] → Your popularity metric column\n• [PRICE_FIELD] → Your price column name\n```\n\n---\n\n## ⚙️ **Sub-Agent Configuration**\n```\n🔄 TEMPLATE REPLACEMENTS:\n• [YOUR_TABLE_NAME] → Actual table name\n• [field_name] → Your column names\n• [verified_field] → Your verification column\n• [popularity_field] → Your popularity column\n• [description_field] → Your description column\n```\n\n---\n\n## 🚨 **Critical System Limits**\n```\n⚠️ NEVER FORGET:\n• Default LIMIT: 10 results\n• Maximum LIMIT: 50 results\n• NO unlimited queries allowed\n• Always use ORDER BY with LIMIT\n• System will break without limits!\n```\n\n---\n\n## 🔗 **Workflow Architecture**\n```\n┌─────────────────┐\n│   USER QUERY    │\n└─────────┬───────┘\n          │\n┌─────────▼───────┐\n│   MAIN AGENT    │ ← Interprets user needs\n└─────────┬───────┘\n          │\n┌─────────▼───────┐\n│   SUB-AGENT     │ ← Generates SQL query\n└─────────┬───────┘\n          │\n┌─────────▼───────┐\n│   DATABASE      │ ← Executes query\n└─────────┬───────┘\n          │\n┌─────────▼───────┐\n│   FORMATTED     │ ← Returns to user\n│   RESPONSE      │\n└─────────────────┘\n```"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"36903df7-c2e2-4b12-b58d-9c9fbeebea24","connections":{"Text":{"main":[[{"node":"Merge","type":"main","index":1}]]},"Merge":{"main":[[{"node":"Main agent","type":"main","index":0}]]},"Think":{"ai_tool":[[{"node":"Query agent","type":"ai_tool","index":0}]]},"Think1":{"ai_tool":[[{"node":"Main agent","type":"ai_tool","index":0}]]},"Main agent":{"main":[[{"node":"SEND MESSAGE","type":"main","index":0}]]},"Query agent":{"main":[[{"node":"ACCES DATABASE WITH DYNAMIC QUERYS","type":"main","index":0}]]},"Transcribe1":{"main":[[{"node":"Merge","type":"main","index":0}]]},"Voice or Text":{"main":[[{"node":"Download File1","type":"main","index":0}],[{"node":"Text","type":"main","index":0}]]},"Download File1":{"main":[[{"node":"Transcribe1","type":"main","index":0}]]},"CALL QUERY AGENT":{"ai_tool":[[{"node":"Main agent","type":"ai_tool","index":0}]]},"Telegram Trigger1":{"main":[[{"node":"Voice or Text","type":"main","index":0}]]},"Postgres Chat Memory":{"ai_memory":[[{"node":"Main agent","type":"ai_memory","index":0}]]},"OpenRouter Chat Model":{"ai_languageModel":[[{"node":"Query agent","type":"ai_languageModel","index":0}]]},"OpenRouter Chat Model1":{"ai_languageModel":[[{"node":"Main agent","type":"ai_languageModel","index":0}]]},"When Executed by Another Workflow":{"main":[[{"node":"Query agent","type":"main","index":0}]]}}}


name: Track n8n Workflow Changes Over Time with Compare Dataset & Google Sheets
author_name: Jimleuk
author_username: jimleuk
nodes_used: ["n8n-nodes-base.googleSheets"]
categories: []
created_at: 2025-06-17T22:43:15.197Z
updated_at: 2025-06-17T22:43:15.197Z
url: https://n8n.io/workflows/5013
scraped_at: 2025-07-06 21:16:30
description:
  This n8n template runs daily to track and report on any changes made to workflows  on any n8n instance.

  Useful if a team is working within a single instance and you want to be notified of what workflows have changed since you last visited them. Another use-case might be monitoring your managed instances for clients and being alerted when changes are made without your knowledge.

  See a sample Gsheet here: https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=sharing

  How it works
  A scheduled trigger is set to run once a day to review all available workflows.
  An n8n node imports the workflows as json.
  The workflows are brought into a loop where each is first checked to see if it exists in the designated google sheet.
  If not, a new entry is created and skipped.
  If the workflow has been captured before, then the comparison subworkflow can be executed using the previous and current versions of the workflow json data.
  The subworkflow uses the compare dataset tool to calculate the changes to nodes and connections for the given workflow.
  The results are then recorded back to the google sheet for review.

  How to use
  Start with the n8n node and try to filter by the workflows you're interested in tracking.
  Set the scheduled trigger interval to match the frequency to suit how often your workflows are being edited.

  Customising the workflow
  Want to get fancy? Add in an AI agent to help determine changes between the previous and current versions of the workflow. Add contextual explanations to reveal the impact of the changes.

workflow_json:
  {"meta":{"instanceId":"408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9","templateCredsSetupCompleted":true},"nodes":[{"id":"f2bb0773-754c-4535-99c0-14617221f64b","name":"Schedule Trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-1100,100],"parameters":{"rule":{"interval":[{}]}},"typeVersion":1.2},{"id":"828cb1c8-f92a-4129-a6eb-4597ea809953","name":"Get Row","type":"n8n-nodes-base.googleSheets","position":[-100,100],"parameters":{"options":{},"filtersUI":{"values":[{"lookupValue":"={{ $json.id }}","lookupColumn":"id"}]},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=drivesdk","cachedResultName":"97. Workflow Template Changes"}},"credentials":{"googleSheetsOAuth2Api":{"id":"XHvC7jIRR8A2TlUl","name":"Google Sheets account"}},"typeVersion":4.6,"alwaysOutputData":true},{"id":"6511415e-afa9-439c-b417-944c69b2c691","name":"Row Exists?","type":"n8n-nodes-base.if","position":[80,100],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"45b02cff-5406-4158-bb14-31cadf88b062","operator":{"type":"object","operation":"notEmpty","singleValue":true},"leftValue":"={{ $json }}","rightValue":""}]}},"typeVersion":2.2},{"id":"1791d64d-fbb1-4143-8925-f2d3dd15e645","name":"Create New Entry","type":"n8n-nodes-base.googleSheets","position":[280,280],"parameters":{"columns":{"value":{"id":"={{ $('Get Values').item.json.id }}","name":"={{ $('Get Values').item.json.name }}","nodes":"={{ $('Get Values').item.json.nodes.toJsonString() }}","status":"={{ $('Get Values').item.json.status }}","history":"={{$now.toISO() }} [info] Initiated","connections":"={{ $('Get Values').item.json.connections.toJsonString() }}","last_updated":"={{ $('Get Values').item.json.updatedAt }}"},"schema":[{"id":"id","type":"string","display":true,"removed":false,"required":false,"displayName":"id","defaultMatch":true,"canBeUsedToMatch":true},{"id":"name","type":"string","display":true,"required":false,"displayName":"name","defaultMatch":false,"canBeUsedToMatch":true},{"id":"status","type":"string","display":true,"removed":false,"required":false,"displayName":"status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"last_updated","type":"string","display":true,"required":false,"displayName":"last_updated","defaultMatch":false,"canBeUsedToMatch":true},{"id":"summary","type":"string","display":true,"required":false,"displayName":"summary","defaultMatch":false,"canBeUsedToMatch":true},{"id":"history","type":"string","display":true,"required":false,"displayName":"history","defaultMatch":false,"canBeUsedToMatch":true},{"id":"nodes","type":"string","display":true,"required":false,"displayName":"nodes","defaultMatch":false,"canBeUsedToMatch":true},{"id":"connections","type":"string","display":true,"removed":false,"required":false,"displayName":"connections","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["id"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{"useAppend":true},"operation":"append","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=drivesdk","cachedResultName":"97. Workflow Template Changes"}},"credentials":{"googleSheetsOAuth2Api":{"id":"XHvC7jIRR8A2TlUl","name":"Google Sheets account"}},"typeVersion":4.6},{"id":"56eacb4e-8c1d-454e-926b-3e91efc23639","name":"Compare Datasets","type":"n8n-nodes-base.compareDatasets","position":[-280,780],"parameters":{"options":{},"mergeByFields":{"values":[{"field1":"type","field2":"type"},{"field1":"name","field2":"name"}]}},"typeVersion":2.3},{"id":"1357e5ee-e456-4e71-8a84-1fbe22e879bf","name":"Current State","type":"n8n-nodes-base.set","position":[780,-20],"parameters":{"options":{},"assignments":{"assignments":[{"id":"a0306005-1c90-4e03-999c-0178663ff406","name":"name","type":"string","value":"={{ $('Get Values').item.json.name }}"},{"id":"847207dd-96a1-4d32-b854-d2965e34a44f","name":"nodes","type":"array","value":"={{ $('Get Values').item.json.nodes }}"},{"id":"e44844d9-b224-43c6-90f0-4e740b0da7fb","name":"connections","type":"array","value":"={{ $('Get Values').item.json.connections }}"},{"id":"e230a396-d27c-4604-b682-39217a40581a","name":"status","type":"string","value":"={{ $('Get Values').item.json.active ? 'active' : 'inactive' }}"}]}},"typeVersion":3.4},{"id":"6f97fba9-82d1-43b4-a51d-3bf9955a8d60","name":"Previous State","type":"n8n-nodes-base.set","position":[600,-20],"parameters":{"options":{},"assignments":{"assignments":[{"id":"98e1e832-ea3c-4bf9-862f-eb6f0c7892a3","name":"name","type":"string","value":"={{ $json.name }}"},{"id":"7594680d-0552-464d-9b2c-4ded8fdc3455","name":"nodes","type":"array","value":"={{ $json.nodes.parseJson() }}"},{"id":"5de5aab3-3236-4d47-88cb-701168aca8b8","name":"connections","type":"array","value":"={{ $json.connections.parseJson() }}"},{"id":"07c50e91-42ba-4fbb-be86-5b999c267541","name":"status","type":"string","value":"={{ $json.status }}"}]}},"typeVersion":3.4},{"id":"d50929da-1948-4283-a19d-4973d9c74acd","name":"Loop Over Items","type":"n8n-nodes-base.splitInBatches","position":[-500,100],"parameters":{"options":{}},"typeVersion":3},{"id":"2ec9bffd-4da4-41e5-9bb1-f2e1ace7db17","name":"Added Nodes","type":"n8n-nodes-base.aggregate","position":[-20,580],"parameters":{"options":{},"aggregate":"aggregateAllItemData","destinationFieldName":"added"},"typeVersion":1},{"id":"2f07ae8b-fea4-4e01-bfae-0b9a689662bf","name":"Same Nodes","type":"n8n-nodes-base.aggregate","position":[-20,720],"parameters":{"options":{},"aggregate":"aggregateAllItemData","destinationFieldName":"unchanged"},"typeVersion":1},{"id":"53e3083c-cf50-4361-bb70-bb6f1498c5b4","name":"Different Nodes","type":"n8n-nodes-base.aggregate","position":[-20,880],"parameters":{"options":{},"aggregate":"aggregateAllItemData","destinationFieldName":"changed"},"typeVersion":1},{"id":"e28eb560-0fae-43a4-9e1f-1c8346d18ac0","name":"Removed Nodes","type":"n8n-nodes-base.aggregate","position":[-20,1020],"parameters":{"options":{},"aggregate":"aggregateAllItemData","destinationFieldName":"removed"},"typeVersion":1},{"id":"c08719a3-b81a-4ee2-a6b8-d0463f70ccfe","name":"Report Nodes","type":"n8n-nodes-base.set","position":[420,1000],"parameters":{"mode":"raw","options":{},"jsonOutput":"={{\n{\n  \"nodes\": {\n    \"added_total\": $json.added?.length ?? 0,\n    \"added_names\": $json.added?.map(node =>\n      `${node.name} (${node.type.split('.').last()})`) ?? [],\n    \"removed_total\": $json.removed?.length ?? 0,\n    \"removed_names\": $json.removed?.map(node => `${node.name} (${node.type.split('.').last()})`) ?? []\n  }\n}\n}}"},"typeVersion":3.4},{"id":"900b67e3-465e-4e1d-8003-bdb312307569","name":"Compare Datasets1","type":"n8n-nodes-base.compareDatasets","position":[-280,1420],"parameters":{"options":{},"mergeByFields":{"values":[{"field1":"key","field2":"key"},{"field1":"node","field2":"node"},{"field1":"index","field2":"index"}]}},"typeVersion":2.3},{"id":"63e56c07-510e-4d28-a799-889cf94ef927","name":"Added Connections","type":"n8n-nodes-base.aggregate","position":[-20,1220],"parameters":{"options":{},"aggregate":"aggregateAllItemData","destinationFieldName":"added"},"typeVersion":1},{"id":"42e3117e-2539-4667-bc99-263d46526fb4","name":"Same Connections","type":"n8n-nodes-base.aggregate","position":[-20,1360],"parameters":{"options":{},"aggregate":"aggregateAllItemData","destinationFieldName":"unchanged"},"typeVersion":1},{"id":"cc09e996-b3af-4436-8eb2-8849745f3f76","name":"Different Connections","type":"n8n-nodes-base.aggregate","position":[-20,1520],"parameters":{"options":{},"aggregate":"aggregateAllItemData","destinationFieldName":"changed"},"typeVersion":1},{"id":"658b2c72-8ff7-41c2-b4f9-a09109a408d9","name":"Removed Connections","type":"n8n-nodes-base.aggregate","position":[-20,1660],"parameters":{"options":{},"aggregate":"aggregateAllItemData","destinationFieldName":"removed"},"typeVersion":1},{"id":"ca385cad-e275-4c5a-a880-9ac2ae0f1cf1","name":"Report Connections","type":"n8n-nodes-base.set","position":[420,1220],"parameters":{"mode":"raw","options":{},"jsonOutput":"={{\n{\n  \"connections\": {\n    \"added_total\": $json.added?.length ?? 0,\n    \"added_names\": $json.added?.map(node => `${node.key} [to] ${node.node}`) ?? [],\n    \"removed_total\": $json.removed?.length ?? 0,\n    \"removed_names\": $json.removed?.map(node => `${node.key} [to] ${node.node}`) ?? [],\n    \n  }\n}\n}}"},"typeVersion":3.4},{"id":"331d7764-752d-4b18-9b41-5c5f98997e13","name":"Merge Nodes Diff","type":"n8n-nodes-base.merge","position":[200,780],"parameters":{"mode":"combine","options":{"includeUnpaired":true},"combineBy":"combineByPosition","numberInputs":4},"typeVersion":3.2},{"id":"97a3ce94-acbb-40bd-b360-5891c62fbdfa","name":"Merge Connections Diff","type":"n8n-nodes-base.merge","position":[200,1420],"parameters":{"mode":"combine","options":{"includeUnpaired":true},"combineBy":"combineByPosition","numberInputs":4},"typeVersion":3.2},{"id":"ffe4301e-ad39-40e0-ae5b-c3ce3ed1cc32","name":"Merge Reports","type":"n8n-nodes-base.merge","position":[640,1120],"parameters":{"mode":"combine","options":{},"combineBy":"combineByPosition"},"typeVersion":3.2},{"id":"0999ab7d-8227-4e6e-a08f-9821d806bd8e","name":"Has UpdatedAt Changed?","type":"n8n-nodes-base.if","position":[280,100],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"e91f9db3-228c-47e4-a982-df0f73ebad26","operator":{"type":"dateTime","operation":"notEquals"},"leftValue":"={{ $('Get All Workflows').item.json.updatedAt }}","rightValue":"={{ $json.last_updated }}"}]}},"typeVersion":2.2},{"id":"f37d8fd6-cad6-4504-ae67-7172732b95ad","name":"When Executed by Another Workflow","type":"n8n-nodes-base.executeWorkflowTrigger","position":[-1060,1120],"parameters":{"workflowInputs":{"values":[{"name":"jobType"},{"name":"data","type":"object"}]}},"typeVersion":1.1},{"id":"c9930943-9348-469c-a500-2e06973b96b1","name":"Switch","type":"n8n-nodes-base.switch","position":[-860,1120],"parameters":{"rules":{"values":[{"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"95d54b19-77f5-4559-b5a2-8cb3d6a608f5","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.jobType }}","rightValue":"diff"}]}}]},"options":{}},"typeVersion":3.2},{"id":"ec179774-ef5c-4e37-8476-ddfa7a32ed8b","name":"Split Conn Previous","type":"n8n-nodes-base.splitOut","position":[-500,1400],"parameters":{"options":{},"fieldToSplitOut":"data.previous.connections"},"typeVersion":1},{"id":"85ca03c4-8eb1-4477-8249-5f1d2235230f","name":"Split Conn Current","type":"n8n-nodes-base.splitOut","position":[-500,1220],"parameters":{"options":{},"fieldToSplitOut":"data.current.connections"},"typeVersion":1},{"id":"7d54b755-8402-40b6-8410-2f4010dc0c1a","name":"Split Nodes Current","type":"n8n-nodes-base.splitOut","position":[-500,860],"parameters":{"options":{},"fieldToSplitOut":"data.current.nodes"},"typeVersion":1},{"id":"2b7f1d6c-04ae-4e96-8004-2b91d94aa7fb","name":"Split Nodes Previous","type":"n8n-nodes-base.splitOut","position":[-500,1020],"parameters":{"options":{},"fieldToSplitOut":"data.previous.nodes"},"typeVersion":1},{"id":"7885842f-23b4-4963-85b3-ab24a536a645","name":"Calculate Template Diffs","type":"n8n-nodes-base.executeWorkflow","position":[960,-20],"parameters":{"mode":"each","options":{"waitForSubWorkflow":true},"workflowId":{"__rl":true,"mode":"id","value":"={{ $workflow.id }}"},"workflowInputs":{"value":{"data":"={{\n{\n  \"current\": $('Current State').item.json,\n  \"previous\": $('Previous State').item.json,\n}\n}}","jobType":"diff"},"schema":[{"id":"jobType","type":"string","display":true,"removed":false,"required":false,"displayName":"jobType","defaultMatch":false,"canBeUsedToMatch":true},{"id":"data","type":"object","display":true,"removed":false,"required":false,"displayName":"data","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":true}},"typeVersion":1.2},{"id":"155f0a4f-627a-43b8-824c-929d521dd2b8","name":"Update Entry","type":"n8n-nodes-base.googleSheets","position":[1580,-20],"parameters":{"columns":{"value":{"id":"={{ $('Get Values').item.json.id }}","name":"={{ $('Get Values').item.json.name }}","nodes":"={{ $('Get Values').item.json.nodes.toJsonString() }}","status":"={{ $('Get Values').item.json.status }}","history":"={{\n$('Current State').item.json.status !== $('Previous State').item.json.status\n  ? `{$now.toISO()} [status] ` + (\n    $('Current State').item.json.status === 'active'\n    ? 'Workflow was activated'\n    : 'Workflow was deactivated'\n  )\n  : ''\n}}\n{{$now.toISO() }} [connections] {{ $json.connections.added_total }} added, {{ $json.connections.removed_total }} removed\n{{$now.toISO() }} [nodes] {{ $json.nodes.added_total }} added, {{ $json.nodes.removed_total }} removed\n{{ $('Has UpdatedAt Changed?').item.json.history }}","summary":"={{\n$('Current State').item.json.status !== $('Previous State').item.json.status\n  ? (\n    $('Current State').item.json.status === 'active'\n    ? 'Workflow was activated'\n    : 'Workflow was deactivated'\n  )\n  : ''\n}}\n{{\n$json.nodes.added_total > 0\n  ? [\n    `The nodes added (${$json.nodes.added_total}) were:`,\n    $json.nodes.added_names.join(', ')\n  ].join(' ')\n  : ''\n}}.\n{{\n$json.nodes.removed_total > 0\n  ? [\n    `The nodes removed (${$json.nodes.removed_total}) were:`,\n    $json.nodes.removed_names.join(', ')\n  ].join(' ')\n  : ''\n}}.\n{{\n$json.connections.added_total > 0\n  ? [\n    `The connections added (${$json.connections.added_total}) were:`,\n    $json.connections.added_names.join(', ')\n  ].join(' ')\n  : ''\n}}\n{{\n$json.connections.removed_total > 0\n  ? [\n    `The connections removed (${$json.connections.removed_total}) were:`,\n    $json.connections.removed_names.join(', ')\n  ].join(' ')\n  : ''\n}}","connections":"={{ $('Get Values').item.json.connections.toJsonString() }}","last_updated":"={{ $('Get Values').item.json.updatedAt }}"},"schema":[{"id":"id","type":"string","display":true,"removed":false,"required":false,"displayName":"id","defaultMatch":true,"canBeUsedToMatch":true},{"id":"name","type":"string","display":true,"required":false,"displayName":"name","defaultMatch":false,"canBeUsedToMatch":true},{"id":"status","type":"string","display":true,"removed":false,"required":false,"displayName":"status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"last_updated","type":"string","display":true,"required":false,"displayName":"last_updated","defaultMatch":false,"canBeUsedToMatch":true},{"id":"summary","type":"string","display":true,"required":false,"displayName":"summary","defaultMatch":false,"canBeUsedToMatch":true},{"id":"history","type":"string","display":true,"required":false,"displayName":"history","defaultMatch":false,"canBeUsedToMatch":true},{"id":"nodes","type":"string","display":true,"required":false,"displayName":"nodes","defaultMatch":false,"canBeUsedToMatch":true},{"id":"connections","type":"string","display":true,"removed":false,"required":false,"displayName":"connections","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["id"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{"useAppend":true},"operation":"appendOrUpdate","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=drivesdk","cachedResultName":"97. Workflow Template Changes"}},"credentials":{"googleSheetsOAuth2Api":{"id":"XHvC7jIRR8A2TlUl","name":"Google Sheets account"}},"typeVersion":4.6},{"id":"e16b0e69-5eee-4b51-9a5e-a653833a5d26","name":"Get Values","type":"n8n-nodes-base.set","position":[-280,100],"parameters":{"options":{},"assignments":{"assignments":[{"id":"0bd0d75d-3a1b-4e50-b496-6d33edebda8b","name":"id","type":"string","value":"={{ $json.id }}"},{"id":"07f2d234-c5d6-41ab-9198-80b139e898ae","name":"name","type":"string","value":"={{ $json.name }}"},{"id":"2596e1bd-a2d6-4c51-9797-b029ceb57d07","name":"nodes","type":"array","value":"={{ $json.nodes.map(node => ({ name: node.name, type: node.type })) }}"},{"id":"4182dc9c-8d40-438a-b8bb-db2f86632110","name":"connections","type":"array","value":"={{\n(function(connections){\n  return connections\n    .keys()\n    .flatMap(key =>\n      connections[key].keys().map(subkey =>\n        connections[key][subkey].flatMap(node =>\n          node.map(item =>\n            ({ key, node: item.node, index: item.index })\n          )\n        )\n      )\n    )\n})($json.connections)\n}}"},{"id":"82e3cb86-123a-4ae8-9dbe-0f613785feb6","name":"updatedAt","type":"string","value":"={{ $json.updatedAt }}"},{"id":"e98aaa3e-174d-456b-8289-c1d2025b986d","name":"status","type":"string","value":"={{ $json.active ? 'active' : 'inactive' }}"}]}},"typeVersion":3.4},{"id":"f98f2311-879c-4cfa-8498-dbd5d063f7a4","name":"set non-update response","type":"n8n-nodes-base.set","position":[1600,280],"parameters":{"options":{},"assignments":{"assignments":[{"id":"809ff45c-ff14-4195-b132-353e5cc49803","name":"id","type":"string","value":"={{ $json.id }}"},{"id":"77252bda-65ce-4e2b-852c-4c9dc7ce457e","name":"is_updated","type":"boolean","value":false}]}},"typeVersion":3.4},{"id":"b02b7552-68d4-40fc-a237-5a5d101a8d37","name":"Set Response","type":"n8n-nodes-base.set","position":[1820,280],"parameters":{"options":{},"assignments":{"assignments":[{"id":"99dccb72-bc38-47e9-9607-f7ef2d146293","name":"id","type":"string","value":"={{ $json.id }}"},{"id":"384725e9-bdc2-405b-8c1c-ab68b7a656f0","name":"is_updated","type":"boolean","value":"={{ $json.is_updated ?? true }}"}]}},"typeVersion":3.4},{"id":"ff36d209-0b29-443f-9dc8-33024ed9fa81","name":"Has Node or Connection Updates?","type":"n8n-nodes-base.if","position":[1340,-20],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"or","conditions":[{"id":"81db3948-7061-4ef1-a883-498dc03a2ab4","operator":{"type":"number","operation":"gt"},"leftValue":"={{ $json.nodes.added_total }}","rightValue":0},{"id":"4aad2fa6-dac1-430e-9f41-1c315cc9aa1c","operator":{"type":"number","operation":"gt"},"leftValue":"={{ $json.nodes.removed_total }}","rightValue":0},{"id":"b8f0889d-9b6a-4de6-b82e-e17e7135508d","operator":{"type":"number","operation":"gt"},"leftValue":"={{ $json.connections.added_total }}","rightValue":0},{"id":"c6a5ba18-6e40-4ae5-b703-6f985fd49b66","operator":{"type":"number","operation":"gt"},"leftValue":"={{ $json.connections.removed_total }}","rightValue":0}]}},"typeVersion":2.2},{"id":"89fbe71d-dd20-4b07-a203-c7ffb77750a7","name":"GSheets Rate Limit","type":"n8n-nodes-base.wait","position":[2020,280],"webhookId":"efe9a371-126f-4d73-9128-04b272222a9b","parameters":{"amount":3},"typeVersion":1.1},{"id":"9994e65f-2825-4ad8-9ce7-bcc9745c6346","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1200,-100],"parameters":{"color":7,"width":520,"height":400,"content":"## 1. Get Workflows To Track\n[Learn more about the n8n node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.n8n/)\n\nTo start, we'll need the json templates of the workflows that exist in the n8n instance. We can easily get these by using the n8n node. You may want to further filter down workflow depending on which ones you want to track. "},"typeVersion":1},{"id":"47202dc8-880d-48e4-b58a-a681d7dc56a2","name":"Get All Workflows","type":"n8n-nodes-base.n8n","position":[-880,100],"parameters":{"limit":25,"filters":{"activeWorkflows":false},"returnAll":false,"requestOptions":{}},"credentials":{"n8nApi":{"id":"5vELmsVPmK4Bkqkg","name":"n8n account"}},"typeVersion":1},{"id":"d1c2137f-2ac9-47a9-998d-6e17c8492793","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-620,-100],"parameters":{"color":7,"width":1080,"height":620,"content":"## 2. Create GSheet Entry If Workflow is New\n[Read more about the loop node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.splitinbatches)\n\nNext, we'll need to determine which workflows are currently new vs already being tracked. This is important as we can only compare workflow versions if we have a previous copy of it. If a workflow doesn't have an entry in our sheet then we can presume it's new and no comparison is necessary as of yet."},"typeVersion":1},{"id":"d4fa75b8-f1be-4dfd-994e-7458ef945016","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[500,-200],"parameters":{"color":7,"width":680,"height":380,"content":"## 3. Calculate Changes Since Last Update\n[Read more about the Execute Workflow node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow/)\n\nIf a previous version exists, we'll can compare it with the current versions to workout what exactly has changed. Here, I'll pass both versions of the workflow's json to a subworkflow which can compare the two."},"typeVersion":1},{"id":"c0044b95-e9ed-40ba-b602-ef7822637773","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[1220,-200],"parameters":{"color":7,"width":580,"height":380,"content":"## 5. Update GSheet Entry with Changes\n[Read more about the Google Sheets node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.googlesheets)\n\nThe resulting list of changes of the workflow are updated in the Google sheet for review. From here, it's possible to connect messaging and/or notification platforms to alert on changes which may break the business processes or worse!"},"typeVersion":1},{"id":"7a83901c-3ed0-41c2-8f81-55d1508d0f94","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-1200,840],"parameters":{"color":7,"width":600,"height":220,"content":"## 4. Calculate Differences in Nodes & Connections\n[Learn more about the Compare Datasets node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.comparedatasets)\n\nOur comparison focuses on changes between nodes and connections. It does this by running both the previous and current versions of the workflow json through the \"Compare dataset\" node to find the differences. Using this node, we're able to determine how many nodes and/or connections were added or removed."},"typeVersion":1},{"id":"49553752-1bba-44d1-ab92-4a4130dfa388","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-1660,-280],"parameters":{"width":420,"height":960,"content":"## Try It Out!\n### This n8n template runs daily to track and report on any changes to available workflows on an n8n instance.\n\nUseful if a team is working within a single instance and you want to be notified of what workflows have changed since you last visited them. Another use-case might be monitoring your managed instances for clients and being alerted when changes are made without your knowledge.\n\nSee a sample Gsheet here: [https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=sharing](https://docs.google.com/spreadsheets/d/1dOHSfeE0W_qPyEWj5Zz0JBJm8Vrf_cWp-02OBrA_ZYc/edit?usp=sharing)\n\n### How it works\n* A scheduled trigger is set to run once a day to review all available workflows.\n* An n8n node imports the workflows as json.\n* The workflows are brought into a loop where each is first checked to see if it exists in the designated google sheet.\n* If not, a new entry is created and skipped.\n* If the workflow has been captured before, then the comparison subworkflow can be executed using the previous and current versions of the workflow json data.\n* The subworkflow uses the compare dataset tool to calculate the changes to nodes and connections for the given workflow.\n* The results are then recorded back to the google sheet for review.\n\n### How to use\n* Start with the n8n node and try to filter by the workflows you're interested in tracking.\n* Set the scheduled trigger interval to match the frequency to suit how often your workflows are being edited.\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!\n\nHappy Hacking!"},"typeVersion":1}],"connections":{"Switch":{"main":[[{"node":"Split Nodes Current","type":"main","index":0},{"node":"Split Nodes Previous","type":"main","index":0},{"node":"Split Conn Current","type":"main","index":0},{"node":"Split Conn Previous","type":"main","index":0}]]},"Get Row":{"main":[[{"node":"Row Exists?","type":"main","index":0}]]},"Get Values":{"main":[[{"node":"Get Row","type":"main","index":0}]]},"Same Nodes":{"main":[[{"node":"Merge Nodes Diff","type":"main","index":1}]]},"Added Nodes":{"main":[[{"node":"Merge Nodes Diff","type":"main","index":0}]]},"Row Exists?":{"main":[[{"node":"Has UpdatedAt Changed?","type":"main","index":0}],[{"node":"Create New Entry","type":"main","index":0}]]},"Report Nodes":{"main":[[{"node":"Merge Reports","type":"main","index":0}]]},"Set Response":{"main":[[{"node":"GSheets Rate Limit","type":"main","index":0}]]},"Update Entry":{"main":[[{"node":"Set Response","type":"main","index":0}]]},"Current State":{"main":[[{"node":"Calculate Template Diffs","type":"main","index":0}]]},"Removed Nodes":{"main":[[{"node":"Merge Nodes Diff","type":"main","index":3}]]},"Previous State":{"main":[[{"node":"Current State","type":"main","index":0}]]},"Different Nodes":{"main":[[{"node":"Merge Nodes Diff","type":"main","index":2}]]},"Loop Over Items":{"main":[[],[{"node":"Get Values","type":"main","index":0}]]},"Compare Datasets":{"main":[[{"node":"Added Nodes","type":"main","index":0}],[{"node":"Same Nodes","type":"main","index":0}],[{"node":"Different Nodes","type":"main","index":0}],[{"node":"Removed Nodes","type":"main","index":0}]]},"Create New Entry":{"main":[[{"node":"set non-update response","type":"main","index":0}]]},"Merge Nodes Diff":{"main":[[{"node":"Report Nodes","type":"main","index":0}]]},"Same Connections":{"main":[[{"node":"Merge Connections Diff","type":"main","index":1}]]},"Schedule Trigger":{"main":[[{"node":"Get All Workflows","type":"main","index":0}]]},"Added Connections":{"main":[[{"node":"Merge Connections Diff","type":"main","index":0}]]},"Compare Datasets1":{"main":[[{"node":"Added Connections","type":"main","index":0}],[{"node":"Same Connections","type":"main","index":0}],[{"node":"Different Connections","type":"main","index":0}],[{"node":"Removed Connections","type":"main","index":0}]]},"Get All Workflows":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"GSheets Rate Limit":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Report Connections":{"main":[[{"node":"Merge Reports","type":"main","index":1}]]},"Split Conn Current":{"main":[[{"node":"Compare Datasets1","type":"main","index":0}]]},"Removed Connections":{"main":[[{"node":"Merge Connections Diff","type":"main","index":3}]]},"Split Conn Previous":{"main":[[{"node":"Compare Datasets1","type":"main","index":1}]]},"Split Nodes Current":{"main":[[{"node":"Compare Datasets","type":"main","index":0}]]},"Split Nodes Previous":{"main":[[{"node":"Compare Datasets","type":"main","index":1}]]},"Different Connections":{"main":[[{"node":"Merge Connections Diff","type":"main","index":2}]]},"Has UpdatedAt Changed?":{"main":[[{"node":"Previous State","type":"main","index":0}],[{"node":"set non-update response","type":"main","index":0}]]},"Merge Connections Diff":{"main":[[{"node":"Report Connections","type":"main","index":0}]]},"set non-update response":{"main":[[{"node":"Set Response","type":"main","index":0}]]},"Calculate Template Diffs":{"main":[[{"node":"Has Node or Connection Updates?","type":"main","index":0}]]},"Has Node or Connection Updates?":{"main":[[{"node":"Update Entry","type":"main","index":0}],[{"node":"set non-update response","type":"main","index":0}]]},"When Executed by Another Workflow":{"main":[[{"node":"Switch","type":"main","index":0}]]}}}


name: End of Turn Detection for smoother AI agent chats with Telegram and Gemini
author_name: Jimleuk
author_username: jimleuk
categories: []
created_at: 2025-06-17T22:47:24.712Z
updated_at: 2025-06-17T22:47:24.712Z
url: https://n8n.io/workflows/5014
scraped_at: 2025-07-06 21:16:30
description:
  This n8n template demonstrates one approach to achieve a more natural and less frustration conversations with AI agents by reducing interrupts by predicting the end of user utterances.

  When we text or chat casually, it's not uncommon to break our sentences over multiple messages or when it comes to voice, break our speech with the odd pause or umms and ahhs. If an agent replies to every message, it's likely to interrupt us before we finish our thoughts and it can get very annoying!

  Previously, I demonstrated a simple technique for buffering each incoming message by 5 seconds but that approach still suffers in some scenarios when more time is needed. This technique has no arbitrary time limit and instead uses AI to figure out when its the agent's turn based on the user's message, allowing for the user to take all the time they need.

  How it works
  Telegram messages are received but no reply is generated for them by default. Instead they are sent to the prediction subworkflow to determine if a reply should be generated.
  The prediction subworkflow begins by checking Redis for the current user's prediction session state. If this is a new "utterance", it kicks off the "predict end of utterance" loop - the purpose of which is to buffer messages in a smart way!
  New users message can continue to be accepted by the workflow until enough is collected to allow our prediction classifier to determine the end of the utterance has been reached.
  The loop is then broken and the buffered chat messages are combined and sent to the AI agent to generate a response and sent to the user via the telegram node.
  The prediction session state is then deleted to signal the workflow is ready to start again with a new message.

  How to use
  This system sits between your preferred chat platform and the AI agent so all you need to do is replace the telegram nodes as required.
  Where LLM-only prediction isn't working well enough, consider more traditional code-based checking of heuristics to improve the detection.
  Ideally you'll want a fast but accurate LLM so your user isn't waiting longer than they have to - at time of writing Gemini-2.5-flash-lite was the fastest in testing but keep a look out for smaller and more powerful LLMs in the future.

  Requirements
  Gemini for LLM
  Redis for session management
  Telegram for chat platform

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.redis","n8n-nodes-base.telegram","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.memoryRedisChat","@n8n/n8n-nodes-langchain.lmChatGoogleGemini","@n8n/n8n-nodes-langchain.textClassifier"]

workflow_json:
  {"meta":{"instanceId":"408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9","templateCredsSetupCompleted":true},"nodes":[{"id":"dd511e76-27a0-47a1-b475-d00fffa22eb8","name":"Telegram Trigger","type":"n8n-nodes-base.telegramTrigger","position":[-1280,120],"webhookId":"dce8f9a4-86d1-4dd9-a83a-4de75185ae21","parameters":{"updates":["message"],"additionalFields":{}},"credentials":{"telegramApi":{"id":"Lk9x8q4NhLDMjfTV","name":"jimleuk_bot"}},"typeVersion":1.2},{"id":"fef3c7b6-ac57-4b83-8f21-2babd81d3b50","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[1280,320],"parameters":{"text":"={{\n$('Session Ref').first().json.data.messages?.parseJson()\n  .map(msg => msg.value)\n  .join(' ')\n}}","options":{"systemMessage":"Do not format your response in markdown, use plain text instead."},"promptType":"define"},"typeVersion":2},{"id":"084bfb67-c59b-44c4-a310-4c25743cd8f9","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[1260,520],"parameters":{"options":{},"modelName":"models/gemini-2.5-flash-preview-05-20"},"credentials":{"googlePalmApi":{"id":"dSxo6ns5wn658r8N","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"4733b8d3-427d-4724-a5a3-7eb787941494","name":"Redis Chat Memory","type":"@n8n/n8n-nodes-langchain.memoryRedisChat","position":[1420,520],"parameters":{"sessionKey":"=session/{{ $('Session Ref').first().json.data.from }}/agent","sessionIdType":"customKey","contextWindowLength":10},"credentials":{"redis":{"id":"zU4DA70qSDrZM1El","name":"Redis account (localhost)"}},"typeVersion":1.5},{"id":"8f7e6148-b1a5-46b5-934a-0c75f20898d8","name":"Get Values","type":"n8n-nodes-base.set","position":[-860,120],"parameters":{"options":{},"assignments":{"assignments":[{"id":"7cee3033-0615-43ac-93fd-5397c759e6a3","name":"from","type":"string","value":"={{ $json.message.chat.id }}"},{"id":"c2bb1875-7074-411f-a14a-42c699e5bdc1","name":"message","type":"string","value":"={{ $json.message.text }}"},{"id":"34d5087e-79be-4181-b839-0a55b95133e8","name":"createdAt","type":"string","value":"={{ $now.toISO() }}"}]}},"typeVersion":3.4},{"id":"52cc0bd2-bb0a-4c2c-a1a5-2a9104d891da","name":"Update Session","type":"n8n-nodes-base.redis","position":[-920,700],"parameters":{"key":"=session/{{ $('Prediction Subworkflow').item.json.from }}","value":"={{\n{\n  ...($('Get Session').item.json.data ?? {}),\n  messages: [\n    ...($('Get Session').item.json.data?.messages\n      ? $('Get Session').item.json.data?.messages.parseJson()\n      : []\n    ),\n    {\n      value: $('Prediction Subworkflow').item.json.message,\n      createdAt: $('Prediction Subworkflow').item.json.createdAt\n    }\n  ].toJsonString(),\n  from: $('Prediction Subworkflow').item.json.from\n}\n}}","expire":true,"keyType":"hash","operation":"set"},"credentials":{"redis":{"id":"zU4DA70qSDrZM1El","name":"Redis account (localhost)"}},"typeVersion":1},{"id":"7bdee33c-a2e7-49a3-b782-d045f3f46dd3","name":"Get Session","type":"n8n-nodes-base.redis","position":[-1100,700],"parameters":{"key":"=session/{{ $json.from }}","keyType":"hash","options":{},"operation":"get","propertyName":"data"},"credentials":{"redis":{"id":"zU4DA70qSDrZM1El","name":"Redis account (localhost)"}},"typeVersion":1},{"id":"0fc0b9eb-3553-4fdb-befc-7d7891305405","name":"Is Waiting?","type":"n8n-nodes-base.if","position":[-80,1020],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"0e37d8ff-3d04-4224-84cc-defa80dc4a8b","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $('Get Session').item.json.data?.state }}","rightValue":"waiting"}]}},"typeVersion":2.2},{"id":"de3eb7bb-81e0-4169-a6f4-286a1ac9a2f7","name":"Update Session1","type":"n8n-nodes-base.redis","position":[40,300],"parameters":{"key":"=session/{{ $('Session Ref').first().json.data.from }}","value":"={{\n{\n  state: 'waiting',\n  resumeUrl: $execution.resumeUrl\n}\n}}","expire":true,"keyType":"hash","operation":"set"},"credentials":{"redis":{"id":"zU4DA70qSDrZM1El","name":"Redis account (localhost)"}},"typeVersion":1},{"id":"c7fb3fba-9d6a-4c68-a995-5539ab6bcf63","name":"is New Session?","type":"n8n-nodes-base.if","position":[-560,700],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"71db97f1-e5ba-49d1-8a9a-b9df3a989c77","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ !$json.data?.state }}","rightValue":""}]}},"typeVersion":2.2},{"id":"8bbb222c-d3d1-4c03-931c-37f1d2d37df2","name":"Google Gemini Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[300,460],"parameters":{"options":{},"modelName":"models/gemini-2.5-flash-lite-preview-06-17"},"credentials":{"googlePalmApi":{"id":"dSxo6ns5wn658r8N","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"3a285fef-8c80-48dc-8e79-2c30ff9d351c","name":"Get Session2","type":"n8n-nodes-base.redis","position":[720,460],"parameters":{"key":"=session/{{ $('Session Ref').first().json.data.from }}","keyType":"hash","options":{},"operation":"get","propertyName":"data"},"credentials":{"redis":{"id":"zU4DA70qSDrZM1El","name":"Redis account (localhost)"}},"typeVersion":1},{"id":"e8254612-ff46-4165-ab93-a6c9d7a2c583","name":"Session Ref","type":"n8n-nodes-base.noOp","position":[-120,300],"parameters":{},"typeVersion":1},{"id":"bdd227f1-65fd-46d0-8e0c-23e812f83967","name":"Session Ended?","type":"n8n-nodes-base.if","position":[880,460],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"398277f7-9386-4f99-ab9c-f99fe59c872e","operator":{"type":"object","operation":"empty","singleValue":true},"leftValue":"={{ Object.assign({}, $json.data ?? {}) }}","rightValue":""}]}},"typeVersion":2.2},{"id":"a9611069-9cf9-4090-aa6e-cc6a3f4a0fa8","name":"Wait For Webhook","type":"n8n-nodes-base.wait","position":[560,460],"webhookId":"d753b11d-0a61-40e5-b1c4-d217e106eaac","parameters":{"resume":"webhook","options":{},"resumeUnit":"seconds","resumeAmount":20,"limitWaitTime":true},"typeVersion":1.1},{"id":"456d5b81-7eee-49fd-9b27-93e9e8fbe7b8","name":"Update Session2","type":"n8n-nodes-base.redis","position":[1620,320],"parameters":{"key":"=session/{{ $('Session Ref').first().json.data.from }}","operation":"delete"},"credentials":{"redis":{"id":"zU4DA70qSDrZM1El","name":"Redis account (localhost)"}},"typeVersion":1},{"id":"d778edf7-4152-4bd9-a720-a0a28db45369","name":"Is Bot command?","type":"n8n-nodes-base.if","position":[-1080,120],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"bff0d1a5-1d78-4af6-a643-b2fd28f10fba","operator":{"type":"string","operation":"startsWith"},"leftValue":"={{ $json.message.text }}","rightValue":"/"}]}},"typeVersion":2.2},{"id":"a465cb15-8faf-42fb-b00e-51af15c596da","name":"Predict End of Utterance","type":"@n8n/n8n-nodes-langchain.textClassifier","position":[200,300],"parameters":{"options":{"systemPromptTemplate":"=You are an NLP expert who predicts whether a message is the end of an turn/utterance i.e., whether the user's message is complete or if more parts of the message are likely to follow. Help predict the given message or partial message to determine whether it is now the agent's turn to respond to the user.\n\n## Techniques to use\n* Temporal Threshold (Inactivity Delay) - Use a decay model—each consecutive message shortens the threshold unless punctuation suggests completeness.\n* Punctuation Patterns - Strong indicators of message completeness: Ends with period ., question mark ?, or exclamation mark !. Ends with an emoji or newline after a complete sentence. Weak or uncertain indicators: Ellipsis ... → often implies continuation. Dash - or incomplete sentence → wait for more.\n* Linguistic Features - Lexical cues (last word, punctuation). Part-of-speech tags (is the sentence syntactically complete?). Message length and position in sequence. Semantic cues like discourse markers: \"anyway\", \"so\", \"that's all\"\n* Conversational Cues (Pragmatic Signals) - \"That's it\", \"Done\", \"Hope that helps\", \"Thanks\" → End markers. \"Let me continue\", \"Hold on\", \"Part 2\" → Continuation markers.\n\n### Sample Dataset\nLabel: 1 = end of utterance, 0 = continuation\n* \"Here's the plan for tomorrow.\" = 1,\n* \"First, we meet at 9am.\" = 0,\n* \"Then we head to the venue\" = 0,\n* \"...and set everything up.\" = 0,\n* \"Let me know if you're free!\" = 1,\n* \"Part 1 of the idea is this\" = 0,\n* \"More to come\" = 0,\n* \"That's all!\" = 1,\n* \"Thanks!\" = 1\n* \"Next, we should discuss logistics\" = 0"},"inputText":"={{\n$('Session Ref').item.json.data.messages.parseJson()\n  .map(msg => `[${msg.createdAt}] ${msg.value}`)\n  .join(' ')\n}}","categories":{"categories":[{"category":"end_of_utterance","description":"The user has reached their end of turn or end of utterance"},{"category":"has_more_to_follow","description":"The user has not finished their message or turn or reached their end of utterance"}]}},"typeVersion":1.1},{"id":"14dd091f-636b-4944-81b4-35da5f0f64b2","name":"Respond to User","type":"n8n-nodes-base.telegram","position":[1800,320],"webhookId":"c095b0ea-c349-4ab7-8b16-efa5f4c22299","parameters":{"text":"={{ $json.output }}","chatId":"={{ $('Session Ref').first().json.data.from }}","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"credentials":{"telegramApi":{"id":"Lk9x8q4NhLDMjfTV","name":"jimleuk_bot"}},"typeVersion":1.2},{"id":"b6ae259c-9fc4-481a-bd6d-f1b3a0dc2d28","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1360,-80],"parameters":{"color":7,"width":1020,"height":440,"content":"## 1. Accept Telegram messages\n[Read more about the Telegram Trigger](https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.telegramtrigger)\n\nThis template will only work with chat systems where not every incoming message needs a reply - this unfortunately rules out n8n's built in chat trigger. For demonstration purposes, we'll use Telegram and in this set up, we have designed it to capture as many messages from a single user as possible without blocking the execution."},"typeVersion":1},{"id":"33c5c000-5d3e-459a-814e-f2e5669e9592","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-1360,400],"parameters":{"color":7,"width":1020,"height":560,"content":"## 2. Determine If New Message\n[Learn more about the subworkflow trigger](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflowtrigger)\n\nOur goal is ultimately to not \"interrupt\" the user. We do so by buffering presumed partial messages until we can predict that the user has reached the end of what they want to say. Before we can do that however, we need to first determine if the message received is a new message or \"utterance\". For this task, we'll use simple session/state management via Redis to create temporary data to collect each incoming utterance and track our progress."},"typeVersion":1},{"id":"939f8f46-c7c1-468f-af83-2c4f15fca09b","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-240,780],"parameters":{"color":7,"width":660,"height":460,"content":"## 3. Prediction Loop Already Running? Let's Resume!\n[Read more about the HTTP node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/)\n\nUsing the session data, we can check if a prediction loop is already running and if so, resume it rather than starting a new one. The HTTP request is used to trigger the \"resume_url\" of the prediction loop wait node."},"typeVersion":1},{"id":"d36770f7-1992-4335-8e9d-01a73de44c0b","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-240,-60],"parameters":{"color":7,"width":1340,"height":800,"content":"## 2. Start of a New Utterance? Start the Prediction Wait Loop.\n[Learn more about the Text Classifier node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.text-classifier)\n\nPredicting when a user has finished their thought during a casual text or call is surprisingly difficult. Although some heuristics and natural language processing (NLP) tools exist, I wanted to explore whether large language models (LLMs) could effectively handle this task.\n\nI implemented a basic text classifier and fine-tuned its prompt to predict message completion. If the model determines a message is incomplete, the workflow pauses using a wait node. This node doesn't operate on a timer; instead, it needs to be triggered by a HTTP request to resume. The trick is when we get new messages, we use those executions to resume the paused wait node if it exists. Once the wait node resumes, it combined the new message with the previous messages and sends them to the classifier for a new prediction.\n\nThe loop continues until the model identifies the message as complete, at which point the full conversation is sent to the agent. As a fallback, if the session is somehow lost - maybe due to expiry, the loop is abandoned and the new chat message is sent to the agent instead."},"typeVersion":1},{"id":"d9dcc03f-8549-495e-969b-82c0f96c3057","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1160,80],"parameters":{"color":7,"width":840,"height":660,"content":"## 4. Send Reply Only When End of Utterance is Detected\n[Read more about the AI Agent node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/)\n\nFinally! With the buffered messages combined and sent to the agent, we're now able to generate a reply to the user. The end experience is seemingly much closer to a natural conversation with a human as there is no artificial delays needed.\n\nThe last thing to do then is to clear out the temporary session for the utterance. This allows our workflow to recognise the next chat message as a new utterance."},"typeVersion":1},{"id":"c242729b-0d95-4201-adee-b3a537d28eb1","name":"Resume Wait Node","type":"n8n-nodes-base.httpRequest","position":[140,1020],"parameters":{"url":"={{ $json.data.resumeUrl }}","options":{}},"typeVersion":4.2},{"id":"321e48ff-9389-408f-af97-e1590ce13e0c","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-1860,-300],"parameters":{"width":460,"height":1260,"content":"## Try It Out!\n### This n8n template demonstrates one approach to achieve a more natural and less frustration conversations with AI agents by reducing interrupts by predicting the end of user utterances.\n\nWhen we text or chat casually, it's not uncommon to break our sentences over multiple messages or when it comes to voice, break our speech with the odd pause or umms and ahhs. If an agent replies to every message, it's likely to interrupt us before we finish our thoughts and it can get very annoying!\n\nPreviously, I demonstrated a [simple technique for buffering each incoming message by 5 seconds](https://n8n.io/workflows/2346-enhance-customer-chat-by-buffering-messages-with-twilio-and-redis/) but that approach still suffers in some scenarios when more time is needed. This technique has no arbitrary time limit and instead uses AI to figure out when its the agent's turn based on the user's message, allowing for the user to take all the time they need.\n\n### How it works\n* Telegram messages are received but no reply is generated for them by default. Instead they are sent to the prediction subworkflow to determine if a reply should be generated.\n* The prediction subworkflow begins by checking Redis for the current user's prediction session state. If this is a new \"utterance\", it kicks off the \"predict end of utterance\" loop - the purpose of which is to buffer messages in a smart way!\n* New users message can continue to be accepted by the workflow until enough is collected to allow our prediction classifier to determine the end of the utterance has been reached.\n* The loop is then broken and the buffered chat messages are combined and sent to the AI agent to generate a response and sent to the user via the telegram node.\n* The prediction session state is then deleted to signal the workflow is ready to start again with a new message.\n\n### How to use\n* This system sits between your preferred chat platform and the AI agent so all you need to do is replace the telegram nodes as required.\n* Where LLM-only prediction isn't working well enough, consider more traditional code-based checking of heuristics to improve the detection.\n* Ideally you'll want a fast but accurate LLM so your user isn't waiting longer than they have to - at time of writing Gemini-2.5-flash-lite was the fastest in testing but keep a look out for smaller and more powerful LLMs in the future.\n\n### Requirements\n* Gemini for LLM\n* Redis for session management\n* Telegram for chat platform\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!\n\nHappy Hacking!"},"typeVersion":1},{"id":"f56fe585-7ece-49aa-813a-2d72b11d5d0f","name":"Call Prediction Subworkflow","type":"n8n-nodes-base.executeWorkflow","position":[-640,120],"parameters":{"options":{"waitForSubWorkflow":false},"workflowId":{"__rl":true,"mode":"id","value":"={{ $workflow.id }}"},"workflowInputs":{"value":{"from":"={{ $json.from }}","message":"={{ $json.message }}","createdAt":"={{ $json.createdAt }}"},"schema":[{"id":"from","type":"string","display":true,"removed":false,"required":false,"displayName":"from","defaultMatch":false,"canBeUsedToMatch":true},{"id":"message","type":"string","display":true,"removed":false,"required":false,"displayName":"message","defaultMatch":false,"canBeUsedToMatch":true},{"id":"createdAt","type":"string","display":true,"removed":false,"required":false,"displayName":"createdAt","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":true}},"typeVersion":1.2},{"id":"6d24bc9e-223e-48f8-b32d-84cabf1febfc","name":"Prediction Subworkflow","type":"n8n-nodes-base.executeWorkflowTrigger","position":[-1280,700],"parameters":{"workflowInputs":{"values":[{"name":"from"},{"name":"message"},{"name":"createdAt"}]}},"typeVersion":1.1},{"id":"f711ff8e-4b68-4379-8abe-33bc673bab1f","name":"Get Updated Session Values","type":"n8n-nodes-base.set","position":[-740,700],"parameters":{"options":{},"assignments":{"assignments":[{"id":"ed66f412-aa70-4838-9295-bed652d62bfd","name":"data","type":"object","value":"={{\n{\n  ...($('Get Session').item.json.data ?? {}),\n  messages: [\n    ...($('Get Session').item.json.data?.messages\n      ? $('Get Session').item.json.data?.messages.parseJson()\n      : []\n    ),\n    {\n      value: $('Prediction Subworkflow').item.json.message,\n      createdAt: $('Prediction Subworkflow').item.json.createdAt\n    }\n  ].toJsonString(),\n  from: $('Prediction Subworkflow').item.json.from\n}\n}}"}]}},"typeVersion":3.4}],"connections":{"AI Agent":{"main":[[{"node":"Update Session2","type":"main","index":0}]]},"Get Values":{"main":[[{"node":"Call Prediction Subworkflow","type":"main","index":0}]]},"Get Session":{"main":[[{"node":"Update Session","type":"main","index":0}]]},"Is Waiting?":{"main":[[{"node":"Resume Wait Node","type":"main","index":0}],[]]},"Session Ref":{"main":[[{"node":"Update Session1","type":"main","index":0}]]},"Get Session2":{"main":[[{"node":"Session Ended?","type":"main","index":0}]]},"Session Ended?":{"main":[[{"node":"AI Agent","type":"main","index":0}],[{"node":"Session Ref","type":"main","index":0}]]},"Update Session":{"main":[[{"node":"Get Updated Session Values","type":"main","index":0}]]},"Is Bot command?":{"main":[[],[{"node":"Get Values","type":"main","index":0}]]},"Respond to User":{"main":[[]]},"Update Session1":{"main":[[{"node":"Predict End of Utterance","type":"main","index":0}]]},"Update Session2":{"main":[[{"node":"Respond to User","type":"main","index":0}]]},"is New Session?":{"main":[[{"node":"Session Ref","type":"main","index":0}],[{"node":"Is Waiting?","type":"main","index":0}]]},"Telegram Trigger":{"main":[[{"node":"Is Bot command?","type":"main","index":0}]]},"Wait For Webhook":{"main":[[{"node":"Get Session2","type":"main","index":0}]]},"Redis Chat Memory":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"Prediction Subworkflow":{"main":[[{"node":"Get Session","type":"main","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Predict End of Utterance":{"main":[[{"node":"AI Agent","type":"main","index":0}],[{"node":"Wait For Webhook","type":"main","index":0}]]},"Google Gemini Chat Model1":{"ai_languageModel":[[{"node":"Predict End of Utterance","type":"ai_languageModel","index":0}]]},"Get Updated Session Values":{"main":[[{"node":"is New Session?","type":"main","index":0}]]},"Call Prediction Subworkflow":{"main":[[]]}}}


name: Find and email ANYONE on LinkedIn with OpenAI, Hunter & Gmail
author_name: Abhijay Vuyyuru
author_username: abhijayvuyyuru
categories: []
created_at: 2025-06-18T03:13:10.626Z
updated_at: 2025-06-18T03:13:10.626Z
url: https://n8n.io/workflows/5015
scraped_at: 2025-07-06 21:16:30
description:
  Setup Time

  5-10 minutes

  Problem

  🚨 LinkedIn search is BROKEN. Personalized cold-emailing takes hours!


  I waste hours on LinkedIn manually filtering profiles, reading summaries, hoping they’d reply—tedious, frustrating, inefficient.

  But even after finding the email IDs of the contacts, the job to be done is incomplete. 𝗜 𝘄𝗮𝗻𝘁 𝘁𝗼 𝘀𝘁𝗮𝗿𝘁 𝗮 𝗰𝗼𝗻𝘃𝗲𝗿𝘀𝗮𝘁𝗶𝗼𝗻 𝘄𝗶𝘁𝗵 𝘁𝗵𝗲𝘀𝗲 𝗰𝗼𝗻𝘁𝗮𝗰𝘁𝘀.

  If only I could type "𝘗𝘳𝘰𝘥𝘶𝘤𝘵 𝘮𝘢𝘯𝘢𝘨𝘦𝘳𝘴 𝘸𝘰𝘳𝘬𝘪𝘯𝘨 𝘰𝘯 𝘨𝘦𝘯𝘦𝘳𝘢𝘵𝘪𝘷𝘦 𝘈𝘐 𝘪𝘯 𝘠𝘰𝘶𝘛𝘶𝘣𝘦 𝘪𝘯 𝘕𝘦𝘸 𝘠𝘰𝘳𝘬" and seconds later have 10 personalized outreach emails in my Gmail drafts folder, ready for my review. 

  It would save me hours of research effort!

  Introducing LinkGPT, a LinkedIn Agent, an automated agentic workflow powered by n8n.

  Prerequisites: 
  Required accounts/API keys for Hunter.io, Google, and OpenAI.

  This would be helpful for:

  🎯 Job Seekers wanting direct outreach to hiring managers (everyone applies to multiple jobs, and crafting personal emails takes hours!)

  🎯 Recruiters looking to personalize candidate outreach at scale

  🎯 Sales & Founders aiming for targeted customer conversations 

  Step-by-step workflow:

  Takes 5-10 minutes to setup.

  Generate a Boolean search string for LinkedIn profiles.
  Perform authenticated Google searches using your query.
  Extract LinkedIn URLs and workplace context from the search results.
  Use OpenAI to extract first name, last name, and domain name from the context.
  Use Hunter.io to find emails of the contacts.
  Append all results to your connected Google Sheet. Columns: first_name, last_name, domain_name, email, context
  Read everything publicly available about your target profiles
  Identify common ground (shared backgrounds, interests, experiences)
  Craft highly personalized, thoughtful email drafts
  Automatically save tailored drafts in your Gmail and Google Sheets



  I put together a clear, step-by-step guide on setting this up yourself.

  Sample Query

  Sample:

  Input: "I am headed to NYC later this month, whom should I meet with that works in product management for gen AI products?"

  Output: List of 10 contacts with first name, last name, workplace, email address and context about them, and 10 personalized emails waiting for you review in your Gmail drafts folder 

nodes_used:
  ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest","n8n-nodes-base.hunter","n8n-nodes-base.gmail","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.openAi"]

workflow_json:
  {"id":"e49UBJheMiRF7iDk","meta":{"instanceId":"7b22476bf9699de09fe66fed92056e8ae798418cc9901fa9bd85bb46439116b8","templateCredsSetupCompleted":true},"name":"LinkedIn Agent v2","tags":[{"id":"V4LdVOYIGIbfdqvb","name":"linkedin","createdAt":"2025-06-11T18:52:18.612Z","updatedAt":"2025-06-11T18:52:18.612Z"},{"id":"qlvLkg4Mxoeos0VK","name":"cold email","createdAt":"2025-06-11T18:52:31.368Z","updatedAt":"2025-06-11T18:52:31.368Z"},{"id":"yt7Z3T0SDl1Coo7S","name":"hunter","createdAt":"2025-06-11T18:52:25.423Z","updatedAt":"2025-06-11T18:52:25.423Z"}],"nodes":[{"id":"0fa236a3-2e00-4710-ab5f-a5d237dcfa90","name":"Wait","type":"n8n-nodes-base.wait","position":[760,880],"webhookId":"39010e58-367a-490c-a827-0e06d5d47a51","parameters":{},"typeVersion":1.1},{"id":"5d57cbba-4061-4f2f-b4a1-f99ef47eedcc","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[440,400],"webhookId":"34291cf6-4908-4be5-9cf6-df085702abd2","parameters":{},"typeVersion":1.1},{"id":"af9ccdbe-30aa-451c-851c-3f2b6418c211","name":"Create a new sheet","type":"n8n-nodes-base.googleSheets","position":[1120,400],"parameters":{},"typeVersion":4.5},{"id":"36698cf4-3d75-491f-b4da-bdb7b6d2d3c1","name":"Add columns to new sheet","type":"n8n-nodes-base.googleSheets","position":[760,640],"parameters":{},"typeVersion":4.5},{"id":"84149de7-58b5-498c-aebc-ec79ec7317fa","name":"set page number for google search","type":"n8n-nodes-base.code","position":[1060,640],"parameters":{},"typeVersion":2},{"id":"119084c3-a1d8-4007-9421-764f4625d5dc","name":"Google Boolean Search","type":"n8n-nodes-base.httpRequest","position":[1080,880],"parameters":{},"typeVersion":4.2},{"id":"2ae7afc6-727d-4c25-8f3b-dc6e613b813b","name":"If desired results not reached","type":"n8n-nodes-base.if","position":[400,900],"parameters":{},"typeVersion":2.2},{"id":"650665b9-cb6e-4e69-b039-4962a9a0efca","name":"Appends the results to the sheet","type":"n8n-nodes-base.googleSheets","position":[380,1320],"parameters":{},"typeVersion":4.5},{"id":"5289c588-a2d0-41d9-94e9-5e1ab564c78f","name":"Code","type":"n8n-nodes-base.code","position":[4960,600],"parameters":{},"typeVersion":2},{"id":"5e6b2802-6710-4851-ab2e-4d29c9c5e644","name":"Extracts fname, lname, domainname","type":"n8n-nodes-base.code","position":[1080,1140],"parameters":{},"typeVersion":2},{"id":"f611ee14-5864-4032-8ae1-3342658be76f","name":"Extracts all linkedin urls and workplace context from the google http response","type":"n8n-nodes-base.code","position":[400,1140],"parameters":{},"typeVersion":2},{"id":"7b60c3e0-d6b3-4652-93d4-805bbe7f095c","name":"Adds 10 to start - Go to next page","type":"n8n-nodes-base.code","position":[100,900],"parameters":{},"typeVersion":2},{"id":"f19b8bac-a55f-43cf-bd74-fa59fc0c217c","name":"Generate a Boolean Search String","type":"@n8n/n8n-nodes-langchain.openAi","position":[740,400],"parameters":{},"retryOnFail":false,"typeVersion":1.8},{"id":"7b57464a-d650-465b-91fd-d87aa8884517","name":"Extract Contact Details","type":"@n8n/n8n-nodes-langchain.openAi","position":[680,1140],"parameters":{},"typeVersion":1.8},{"id":"18fba241-bb89-4468-bbf0-6bec4e75612c","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1240,840],"parameters":{"content":""},"typeVersion":1},{"id":"ebb1f62f-3206-46f3-873e-36d78eb134dc","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[660,1060],"parameters":{"content":""},"typeVersion":1},{"id":"e7283690-37fb-4ca6-8797-d0b07026e0a6","name":"Columns to add: linkedin_url, first_name, last_name, email, context, domain","type":"n8n-nodes-base.code","position":[420,640],"parameters":{},"typeVersion":2},{"id":"98eb8c1b-a90d-497b-865f-70db3a79ba4a","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[720,300],"parameters":{"content":""},"typeVersion":1},{"id":"463dc7e3-711b-4d9f-8b23-6622215e20e9","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[640,820],"parameters":{"content":""},"typeVersion":1},{"id":"db7b1096-5381-4daf-8aac-ab491921d862","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[60,760],"parameters":{"content":""},"typeVersion":1},{"id":"4a9d208c-c989-4630-a013-77aa9a3f9bd7","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[180,1280],"parameters":{"content":""},"typeVersion":1},{"id":"7b8fb208-bfc3-4d3a-b676-3fc9ea53c5c1","name":"Gmail","type":"n8n-nodes-base.gmail","position":[1260,1360],"webhookId":"e3c8a3f8-6dac-48e0-90c8-3fb9ac2213fb","parameters":{},"typeVersion":2.1},{"id":"1f3132e6-a3d1-4e94-9d3d-bd5ea6e333d0","name":"Extract subject and email body","type":"n8n-nodes-base.code","position":[700,1360],"parameters":{},"typeVersion":2},{"id":"b4396b3c-83aa-4255-92c1-98b910388101","name":"Personalized Cold-Email Generator","type":"@n8n/n8n-nodes-langchain.openAi","position":[1360,1140],"parameters":{},"typeVersion":1.8},{"id":"9822e7c5-1f6a-4c94-a997-d83f30a0160c","name":"Hunter","type":"n8n-nodes-base.hunter","position":[900,1360],"parameters":{},"executeOnce":true,"typeVersion":1},{"id":"c9813338-95b8-433c-b52b-c78c049575ec","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[860,1320],"parameters":{"content":""},"typeVersion":1},{"id":"28eddff1-1b6b-4d87-a650-0262d2f2ccde","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[1080,320],"parameters":{"content":""},"typeVersion":1},{"id":"e92fb3ad-c98b-4917-98d6-6de847af7425","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[1320,1060],"parameters":{"content":""},"typeVersion":1},{"id":"2b8c2dba-4b3c-486d-b765-7bae108802a3","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[1360,1340],"parameters":{"content":""},"typeVersion":1}],"active":false,"settings":{},"versionId":"70ebcd8c-5023-4fee-85af-c94683f7bba0","connections":{"Code":{"main":[[]]},"Wait":{"main":[[{"node":"Google Boolean Search","type":"main","index":0}]]},"Hunter":{"main":[[{"node":"Gmail","type":"main","index":0},{"node":"Appends the results to the sheet","type":"main","index":0}]]},"Create a new sheet":{"main":[[{"node":"Columns to add: linkedin_url, first_name, last_name, email, context, domain","type":"main","index":0}]]},"Google Boolean Search":{"main":[[{"node":"Extracts all linkedin urls and workplace context from the google http response","type":"main","index":0}]]},"Extract Contact Details":{"main":[[{"node":"Extracts fname, lname, domainname","type":"main","index":0}]]},"Add columns to new sheet":{"main":[[{"node":"set page number for google search","type":"main","index":0}]]},"When chat message received":{"main":[[{"node":"Generate a Boolean Search String","type":"main","index":0}]]},"Extract subject and email body":{"main":[[{"node":"Hunter","type":"main","index":0}]]},"If desired results not reached":{"main":[[{"node":"Wait","type":"main","index":0}],[]]},"Appends the results to the sheet":{"main":[[{"node":"Adds 10 to start - Go to next page","type":"main","index":0}]]},"Generate a Boolean Search String":{"main":[[{"node":"Create a new sheet","type":"main","index":0}]]},"Extracts fname, lname, domainname":{"main":[[{"node":"Personalized Cold-Email Generator","type":"main","index":0}]]},"Personalized Cold-Email Generator":{"main":[[{"node":"Extract subject and email body","type":"main","index":0}]]},"set page number for google search":{"main":[[{"node":"If desired results not reached","type":"main","index":0}]]},"Adds 10 to start - Go to next page":{"main":[[{"node":"If desired results not reached","type":"main","index":0}]]},"Columns to add: linkedin_url, first_name, last_name, email, context, domain":{"main":[[{"node":"Add columns to new sheet","type":"main","index":0}]]},"Extracts all linkedin urls and workplace context from the google http response":{"main":[[{"node":"Extract Contact Details","type":"main","index":0}]]}}}


name: Zillow Property Scraper by Location via Bright Data & Google Sheets
author_name: Incrementors
author_username: incrementors
nodes_used: ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest"]
categories: []
created_at: 2025-06-18T11:31:57.431Z
updated_at: 2025-06-18T11:31:57.431Z
url: https://n8n.io/workflows/5019
scraped_at: 2025-07-06 21:16:30
description:
  🛒 Google Maps Business Phone Number Scraper Using Bright Data API & Google Sheets Integration

  This template requires a self-hosted n8n instance to run.

  An automated workflow that extracts business information including phone numbers from Google Maps using Bright Data's API and saves the data to Google Sheets for easy access and analysis.

  📋 Overview

  This workflow provides an automated solution for extracting business contact information from Google Maps based on location and keyword searches. Perfect for lead generation, market research, competitor analysis, and business directory creation.

  ✨ Key Features

  🎯 Form-Based Input: Easy-to-use form for location and keyword submission
  🗺️ Google Maps Integration: Uses Bright Data's Google Maps dataset for accurate business data
  📊 Comprehensive Data Extraction: Extracts business names, addresses, phone numbers, ratings, and more
  📧 Automated Processing: Handles the entire scraping process automatically
  📈 Google Sheets Storage: Automatically saves extracted data to organized spreadsheets
  🔄 Smart Status Checking: Monitors scraping progress with automatic retry logic
  ⚡ Fast & Reliable: Professional scraping with built-in error handling
  🎯 Customizable Output: Configurable data fields for specific business needs

  🎯 What This Workflow Does

  Input
  Location:** Geographic area to search (city, state, country)
  Keywords:** Business type or industry keywords

  Processing
  Form Submission: User submits location and keywords through web form
  API Request: Sends scraping request to Bright Data's Google Maps dataset
  Status Monitoring: Continuously checks scraping progress
  Data Retrieval: Fetches completed business data when ready
  Data Storage: Saves extracted information to Google Sheets
  Error Handling: Implements retry logic for failed requests

  Output Data Points

  | Field | Description | Example |
  |-------|-------------|---------|
  | Business Name | Official business name from Google Maps | "Joe's Pizza Restaurant" |
  | Phone Number | Contact phone number | "+1-555-123-4567" |
  | Address | Complete business address | "123 Main St, New York, NY 10001" |
  | Rating | Google Maps rating score | 4.5 |
  | URL | Google Maps listing URL | "https://maps.google.com/..." |

  🚀 Setup Instructions

  Prerequisites
  n8n instance (self-hosted or cloud)
  Google account with Sheets access
  Bright Data account with Google Maps dataset access
  5-10 minutes for setup

  Step 1: Import the Workflow
  Copy the JSON workflow code from the provided file
  In n8n: Workflows → + Add workflow → Import from JSON
  Paste JSON and click Import

  Step 2: Configure Bright Data
  Set up Bright Data credentials:
     In n8n: Credentials → + Add credential → HTTP Request Auth
     Enter your Bright Data API key
     Test the connection
  Configure dataset:
     Ensure you have access to Google Maps dataset (gd_m8ebnr0q2qlklc02fz)
     Verify dataset permissions in Bright Data dashboard

  Step 3: Configure Google Sheets Integration
  Create a Google Sheet:
     Go to Google Sheets
     Create a new spreadsheet named "Business Data" or similar
     Copy the Sheet ID from URL: https://docs.google.com/spreadsheets/d/SHEET_ID_HERE/edit
  Set up Google Sheets credentials:
     In n8n: Credentials → + Add credential → Google Sheets OAuth2 API
     Complete OAuth setup and test connection
  Prepare your data sheet with columns:
     Column A: Name
     Column B: Address
     Column C: Rating
     Column D: Phone Number
     Column E: URL

  Step 4: Update Workflow Settings
  Update Google Sheets node:
     Open "Save to Google Sheets" node
     Replace the document ID with your Sheet ID
     Select your Google Sheets credential
     Choose the correct sheet/tab name
  Update Bright Data nodes:
     Open HTTP Request nodes
     Replace BRIGHT_DATA_API_KEY with your actual API key
     Verify dataset ID matches your subscription

  Step 5: Test & Activate
  Test the workflow:
     Activate workflow (toggle switch)
     Submit test form with location: "New York" and keywords: "restaurants"
     Verify data appears in Google Sheet
     Check for proper phone number extraction

  📖 Usage Guide

  Submitting Search Requests
  Access the form URL provided by n8n
  Enter the desired location (city, state, or country)
  Enter relevant keywords (business type, industry, etc.)
  Submit the form and wait for processing

  Understanding the Results
  Your Google Sheet will populate with business data including:
  Complete business contact information
  Verified phone numbers from Google Maps
  Accurate addresses and ratings
  Direct links to Google Maps listings

  🔧 Customization Options

  Adding More Data Points
  Edit the "Bright Data API - Request Business Data" node to capture additional fields:
  Business descriptions
  Operating hours
  Reviews count
  Website URLs
  Photos and videos

  Modifying Search Parameters
  Customize the search behavior:
  Adjust "limit_per_input" for more or fewer results
  Modify search type and discovery method
  Add geographical coordinates for precise targeting

  🚨 Troubleshooting

  Common Issues & Solutions

  1. "Bright Data connection failed"
  Cause:** Invalid API credentials or dataset access
  Solution:** Verify credentials in Bright Data dashboard, check dataset permissions

  2. "No business data extracted"
  Cause:** Invalid search parameters or no results found
  Solution:** Try broader keywords or different locations, verify dataset availability

  3. "Google Sheets permission denied"
  Cause:** Incorrect credentials or sheet permissions
  Solution:** Re-authenticate Google Sheets, check sheet sharing settings

  4. "Workflow execution timeout"
  Cause:** Large search results or slow API response
  Solution:** Reduce search scope, increase timeout settings, check internet connection

  📊 Use Cases & Examples

  1. Lead Generation
  Goal:** Find potential customers in specific areas
  Search for businesses by industry and location
  Extract contact information for outreach campaigns
  Build targeted prospect lists

  2. Market Research
  Goal:** Analyze local business landscape
  Study competitor density in target markets
  Identify market gaps and opportunities
  Gather business intelligence for strategic planning

  3. Directory Creation
  Goal:** Build comprehensive business directories
  Create industry-specific business listings
  Maintain updated contact databases
  Support local business communities

  📈 Performance & Limits

  Expected Performance
  Processing time:** 1-5 minutes per search depending on results
  Data accuracy:** 95%+ for active Google Maps listings
  Success rate:** 90%+ for accessible businesses
  Concurrent requests:** Depends on Bright Data plan limits

  Resource Usage
  Memory:** ~50MB per execution
  Storage:** Minimal (data stored in Google Sheets)
  API calls:** 2-3 Bright Data calls + 1 Google Sheets call per search
  Bandwidth:** ~1-2MB per search request
  Execution time:** 2-5 minutes for typical searches

  Scaling Considerations
  Rate limiting:** Respect Bright Data API limits
  Error handling:** Implement retry logic for failed requests
  Data validation:** Add checks for incomplete business data
  Cost optimization:** Monitor API usage to control expenses
  Batch processing:** Group multiple searches for efficiency

  🤝 Support & Community

  Getting Help
  n8n Community Forum:** community.n8n.io
  Documentation:** docs.n8n.io
  Bright Data Support:** Contact through your dashboard
  GitHub Issues:** Report bugs and feature requests

  Contributing
  Share improvements with the community
  Report issues and suggest enhancements
  Create variations for specific use cases
  Document best practices and lessons learned

  🎯 Ready to Use!

  This workflow provides a solid foundation for automated Google Maps business data extraction. Customize it to fit your specific needs and use cases.

  Your workflow URL: https://your-n8n-instance.com/workflow/google-maps-scraper

  For any questions or support, please contact:  
  info@incrementors.com  
  or fill out this form: https://www.incrementors.com/contact-us/

workflow_json:
  {"id":"0eFmaRUQnmJfkcaI","meta":{"instanceId":"bc8ca75c203589705ae2e446cad7181d6f2a7cc1766f958ef9f34810e53b8cb2","templateCredsSetupCompleted":true},"name":"Zillow Property Listing Scraper by Location & Category Using Bright Data API & Google Sheets Integration","tags":[],"nodes":[{"id":"3ac2c390-45ef-4c40-99ba-7c41e387f88c","name":"📝 Form Trigger - Start Property Search","type":"n8n-nodes-base.formTrigger","position":[-2040,620],"webhookId":"1485a089-e3a3-4aff-8043-9e2e24a24bad","parameters":{"options":{},"formTitle":"Zillow Property Search","formFields":{"values":[{"fieldLabel":"Location","requiredField":true},{"fieldType":"dropdown","fieldLabel":"Listing Category","fieldOptions":{"values":[{"option":"House for rent"},{"option":"House for sale"}]}}]}},"typeVersion":2.2},{"id":"e8976089-8572-45f0-b895-3517bf157801","name":"📤 Trigger Bright Data Scraping Job","type":"n8n-nodes-base.httpRequest","position":[-1800,620],"parameters":{"url":"https://api.brightdata.com/datasets/v3/trigger","method":"POST","options":{},"jsonBody":"={\n  \"input\": [\n    {\n      \"location\": \"{{ $json.Location }}\",\n      \"listingCategory\": \"{{ $json['Listing Category'] }}\",\n      \"HomeType\": \"\",\n      \"days_on_zillow\": \"\"\n    }\n  ]\n}","sendBody":true,"sendQuery":true,"sendHeaders":true,"specifyBody":"json","queryParameters":{"parameters":[{"name":"dataset_id","value":"gd_lfqkr8wm13ixtbd8f5"},{"name":"include_errors","value":"true"},{"name":"type","value":"discover_new"},{"name":"discover_by","value":"input_filters"},{"name":"limit_per_input","value":"2"}]},"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer YOUR_TOKEN_HERE"}]}},"typeVersion":4.2},{"id":"1a3a3572-b249-4ca0-9b18-0fc2341aea93","name":"Form Submission Note","type":"n8n-nodes-base.stickyNote","position":[-2080,545],"parameters":{"color":7,"width":180,"height":240,"content":"Starts workflow when user submits location & category via form"},"typeVersion":1},{"id":"902fe79f-8373-4a17-9e6a-a8449bcd48f5","name":"API Trigger Note","type":"n8n-nodes-base.stickyNote","position":[-1850,545],"parameters":{"color":2,"width":200,"height":240,"content":"Sends search request to Bright Data API to trigger Zillow data scraping"},"typeVersion":1},{"id":"eea4519d-eaca-4bba-b31b-67c12bdd943b","name":"Status Check Note","type":"n8n-nodes-base.stickyNote","position":[-1610,545],"parameters":{"color":6,"width":200,"height":240,"content":"Monitors scraping job status and waits for completion"},"typeVersion":1},{"id":"0992cf05-aa2c-449f-af0f-c4cbd4cb340d","name":"⏳ Check Scraping Job Status","type":"n8n-nodes-base.httpRequest","position":[-1560,620],"parameters":{"url":"=https://api.brightdata.com/datasets/v3/progress/{{ $json.snapshot_id }}","options":{},"sendQuery":true,"sendHeaders":true,"queryParameters":{"parameters":[{"name":"format","value":"json"}]},"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer YOUR_TOKEN_HERE"}]}},"typeVersion":4.2},{"id":"ce4357aa-e6de-4082-8cef-7cb3aa9727a2","name":"Wait Timer Note","type":"n8n-nodes-base.stickyNote","position":[-1140,660],"parameters":{"color":6,"width":220,"height":220,"content":"Waits 1 minute before rechecking scraping job status"},"typeVersion":1},{"id":"5be9e5cb-57d3-47db-ba39-543799a1ecad","name":"⏱️ Wait Before Retry","type":"n8n-nodes-base.wait","position":[-1100,720],"webhookId":"7047efad-de41-4608-b95c-d3e0203ef620","parameters":{"unit":"minutes","amount":1},"typeVersion":1.1},{"id":"60878135-aa34-4b71-98ca-ac9dccc6b7e9","name":"Data Validation Note","type":"n8n-nodes-base.stickyNote","position":[-1140,420],"parameters":{"color":5,"width":220,"height":220,"content":"Validates if property data was found in scraping results"},"typeVersion":1},{"id":"4b6df4c2-c72a-4a29-8077-17332184a038","name":"Data Retrieval Note","type":"n8n-nodes-base.stickyNote","position":[-880,400],"parameters":{"color":4,"width":220,"height":220,"content":"Retrieves the actual property data using snapshot ID"},"typeVersion":1},{"id":"fc1fcdd3-f3cf-43aa-ac63-bfc5270b3663","name":"📥 Fetch Property Listing Data","type":"n8n-nodes-base.httpRequest","position":[-820,460],"parameters":{"url":"=https://api.brightdata.com/datasets/v3/snapshot/{{ $json.snapshot_id }}","options":{},"sendQuery":true,"sendHeaders":true,"queryParameters":{"parameters":[{"name":"format","value":"json"}]},"headerParameters":{"parameters":[{"name":"Authorization","value":"Bearer YOUR_TOKEN_HERE"}]}},"typeVersion":4.2},{"id":"b980cf99-85cc-4dd9-9c41-405f20e45827","name":"Google Sheets Save Note","type":"n8n-nodes-base.stickyNote","position":[-640,400],"parameters":{"color":3,"height":220,"content":"Saves the scraped property data to your Google Sheet"},"typeVersion":1},{"id":"a9daf529-3b67-4f07-8d55-95af66861baf","name":"📄 Save Property Data to Google Sheets","type":"n8n-nodes-base.googleSheets","position":[-600,460],"parameters":{"columns":{"value":{"URL":"={{ $json.hdpUrl }}","City":"={{ $json.city }}","Country":"={{ $json.country }}","Home Type":"={{ $json.homeType }}","Zestimate":"={{ $json.zestimate }}","Year Built":"={{ $json.yearBuilt }}","Agent Phone":"={{ $json.listing_provided_by.phone_number }}","Home Status":"={{ $json.homeStatus }}","School Rating":"={{ $json.schools[0].rating }}","Street Address":"={{ $json.address }}","Interior Details":"={{ $json.interior_full[0].values }}"},"schema":[{"id":"URL","type":"string","display":true,"required":false,"displayName":"URL","defaultMatch":false,"canBeUsedToMatch":true},{"id":"City","type":"string","display":true,"required":false,"displayName":"City","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Agent Phone","type":"string","display":true,"required":false,"displayName":"Agent Phone","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Home Status","type":"string","display":true,"required":false,"displayName":"Home Status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Street Address","type":"string","display":true,"required":false,"displayName":"Street Address","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Zestimate","type":"string","display":true,"required":false,"displayName":"Zestimate","defaultMatch":false,"canBeUsedToMatch":true},{"id":"School Rating","type":"string","display":true,"required":false,"displayName":"School Rating","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Year Built","type":"string","display":true,"required":false,"displayName":"Year Built","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Home Type","type":"string","display":true,"required":false,"displayName":"Home Type","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Country","type":"string","display":true,"required":false,"displayName":"Country","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Interior Details","type":"string","display":true,"required":false,"displayName":"Interior Details","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"append","sheetName":{"__rl":true,"mode":"list","value":"Zillow","cachedResultUrl":"https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=0","cachedResultName":"Zillow"},"documentId":{"__rl":true,"mode":"list","value":"YOUR_GOOGLE_SHEET_ID","cachedResultUrl":"https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit","cachedResultName":"Property Data Sheet"}},"credentials":{"googleSheetsOAuth2Api":{"id":"YOUR_GOOGLE_SHEETS_CREDENTIAL_ID","name":"Google Sheets OAuth2"}},"typeVersion":4.6},{"id":"74062322-6e62-40d6-8876-dada77a319fc","name":"✅ Check If Scraping Complete","type":"n8n-nodes-base.if","position":[-1320,540],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"or","conditions":[{"id":"35ed620d-b5d5-4e97-bcc5-52b283d85616","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.status }}","rightValue":"ready"}]}},"typeVersion":2.2},{"id":"25326b0a-7fb3-4ee5-9d6a-56c2d1d4cf41","name":"📊 Validate Property Data Exists","type":"n8n-nodes-base.if","position":[-1080,480],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"f01bd215-c406-493c-a6e4-2b8ec5686b44","operator":{"type":"number","operation":"notEquals"},"leftValue":"={{ $json.records }}","rightValue":"={{ 0 }}"}]}},"typeVersion":2.2},{"id":"3a7c4645-e5e9-4feb-8635-0953b6ae6a6a","name":"Google Sheet Template Note","type":"n8n-nodes-base.stickyNote","position":[-2080,300],"parameters":{"color":7,"width":280,"content":"Sample Google Sheet Template:\nhttps://docs.google.com/spreadsheets/d/SAMPLE_SHEET_ID/edit\n\nMake a copy and update the workflow with your Sheet ID"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"1be06750-3f46-4f87-ab33-829b4e8f3079","connections":{"⏱️ Wait Before Retry":{"main":[[{"node":"⏳ Check Scraping Job Status","type":"main","index":0}]]},"⏳ Check Scraping Job Status":{"main":[[{"node":"✅ Check If Scraping Complete","type":"main","index":0}]]},"✅ Check If Scraping Complete":{"main":[[{"node":"📊 Validate Property Data Exists","type":"main","index":0}],[{"node":"⏱️ Wait Before Retry","type":"main","index":0}]]},"📥 Fetch Property Listing Data":{"main":[[{"node":"📄 Save Property Data to Google Sheets","type":"main","index":0}]]},"📊 Validate Property Data Exists":{"main":[[{"node":"📥 Fetch Property Listing Data","type":"main","index":0}]]},"📤 Trigger Bright Data Scraping Job":{"main":[[{"node":"⏳ Check Scraping Job Status","type":"main","index":0}]]},"📝 Form Trigger - Start Property Search":{"main":[[{"node":"📤 Trigger Bright Data Scraping Job","type":"main","index":0}]]}}}


name: Automated GitHub Scanner for Exposed AWS IAM Keys
author_name: Niranjan G
author_username: niranjan
nodes_used: ["n8n-nodes-base.httpRequest","n8n-nodes-base.slack","n8n-nodes-base.code"]
categories: []
created_at: 2025-06-18T13:22:16.072Z
updated_at: 2025-06-18T13:22:16.072Z
url: https://n8n.io/workflows/5021
scraped_at: 2025-07-06 21:16:30
description:
  Automated GitHub Scanner for Exposed AWS IAM Keys

  Overview

  This n8n workflow automatically scans GitHub for exposed AWS IAM access keys associated with your AWS account, helping security teams quickly identify and respond to potential security breaches. When compromised keys are found, the workflow generates detailed security reports and sends Slack notifications with actionable remediation steps.

  🔑 Key Features

  Automated AWS IAM Key Scanning**: Regularly checks for exposed AWS access keys on GitHub
  Real-time Security Alerts**: Sends immediate Slack notifications when compromised keys are detected
  Comprehensive Security Reports**: Generates detailed reports with exposure information and risk assessment
  Actionable Remediation Steps**: Provides clear instructions for securing compromised credentials
  Continuous Monitoring**: Maintains ongoing surveillance of your AWS environment

  📋 Workflow Steps

  List AWS Users: Retrieves all users from your AWS account
  Split Users for Processing: Processes each user individually
  Get User Access Keys: Retrieves access keys for each user
  Filter Active Keys Only: Focuses only on currently active access keys
  Search GitHub for Exposed Keys: Scans GitHub repositories for exposed access keys
  Aggregate Search Results: Consolidates and deduplicates search findings
  Check For Compromised Keys: Determines if any keys have been exposed
  Generate Security Report: Creates detailed security reports for compromised keys
  Extract AWS Usernames: Extracts usernames from AWS response for notification
  Format Slack Alert: Prepares comprehensive Slack notifications
  Send Slack Notification: Delivers alerts with actionable information
  Continue Scanning: Maintains continuous monitoring cycle

  🛠️ Setup Requirements

  Prerequisites

  Active n8n instance
  AWS account with IAM permissions
  GitHub account/token for searching repositories
  Slack workspace for notifications

  Required Credentials

  AWS Credentials:
     IAM user with permissions to list users and access keys
     Access Key ID and Secret Access Key

  GitHub Credentials:
     Personal Access Token with search permissions

  Slack Credentials:
     Webhook URL for your notification channel

  ⚙️ Configuration

  AWS Configuration:
     Configure the "List AWS Users" node with your AWS credentials
     Ensure proper IAM permissions for listing users and access keys

  GitHub Configuration:
     Set up the "Search GitHub for Exposed Keys" node with your GitHub token
     Adjust search parameters if needed

  Slack Configuration:
     Configure the Slack node with your webhook URL
     Customize notification format if desired

  🚀 Usage

  Running the Workflow

  Manual Execution: Click "Execute Workflow" to run an immediate scan
  Scheduled Execution: Set up a schedule to run periodic scans (recommended daily or weekly)

  Repository Compatibility

  This workflow is compatible with both public and private GitHub repositories to which you have access. It will scan all repositories you have permission to view based on your GitHub credentials.

  Handling Alerts

  When a compromised key is detected:

  Review the Slack notification for details about the exposure
  Follow the recommended remediation steps:
     Deactivate the compromised key immediately
     Create a new key if needed
     Investigate the exposure source
     Update any services using the compromised key

  ⚠️ Disclaimer

  This workflow template is provided for reference purposes only to demonstrate how to automate AWS IAM key exposure scanning. Please note:

  The scanning process may produce false positives as it only matches potential AWS access key patterns
  Always verify any reported exposures manually before taking action
  Disabling or deleting access keys without proper verification could have significant negative impacts on your environment
  Understand which systems and applications rely on identified access keys before deactivating them
  This template should be customized to fit your specific environment and security policies

  IMPORTANT: Use this workflow with caution and only after thoroughly understanding your AWS environment. The authors of this template are not responsible for any disruptions or damages resulting from its use.

  🔒 Security Considerations

  This workflow requires access to sensitive AWS credentials
  Store all credentials securely within n8n
  Review and rotate access keys regularly

  📝 Customization Options

  Adjust GitHub search parameters for more targeted scanning
  Customize Slack notification format and content
  Modify security report generation for your specific needs
  Integrate with additional notification channels (email, MS Teams, etc.)

  Optional: Enabling Interactive Slack Buttons

  The Slack Block Kit notification format supports interactive buttons that can be implemented if you want to perform actions directly from Slack:

  Disable Key: This button can be configured to automatically disable the compromised AWS IAM access key
  View Details: This button can be set up to show additional information about the exposure
  Acknowledge: This button can be used to mark the alert as acknowledged

  To make these buttons functional:

  Set up a Slack Socket Mode App:
     Create a Slack app in the Slack API Console
     Enable Socket Mode and Interactive Components
     Subscribe to the block_actions event to capture button clicks

  Create an n8n Webhook Endpoint:
     Add a new webhook node to receive Slack button click events
     Create separate workflows for each button action

  Implement AWS Key Disabling:
     For the "Disable Key" button, create a workflow that uses the n8n HTTP Request node to call the AWS IAM UpdateAccessKey API
     Example HTTP request that can be implemented in n8n:
            Method: POST
       URL: https://iam.amazonaws.com/
       Query Parameters:
         Action: UpdateAccessKey
         AccessKeyId: AKIAIOSFODNN7EXAMPLE
         Status: Inactive
         UserName: {{$json.username}}
         Version: 2010-05-08
       
  Update the Slack Message Format:
     Modify the Format Slack Alert node to include your webhook URL in the button action values
     Add callback_id and action_id values to identify which button was clicked

  This implementation allows for immediate response to security incidents directly from the Slack interface, reducing response time and improving security posture.

workflow_json:
  {"id":"Tcy2xebw2oGWMxUN","meta":{"instanceId":"c62c01f3e843893075a10f252ec7d6d69e5ab593af019f50055d506cb3081b99","templateCredsSetupCompleted":true},"name":"🕵️‍♂️ Automated GitHub Scanner for Exposed AWS IAM Keys","tags":[{"id":"XuoVybTXeUXuim6G","name":"✅ Live","createdAt":"2025-06-08T07:59:43.586Z","updatedAt":"2025-06-08T07:59:43.586Z"},{"id":"MbPHhZHgb39Syuoa","name":"🔐 SecOps","createdAt":"2025-04-20T05:18:20.689Z","updatedAt":"2025-06-08T08:01:56.494Z"}],"nodes":[{"id":"84edf6c4-fc87-4b34-86c6-ad72c15cafe8","name":"When clicking ‘Execute workflow’","type":"n8n-nodes-base.manualTrigger","position":[-880,75],"parameters":{},"typeVersion":1},{"id":"b2c1157f-c1eb-4d22-95d0-6ec166a93a4a","name":"Split Users for Processing","type":"n8n-nodes-base.splitInBatches","position":[-220,75],"parameters":{"options":{}},"typeVersion":3},{"id":"ae5a0e4f-892c-4a75-bdcc-36253fbc7274","name":"Get User Access Keys","type":"n8n-nodes-base.httpRequest","position":[0,0],"parameters":{"url":"https://iam.amazonaws.com","method":"POST","options":{},"sendBody":true,"contentType":"form-urlencoded","authentication":"predefinedCredentialType","bodyParameters":{"parameters":[{"name":"Action","value":"ListAccessKeys"},{"name":"Version","value":"2010-05-08"},{"name":"UserName","value":"={{ $json.username }}"}]},"nodeCredentialType":"aws"},"credentials":{"aws":{"id":"Y0EXCbx12345678","name":"AWS account"}},"typeVersion":4.1},{"id":"0946f05d-11f0-480b-934a-c996bbb9551e","name":"Filter Active Keys Only","type":"n8n-nodes-base.if","position":[220,0],"parameters":{"options":{},"conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"active-key-check","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata[0].Status }}","rightValue":"Active"}]}},"typeVersion":2},{"id":"8f9db031-245e-4c00-bdb9-4ed55e9b57b2","name":"Search GitHub for Exposed Keys","type":"n8n-nodes-base.httpRequest","position":[880,0],"parameters":{"url":"={{ $json.simpleSearch.searchUrl }}","options":{"timeout":10000,"response":{"response":{"responseFormat":"json"}}},"authentication":"predefinedCredentialType","nodeCredentialType":"githubApi"},"credentials":{"githubApi":{"id":"3fz93A0mgyxzXGOL","name":"GitHub account"}},"typeVersion":4.1},{"id":"a6cd482c-86d2-49ac-aefe-6beec92c98af","name":"Aggregate Search Results","type":"n8n-nodes-base.code","position":[1100,0],"parameters":{"jsCode":"// Aggregate all search results\nconst allResults = [];\nconst accessKeyId = $input.first().json.accessKeyId;\nconst userName = $input.first().json.userName;\n\nfor (const item of $input.all()) {\n  if (item.json.total_count > 0) {\n    allResults.push(...item.json.items);\n  }\n}\n\n// Remove duplicates based on repository and file path\nconst uniqueResults = allResults.filter((item, index, self) => \n  index === self.findIndex(t => t.repository.full_name === item.repository.full_name && t.path === item.path)\n);\n\nreturn [{\n  accessKeyId,\n  userName,\n  totalMatches: uniqueResults.length,\n  repositories: uniqueResults,\n  isCompromised: uniqueResults.length > 0\n}];"},"typeVersion":2},{"id":"75ed15ec-fdee-4644-a83c-6b47005dcac1","name":"Check For Compromised Keys","type":"n8n-nodes-base.if","position":[1320,0],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"ebf33a67-f8f3-4700-8579-1d33b7a642d5","operator":{"type":"boolean","operation":"equals"},"leftValue":"isCompromised","rightValue":"={{ $json.isCompromised }}"}]},"looseTypeValidation":true},"typeVersion":2.2},{"id":"57753be8-33d2-4172-94a2-0d5a4f7c73ec","name":"Generate Security Report","type":"n8n-nodes-base.code","position":[1540,0],"parameters":{"jsCode":"// Generate comprehensive security report - Notification Only (No Automatic Actions)\nconst data = $input.item.json;\n\nconst report = {\n  timestamp: new Date().toISOString(),\n  accessKeyId: data.accessKeyId,\n  userName: data.userName,\n  status: data.isCompromised ? 'COMPROMISED' : 'SAFE',\n  totalRepositories: data.totalMatches,\n  repositories: data.repositories.map(repo => ({\n    name: repo.repository.full_name,\n    url: repo.html_url,\n    path: repo.path,\n    score: repo.score\n  })),\n  actionTaken: data.isCompromised ? 'Security team notified - Manual review required' : 'No action required',\n  riskLevel: data.totalMatches > 5 ? 'HIGH' : data.totalMatches > 0 ? 'MEDIUM' : 'LOW',\n  notificationSent: data.isCompromised ? true : false,\n  requiresManualAction: data.isCompromised ? true : false,\n  recommendedActions: data.isCompromised ? [\n    'Manually disable the compromised access key',\n    'Generate new access keys for affected services',\n    'Remove exposed keys from repositories',\n    'Audit recent API usage for this key'\n  ] : []\n};\n\nreturn [report];"},"typeVersion":2},{"id":"f2634090-b035-4592-ad56-b970c2bff14c","name":"Continue Scanning","type":"n8n-nodes-base.noOp","position":[2340,80],"parameters":{},"typeVersion":1},{"id":"158340f1-4dc4-4b4c-933f-95a28be524dc","name":"Slack","type":"n8n-nodes-base.slack","position":[2020,0],"webhookId":"47dc1fb0-71c0-40f6-8263-88880f01a436","parameters":{"text":"={{ $json.message }}","select":"channel","channelId":{"__rl":true,"mode":"id","value":"C08Q2H8SRUP"},"otherOptions":{}},"credentials":{"slackApi":{"id":"i1yhHILyYn12345678","name":"Slack account"}},"typeVersion":2.3},{"id":"c0300832-418b-4fa8-98b6-2b799f2bcfe6","name":"Format Slack Alert","type":"n8n-nodes-base.code","position":[1760,0],"parameters":{"jsCode":"/**\n * GitHub Scanner for Exposed AWS IAM Keys - Data Processor\n * \n * This script processes the results from the AWS IAM Key scanner workflow\n * and formats them for reporting and notification purposes.\n */\n\n// Main entry point - this is what n8n will call\n// Input: items array from n8n workflow\n// Output: Slack Block Kit UI format (blocks array only)\nconst items = $input.all();\n\n// Process the input data\nconst scanResults = items.map(item => item.json);\nconst processedResults = processIAMScanResults(scanResults);\n\n// Format for markdown notification\nconst markdownNotification = formatForMarkdownNotification(processedResults);\n// Return as array of objects for n8n\nreturn [{ message: markdownNotification }];\n\n/**\n * Process scan results and format them for reporting\n * @param {Array} scanResults - Array of scan result objects from the workflow\n * @returns {Array} Array of formatted result objects\n */\nfunction processIAMScanResults(scanResults) {\n  if (!Array.isArray(scanResults) || scanResults.length === 0) {\n    return [{\n      status: 'NO_RESULTS',\n      timestamp: new Date().toISOString(),\n      message: 'No scan results to process'\n    }];\n  }\n\n  // Process each scan result\n  const processedResults = scanResults.map(result => {\n    // Create a deep copy to avoid modifying the original data\n    const processedResult = JSON.parse(JSON.stringify(result));\n    \n    // Ensure we have the required fields\n    if (!processedResult.timestamp) {\n      processedResult.timestamp = new Date().toISOString();\n    }\n    \n    // Calculate risk metrics if not provided\n    if (!processedResult.riskLevel) {\n      processedResult.riskLevel = calculateRiskLevel(processedResult);\n    }\n    \n    // Generate recommended actions if not provided\n    if (!processedResult.recommendedActions || processedResult.recommendedActions.length === 0) {\n      processedResult.recommendedActions = generateRecommendedActions(processedResult);\n    }\n    \n    return processedResult;\n  });\n\n  return processedResults;\n}\n  \n  /**\n   * Calculate risk level based on scan result data\n   * @param {Object} result - Individual scan result\n   * @returns {string} Risk level (HIGH, MEDIUM, LOW)\n   */\n  function calculateRiskLevel(result) {\n    // Default to MEDIUM if we can't determine\n    if (!result || !result.status) {\n      return 'MEDIUM';\n    }\n    \n    // Determine risk level based on status and other factors\n    if (result.status === 'COMPROMISED') {\n      // Public repositories or repositories with many contributors increase risk\n      if (result.repositories && result.repositories.some(repo => {\n        return repo.score >= 0.8; // High score indicates higher risk\n      })) {\n        return 'HIGH';\n      }\n      return 'MEDIUM';\n    } else if (result.status === 'POTENTIAL_EXPOSURE') {\n      return 'MEDIUM';\n    } else {\n      return 'LOW';\n    }\n  }\n  \n  /**\n   * Generate recommended actions based on scan result\n   * @param {Object} result - Individual scan result\n   * @returns {Array} List of recommended actions\n   */\n  function generateRecommendedActions(result) {\n    const commonActions = [\n      'Review the exposure details in the security report',\n      'Rotate affected access keys immediately'\n    ];\n    \n    if (result.status === 'COMPROMISED') {\n      return [\n        ...commonActions,\n        'Disable the compromised access key',\n        'Generate new access keys for affected services',\n        'Remove exposed keys from repositories',\n        'Audit recent API usage for this key'\n      ];\n    } else if (result.status === 'POTENTIAL_EXPOSURE') {\n      return [\n        ...commonActions,\n        'Verify if the exposure is a false positive',\n        'Consider rotating keys as a precaution'\n      ];\n    } else {\n      return [\n        'No immediate action required',\n        'Continue monitoring for potential exposures'\n      ];\n    }\n  }\n  \n  /**\n   * Format scan results for Slack-compatible markdown notification\n   * @param {Array} processedResults - Processed scan results\n   * @returns {string} Slack-compatible markdown formatted notification text\n   */\n  function formatForMarkdownNotification(processedResults) {\n    if (!Array.isArray(processedResults) || processedResults.length === 0) {\n      return `🔒 *AWS IAM Key Scan Completed*\\n\\nNo exposed AWS IAM keys were detected in this scan.`;\n    }\n  \n    // Count compromised keys\n    const compromisedCount = processedResults.filter(r => r.status === 'COMPROMISED').length;\n    \n    if (compromisedCount === 0) {\n      return `🔒 *AWS IAM Key Scan Completed*\\n\\nNo exposed AWS IAM keys were detected in this scan.`;\n    }\n    \n    // Create Slack-compatible notification for compromised keys\n    let markdown = `⚠️ *ALERT: AWS IAM Keys Exposed*\\n\\n*${compromisedCount}* AWS IAM keys have been potentially exposed on GitHub. Immediate action required.\\n\\n`;\n    \n    // Add details for each compromised key\n    processedResults.filter(r => r.status === 'COMPROMISED').forEach((result, index) => {\n      markdown += `*Exposure ${index + 1}*\\n\\n`;\n      \n      // Add repository information in a cleaner format\n      markdown += `*Exposure Details:*\\n`;\n      result.repositories.forEach(repo => {\n        markdown += `• *Repository:* ${repo.name}\\n`;\n        markdown += `• *Path:* \\`${repo.path}\\`\\n`;\n        markdown += `• *Risk Score:* ${repo.score.toFixed(2)}\\n\\n`;\n      });\n      \n      // Add risk level and action taken in a compact format\n      markdown += `*Risk Level:* ${result.riskLevel} | *Action Taken:* ${result.actionTaken || 'None'}\\n\\n`;\n      \n      // Add recommended actions with better formatting\n      markdown += `*Recommended Actions:*\\n`;\n      result.recommendedActions.forEach(action => {\n        markdown += `• ${action}\\n`;\n      });\n      markdown += `\\n`;\n    });\n    \n    return markdown;\n  }\n\n  \n  // Export functions for use in n8n workflow\n  module.exports = {\n    processIAMScanResults,\n    calculateRiskLevel,\n    generateRecommendedActions,\n    formatForMarkdownNotification\n  };"},"typeVersion":2},{"id":"3ed685c7-27b5-4a00-840a-6f9dddff6d3f","name":"Prepare Github Search","type":"n8n-nodes-base.code","position":[440,0],"parameters":{"jsCode":"/**\n * Simplified GitHub Search for AWS Access Keys\n * This script generates optimized search queries for finding exposed AWS access keys on GitHub\n */\n\n/**\n * Generates a GitHub API search URL for a given AWS access key\n * @param {Object} inputData - The input data containing AWS access key information\n * @returns {Object} - Search information including URL and query\n */\nfunction generateGitHubSearchQuery(inputData) {\n  try {\n    // Extract access key information from input\n    let accessKeyId;\n    let userName;\n    \n    // Handle different input formats\n    if (inputData && typeof inputData === 'object') {\n      // Check for n8n workflow format\n      if (inputData.ListAccessKeysResponse && \n          inputData.ListAccessKeysResponse.ListAccessKeysResult && \n          inputData.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata && \n          Array.isArray(inputData.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata) && \n          inputData.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata.length > 0) {\n        \n        accessKeyId = inputData.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata[0].AccessKeyId;\n        userName = inputData.ListAccessKeysResponse.ListAccessKeysResult.AccessKeyMetadata[0].UserName;\n      } \n      // Direct object format\n      else if (inputData.accessKeyId) {\n        accessKeyId = inputData.accessKeyId;\n        userName = inputData.userName || 'unknown';\n      }\n    }\n    \n    // Validate we have an access key\n    if (!accessKeyId) {\n      console.error('No valid AWS access key ID found in input');\n      return { error: 'No valid AWS access key ID found in input' };\n    }\n    \n    // Create the most effective search query\n    // Based on testing, the exact match with quotes is most reliable\n    const searchQuery = `\"${accessKeyId}\" in:file`;\n    \n    // Generate the GitHub API search URL\n    const searchUrl = `https://api.github.com/search/code?q=${encodeURIComponent(searchQuery)}`;\n    \n    return {\n      accessKeyId,\n      userName,\n      searchQuery,\n      searchUrl,\n      note: 'A single exact match query is typically sufficient for finding exposed AWS keys'\n    };\n  } catch (error) {\n    console.error('Error generating GitHub search query:', error);\n    return { error: `Error generating GitHub search query: ${error.message}` };\n  }\n}\n\n/**\n * For more comprehensive searches, this function generates multiple search patterns\n * This is optional and can be used if the simple search doesn't yield results\n * @param {string} accessKeyId - The AWS access key ID to search for\n * @returns {Array} - Array of search queries and URLs\n */\nfunction generateComprehensiveSearch(accessKeyId) {\n  if (!accessKeyId) {\n    return { error: 'No access key ID provided' };\n  }\n  \n  // Search patterns for access keys (in order of effectiveness)\n  const searchQueries = [\n    `\"${accessKeyId}\" in:file`,           // Exact match (most effective)\n    `${accessKeyId} in:file`,              // Without quotes (catches more results but may have false positives)\n    `AWS_ACCESS_KEY_ID=${accessKeyId} in:file`,  // Environment variable format\n    `aws_access_key_id: ${accessKeyId} in:file`, // YAML/config format\n    `accessKeyId: ${accessKeyId} in:file`        // JavaScript/JSON format\n  ];\n  \n  return searchQueries.map(query => ({\n    searchQuery: query,\n    searchUrl: `https://api.github.com/search/code?q=${encodeURIComponent(query)}`\n  }));\n}\n\n// For n8n integration\nfunction processForN8n() {\n  try {\n    // Get input data\n    const inputData = $input.item.json;\n    \n    // Generate the simplified search (recommended approach)\n    const simpleSearch = generateGitHubSearchQuery(inputData);\n    \n    // For backward compatibility, also generate the comprehensive search\n    // if an access key was successfully extracted\n    let comprehensiveSearch = [];\n    if (simpleSearch.accessKeyId) {\n      comprehensiveSearch = generateComprehensiveSearch(simpleSearch.accessKeyId);\n    }\n    \n    return {\n      simpleSearch,\n      comprehensiveSearch,\n      recommendation: 'The simple search is recommended for most cases. Only use comprehensive search if simple search yields no results.'\n    };\n  } catch (error) {\n    console.error('Error in n8n processing:', error);\n    return { error: `Error in n8n processing: ${error.message}` };\n  }\n}\n\n// For standalone usage\nif (typeof module !== 'undefined' && module.exports) {\n  module.exports = {\n    generateGitHubSearchQuery,\n    generateComprehensiveSearch\n  };\n} else {\n  // For n8n execution\n  return processForN8n();\n}"},"typeVersion":2},{"id":"e58f0cd8-13df-41eb-9a9c-99efc7eba0c4","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-900,-680],"parameters":{"width":1120,"height":580,"content":"# 🔐🕵️‍♂️ GitHub Scanner for Exposed AWS IAM Keys – Quick Overview\n\n## ⚙️ Workflow at a Glance\n\n1. 🔍 **Automated Discovery**  \n   Scans GitHub repositories for exposed AWS IAM access keys associated with your AWS account.\n\n2. 🧠 **Intelligent Filtering**  \n   Processes only active access keys and eliminates duplicate findings.\n\n3. 🚨 **Risk Assessment**  \n   Evaluates exposure severity and assigns risk levels (High/Medium/Low) based on findings.\n\n4. 📣 **Actionable Alerts**  \n   Sends detailed Slack notifications with interactive buttons for immediate response.\n\n5. 🛠️ **Remediation Guidance**  \n   Provides step-by-step instructions for securing compromised credentials.\n\n6. 🔄 **Continuous Monitoring**  \n   Maintains ongoing surveillance to detect new exposures quickly.\n\n---\n\n*🛡️ This workflow helps security teams quickly identify and respond to potential security breaches from exposed AWS credentials.*\n"},"typeVersion":1},{"id":"ef29b02b-f2a4-4642-a5c4-c9685b0e2c22","name":"Rate Limit Wait","type":"n8n-nodes-base.wait","position":[660,0],"webhookId":"850e337e-d261-456a-86c1-1725d77f9e52","parameters":{},"typeVersion":1.1},{"id":"714724b6-9aaf-4d17-97b7-1a3fd3dcaeae","name":"List AWS Users1","type":"n8n-nodes-base.httpRequest","position":[-660,80],"parameters":{"url":"https://iam.amazonaws.com","method":"POST","options":{},"sendBody":true,"contentType":"form-urlencoded","authentication":"predefinedCredentialType","bodyParameters":{"parameters":[{"name":"Action","value":"ListUsers"},{"name":"Version","value":"2010-05-08"}]},"nodeCredentialType":"aws"},"credentials":{"aws":{"id":"Y0EXCbx12345678","name":"AWS account"}},"typeVersion":4.1},{"id":"a1448a68-81aa-4571-8f62-617c57daa6e6","name":"Extract AWS Usernames","type":"n8n-nodes-base.code","position":[-440,75],"parameters":{"jsCode":"// n8n Function node: Extract usernames from AWS ListUsersResponse\n\nconst allInputs = $input.all();\n\n// Find the ListUsersResponse input\nconst listUsersInput = allInputs.find(item => item.json.ListUsersResponse);\n\nif (!listUsersInput) {\n  throw new Error('No ListUsersResponse found in input data');\n}\n\n// Extract users array from the response\nconst users = listUsersInput.json\n  .ListUsersResponse\n  .ListUsersResult\n  .Users || [];\n\n// Extract usernames and return each as a separate item for looping\nconst usernameItems = users.map(user => ({\n  json: { username: user.UserName }\n}));\n\n// Return array of individual username objects\nreturn usernameItems;"},"typeVersion":2},{"id":"2339c570-93a3-4c1a-ae0d-2eb9810eeee8","name":"Disable Access Keys","type":"n8n-nodes-base.httpRequest","disabled":true,"position":[1200,-620],"parameters":{"url":"https://iam.amazonaws.com","method":"POST","options":{},"sendBody":true,"contentType":"form-urlencoded","authentication":"predefinedCredentialType","bodyParameters":{"parameters":[{"name":"Action","value":"UpdateAccessKey"},{"name":"AccessKeyId","value":"AKIAEXAMPLEACCESSKEY1"},{"name":"UserName","value":"user@domain.com"},{"name":"Status","value":"Inactive"},{"name":"Version","value":"2010-05-08"}]},"nodeCredentialType":"aws"},"credentials":{"aws":{"id":"Y0EXCbx12345678","name":"AWS account"}},"typeVersion":4.1},{"id":"99938eb1-580b-4a91-b7a7-83464b33053e","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[240,-680],"parameters":{"color":6,"width":1200,"height":580,"content":"## 🚨 Automate Disable Access Keys\n\n### 1. Prerequisites\n\n- Configure AWS credentials in n8n with appropriate IAM permissions  \n- Create an `Extract_Key_Info` node that provides the compromised key's ID and username  \n\n### 2. Workflow Integration\n\n- Add this node after your key detection logic  \n- Connect it to trigger when a compromised key is confirmed  \n\n### 3. Security Considerations\n\n- Ensure your AWS credentials have the `iam:UpdateAccessKey` permission  \n- Consider adding verification steps before automatic disabling  \n- Implement notification steps after key disabling (e.g., Slack, email)  \n\n---\n\nThis implementation enables **immediate remediation of security risks** by automatically disabling compromised AWS access keys as soon as they're discovered in GitHub repositories.\n"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"d96b586a-4739-4ef5-84c8-c71ff9f3e1e6","connections":{"Slack":{"main":[[{"node":"Continue Scanning","type":"main","index":0}]]},"List AWS Users1":{"main":[[{"node":"Extract AWS Usernames","type":"main","index":0}]]},"Rate Limit Wait":{"main":[[{"node":"Search GitHub for Exposed Keys","type":"main","index":0}]]},"Continue Scanning":{"main":[[{"node":"Split Users for Processing","type":"main","index":0}]]},"Format Slack Alert":{"main":[[{"node":"Slack","type":"main","index":0}]]},"Get User Access Keys":{"main":[[{"node":"Filter Active Keys Only","type":"main","index":0}]]},"Extract AWS Usernames":{"main":[[{"node":"Split Users for Processing","type":"main","index":0}]]},"Prepare Github Search":{"main":[[{"node":"Rate Limit Wait","type":"main","index":0}]]},"Filter Active Keys Only":{"main":[[{"node":"Prepare Github Search","type":"main","index":0}]]},"Aggregate Search Results":{"main":[[{"node":"Check For Compromised Keys","type":"main","index":0}]]},"Generate Security Report":{"main":[[{"node":"Format Slack Alert","type":"main","index":0}]]},"Check For Compromised Keys":{"main":[[{"node":"Generate Security Report","type":"main","index":0}]]},"Split Users for Processing":{"main":[[],[{"node":"Get User Access Keys","type":"main","index":0}]]},"Search GitHub for Exposed Keys":{"main":[[{"node":"Aggregate Search Results","type":"main","index":0}]]},"When clicking ‘Execute workflow’":{"main":[[{"node":"List AWS Users1","type":"main","index":0}]]}}}


name: LinkedIn Talent Pipeline: AI-Powered Candidate Search & Ranking with GPT-4o
author_name: Badr
author_username: b4dr
categories: []
created_at: 2025-06-18T14:21:55.773Z
updated_at: 2025-06-18T14:21:55.773Z
url: https://n8n.io/workflows/5022
scraped_at: 2025-07-06 21:16:30
description:
  The Ultimate AI Recruiting Solution for Finding Perfect Candidates with GPT-4o

  Are you tired of manually sifting through hundreds of LinkedIn profiles to find the right talent? Say goodbye to inefficient recruiting processes and embrace the power of AI-driven candidate selection. Our AI Candidate Ranking Flow automates the entire process from job description to ranked candidate lists, saving you countless hours while delivering superior results.

  💼 Key Features & Benefits

  Automatic Candidate Discovery**: Finds relevant LinkedIn profiles based on your job requirements
  AI-Powered Profile Analysis**: Uses advanced GPT models to evaluate each candidate's fit
  Multi-Factor Scoring**: Analyzes skills, experience, and education match with precision
  Seamless Google Sheets Integration**: Export comprehensive results for team collaboration
  100% Automated Workflow**: No manual intervention needed after initial setup
  Custom Match Criteria**: Tailor scoring parameters to your specific needs

  🚀 How It Works

  Simple Input: Just provide a detailed job description
  Smart Extraction: AI extracts key job requirements automatically
  Intelligent Search: Workflow finds relevant LinkedIn profiles using Google Search API
  Deep Profile Analysis: Apify scrapes comprehensive profile data
  Advanced AI Evaluation: Candidates scored based on match to job requirements
  Organized Results: Ranked candidates exported to Google Sheets

  🛠️ Getting Started

  Prerequisites:

  n8n workflow automation platform
  Google Cloud account with Custom Search API enabled
  Apify account for LinkedIn data extraction
  Google Sheets for results storage

  Quick Setup Guide:

  Import Workflow: Download and import our AI_Candidate_Ranking_Flow.json
  Set API Credentials:
     Configure your Google Custom Search API key
     Connect your Apify API token
     Set up Google Sheets OAuth connection
  .  Prepare Your Google Sheet:
      Create a new Google Sheet. In the first tab, create the following headers in the first row: First Name, Last Name, LinkedIn URL, Match Score (0-100), Skills Match, Experience Match, Summary, Ranking.
  Customize Parameters: Adjust AI matching criteria if needed
  Run & Analyze: Start the workflow and watch AI do the heavy lifting!

  💡 Pro Tips For Maximum Results

  Provide detailed job descriptions with specific technical requirements
  Include industry-specific terminology in your job description
  Adjust LLM temperature settings for more creative or precise matching
  Utilize multiple search result pages for a wider candidate pool
  Export data to multiple sheets for different hiring managers

  🔗 Essential Resources

  Apify LinkedIn Scraper - Get deep LinkedIn profile data
  n8n Documentation - Master workflow automation
  Google Custom Search Setup - Configure search API

  ⚙️ Technical Specifications

  Workflow Platform: n8n (latest version)
  AI Models: OpenAI GPT-4o-mini with optional upgrades
  Profile Data Source: Apify LinkedIn Scrapers
  API Integrations: Google Custom Search, Apify, Google Sheets
  Customization: Fully modifiable workflow and scoring parameters

  🔒 Privacy & Compliance

  This workflow respects all LinkedIn terms of service by utilizing only publicly available profile information through Google Search results and legitimate API services. Data processing complies with GDPR and relevant data protection regulations.

  🤔 Frequently Asked Questions

  Q: Do I need programming knowledge to use this?
  A: No! The workflow is completely visual and requires no coding experience.


  Q: Can I customize the matching criteria?
  A: Absolutely! The AI prompt and scoring system are fully customizable.

  Q: Does this replace human recruiters?
  A: No, it enhances their capabilities by handling the time-consuming initial screening.

  Get Started Today!

  Transform your recruiting process with our AI-Powered LinkedIn Candidate Ranking System. Import the workflow, connect your APIs, and start finding ideal candidates in minutes!

  Get Your Apify Account →

  Keywords: ai recruiting, linkedin automation, candidate ranking, job matching algorithm, n8n workflow, recruiting automation, apify linkedin, ai hr tools

nodes_used:
  ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.memoryBufferWindow","@n8n/n8n-nodes-langchain.outputParserStructured","@n8n/n8n-nodes-langchain.openAi"]

workflow_json:
  {"meta":{"instanceId":"4786bf0f18c0e8e92c361de5a158cabf4eb0bb3b9c113091b054ff26e359a029"},"nodes":[{"id":"22e89311-cf71-4ac2-9863-86d5ecea8e27","name":"Job Description Input","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[880,320],"webhookId":"job-desc-webhook","parameters":{},"typeVersion":1.1},{"id":"faf1b39a-2d82-443b-a635-e713a2785a80","name":"Extract Job Details","type":"@n8n/n8n-nodes-langchain.agent","position":[1140,320],"parameters":{},"typeVersion":1.7},{"id":"e09c41f5-5e4e-47a3-8e2e-2e24ec74403a","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1100,540],"parameters":{},"typeVersion":1},{"id":"358e5c6d-a2fd-46f2-9f7a-c489d97f4733","name":"Window Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[1220,540],"parameters":{},"typeVersion":1.3},{"id":"5434c8a3-960e-45fa-a35b-d64d74f666b2","name":"Set Search Page Numbers","type":"n8n-nodes-base.set","position":[1540,320],"parameters":{},"typeVersion":3.4},{"id":"be49661f-2eed-40b8-b443-0b556fab29ad","name":"Split Search Pages","type":"n8n-nodes-base.splitOut","position":[1760,320],"parameters":{},"typeVersion":1},{"id":"9e062b99-8ba1-4bf1-9897-75389bd21119","name":"Google Custom Search API Request","type":"n8n-nodes-base.httpRequest","position":[1980,320],"parameters":{},"typeVersion":4.2},{"id":"3baccbf7-f435-47b5-b43e-1d505d01cf31","name":"Filter LinkedIn Profiles","type":"n8n-nodes-base.function","position":[2200,320],"parameters":{},"typeVersion":1},{"id":"83f477e8-33f2-48a9-a0fa-d5933eb5291b","name":"Prepare Apify Input","type":"n8n-nodes-base.function","position":[2420,320],"parameters":{},"typeVersion":1},{"id":"7f0c20da-d3a7-4715-a6ee-8fcaca274bc0","name":"LLM Scoring","type":"@n8n/n8n-nodes-langchain.openAi","position":[2960,960],"parameters":{},"typeVersion":1.7},{"id":"6234ddcf-3e0b-40e2-b5a0-3a7056aa9bbd","name":"Parse LLM Result","type":"n8n-nodes-base.code","position":[3340,960],"parameters":{},"typeVersion":2},{"id":"0b3863b1-e360-4e9f-a230-66978a42de73","name":"Save to Google Sheets","type":"n8n-nodes-base.googleSheets","position":[3560,1040],"parameters":{},"typeVersion":4.5},{"id":"ecb23196-a5f5-4f58-8c40-e9c6660bc8b5","name":"Workflow Documentation","type":"n8n-nodes-base.stickyNote","position":[0,0],"parameters":{"content":""},"typeVersion":1},{"id":"a0a65e86-7ab2-455d-b3f0-5db24603b2b1","name":"Structured Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[1340,540],"parameters":{},"typeVersion":1.2},{"id":"144e0ddf-0d8d-4df4-ae79-0cf71b4be99b","name":"Run Apify Scraper","type":"n8n-nodes-base.httpRequest","position":[1880,960],"parameters":{},"typeVersion":4.2},{"id":"506fc90f-776d-4d71-8978-e9e8ae44c57e","name":"Extract Profile URLs","type":"n8n-nodes-base.code","position":[2640,320],"parameters":{},"typeVersion":2},{"id":"cd875e17-6fce-43c1-851b-97134069fb7f","name":"Limit","type":"n8n-nodes-base.limit","position":[2900,320],"parameters":{},"typeVersion":1},{"id":"1b1bb113-effa-4414-9a78-837f93ee54a0","name":"Loop Over Items","type":"n8n-nodes-base.splitInBatches","position":[1500,940],"parameters":{},"typeVersion":3},{"id":"6ab01d47-532f-49a8-8938-c4d5c5d3f52f","name":"Wait for Scraping","type":"n8n-nodes-base.wait","position":[2080,960],"webhookId":"e238029e-e85d-46a0-8c30-aef3ddeeef77","parameters":{},"typeVersion":1.1},{"id":"5e6356b4-590d-445e-a07a-d7e2bfc066fe","name":"Check Scraping Status","type":"n8n-nodes-base.httpRequest","position":[2300,880],"parameters":{},"typeVersion":4.2},{"id":"c506cd9e-aae1-4481-ac83-fc9e047ebdfd","name":"Verify Completion","type":"n8n-nodes-base.if","position":[2520,960],"parameters":{},"typeVersion":2.2},{"id":"49fb6044-4ba0-4fe3-afdf-0417b26fda5b","name":"Get LinkedIn Data","type":"n8n-nodes-base.httpRequest","position":[2740,960],"parameters":{},"typeVersion":4.2},{"id":"564192fc-3f7a-4837-b1c1-d60b2183c174","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[1460,720],"parameters":{"content":""},"typeVersion":1},{"id":"a5526f40-c47c-490f-aedf-46fc334d22a5","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[800,180],"parameters":{"content":""},"typeVersion":1}],"connections":{"Limit":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"LLM Scoring":{"main":[[{"node":"Parse LLM Result","type":"main","index":0}]]},"Loop Over Items":{"main":[[],[{"node":"Run Apify Scraper","type":"main","index":0}]]},"Parse LLM Result":{"main":[[{"node":"Save to Google Sheets","type":"main","index":0}]]},"Get LinkedIn Data":{"main":[[{"node":"LLM Scoring","type":"main","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"Extract Job Details","type":"ai_languageModel","index":0}]]},"Run Apify Scraper":{"main":[[{"node":"Wait for Scraping","type":"main","index":0}]]},"Verify Completion":{"main":[[{"node":"Get LinkedIn Data","type":"main","index":0}],[{"node":"Wait for Scraping","type":"main","index":0}]]},"Wait for Scraping":{"main":[[{"node":"Check Scraping Status","type":"main","index":0}]]},"Split Search Pages":{"main":[[{"node":"Google Custom Search API Request","type":"main","index":0}]]},"Extract Job Details":{"main":[[{"node":"Set Search Page Numbers","type":"main","index":0}]]},"Prepare Apify Input":{"main":[[{"node":"Extract Profile URLs","type":"main","index":0}]]},"Extract Profile URLs":{"main":[[{"node":"Limit","type":"main","index":0}]]},"Window Buffer Memory":{"ai_memory":[[{"node":"Extract Job Details","type":"ai_memory","index":0}]]},"Check Scraping Status":{"main":[[{"node":"Verify Completion","type":"main","index":0}]]},"Job Description Input":{"main":[[{"node":"Extract Job Details","type":"main","index":0}]]},"Save to Google Sheets":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Set Search Page Numbers":{"main":[[{"node":"Split Search Pages","type":"main","index":0}]]},"Filter LinkedIn Profiles":{"main":[[{"node":"Prepare Apify Input","type":"main","index":0}]]},"Structured Output Parser":{"ai_outputParser":[[{"node":"Extract Job Details","type":"ai_outputParser","index":0}]]},"Google Custom Search API Request":{"main":[[{"node":"Filter LinkedIn Profiles","type":"main","index":0}]]}}}


name: Build a RAG System with Automatic Citations using Qdrant, Gemini & OpenAI
author_name: Davide
author_username: n3witalia
categories: []
created_at: 2025-06-18T14:37:45.594Z
updated_at: 2025-06-18T14:37:45.594Z
url: https://n8n.io/workflows/5023
scraped_at: 2025-07-06 21:16:30
description:
  This workflow implements a Retrieval-Augmented Generation (RAG) system that:

  Stores vectorized documents in Qdrant,
  Retrieves relevant content based on user input,
  Generates AI answers using Google Gemini,
  Automatically cites the document sources (from Google Drive).

  Workflow Steps

  Create Qdrant Collection
     A REST API node creates a new collection in Qdrant with specified vector size (1536) and cosine similarity.

  Load Files from Google Drive
     The workflow lists all files in a Google Drive folder, downloads them as plain text, and loops through each.

  Text Preprocessing & Embedding

     Documents are split into chunks (500 characters, with 50-character overlap).
     Embeddings are created using OpenAI embeddings (text-embedding-3-small assumed).
     Metadata (file name and ID) is attached to each chunk.

  Store in Qdrant
     All vectors, along with metadata, are inserted into the Qdrant collection.

  Chat Input & Retrieval

     When a chat message is received, the question is embedded and matched against Qdrant.
     Top 5 relevant document chunks are retrieved.
     A Gemini model is used to generate the answer based on those sources.

  Source Aggregation & Response

     File IDs and names are deduplicated.
     The AI response is combined with a list of cited documents (filenames).
     Final output:

            AI Response

       Sources: ["Document1", "Document2"]
  Main Advantages

  End-to-end Automation**: From document ingestion to chat response generation, fully automated with no manual steps.
  Scalable Knowledge Base**: Easy to expand by simply adding files to the Google Drive folder.
  Traceable Responses**: Each answer includes its source files, increasing transparency and trustworthiness.
  Modular Design**: Each step (embedding, storage, retrieval, response) is isolated and reusable.
  Multi-provider AI**: Combines OpenAI (for embeddings) and Google Gemini (for chat), optimizing performance and flexibility.
  Secure & Customizable**: Uses API credentials and configurable chunk size, collection name, etc.

  How It Works  
  Document Processing & Vectorization  
     The workflow retrieves documents from a specified Google Drive folder.  
     Each file is downloaded, split into chunks (using a recursive text splitter), and converted into embeddings via OpenAI.  
     The embeddings, along with metadata (file ID and name), are stored in a Qdrant vector database under the collection negozio-emporio-verde.  

  Query Handling & Response Generation  
     When a user submits a chat message, the workflow:  
       Embeds the query using OpenAI.  
       Retrieves the top 5 relevant document chunks from Qdrant.  
       Uses Google Gemini to generate a response based on the retrieved context.  
       Aggregates and deduplicates the source file names from the retrieved chunks.  
     The final output includes both the AI-generated response and a list of source documents (e.g., Sources: ["FAQ.pdf", "Policy.txt"]).  

  Set Up Steps  
  Configure Qdrant Collection  
     Replace QDRANTURL and COLLECTION in the "Create collection" HTTP node to initialize the Qdrant collection with:  
       Vector size: 1536 (OpenAI embedding dimension).  
       Distance metric: Cosine.  
     Ensure the "Clear collection" node is configured to reset the collection if needed.  

  Google Drive & OpenAI Integration  
     Link the Google Drive node to the target folder (Test Negozio in this example).  
     Verify OpenAI and Google Gemini API credentials are correctly set in their respective nodes.  

  Metadata & Output Customization  
     Adjust the "Aggregate" and "Response" nodes if additional metadata fields are needed.  
     Modify the "Output" node to format the response (e.g., changing Sources: {{...}} to match your preferred style).  

  Testing  
     Trigger the workflow manually to test document ingestion.  
     Use the chat interface to verify responses include accurate source attribution.  

  Note: Replace placeholder values (e.g., QDRANTURL) with actual endpoints before deployment.

  Need help customizing?  
  Contact me for consulting and support or add me on Linkedin. 

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.googleDrive","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.chainRetrievalQa","@n8n/n8n-nodes-langchain.embeddingsOpenAi","@n8n/n8n-nodes-langchain.retrieverVectorStore","@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.vectorStoreQdrant","@n8n/n8n-nodes-langchain.lmChatGoogleGemini"]

workflow_json:
  {"id":"OAvKQCYsly0DTlci","meta":{"instanceId":"a4bfc93e975ca233ac45ed7c9227d84cf5a2329310525917adaf3312e10d5462","templateCredsSetupCompleted":true},"name":"Complete RAG System with Automatic Source Citations Using Qdrant","tags":[],"nodes":[{"id":"65d3e882-ef84-4b3b-88b0-bb69bbe6886f","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-400,220],"parameters":{},"typeVersion":1},{"id":"db531b5a-588a-4982-aa00-e565d6f5610b","name":"Embeddings OpenAI1","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[940,480],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"4zwP0MSr8zkNvvV9","name":"OpenAi account"}},"typeVersion":1.1},{"id":"5a1606d8-d851-4fb1-a18a-a45f5de3adf2","name":"Default Data Loader1","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[1080,480],"parameters":{"options":{"metadata":{"metadataValues":[{"name":"file_id","value":"={{ $('Get file').item.json.id }}"},{"name":"file_name","value":"={{ $('Get file').item.json.name }}"}]}},"dataType":"binary","binaryMode":"specificField"},"typeVersion":1},{"id":"9923f6be-c2a5-4498-9fd2-0ed74ccdab35","name":"Qdrant Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStoreQdrant","position":[1000,240],"parameters":{"mode":"insert","options":{},"qdrantCollection":{"__rl":true,"mode":"list","value":"negozio-emporio-verde","cachedResultName":"negozio-emporio-verde"}},"credentials":{"qdrantApi":{"id":"iyQ6MQiVaF3VMBmt","name":"QdrantApi account (Hetzner)"}},"typeVersion":1},{"id":"db1f5e71-28ef-427e-8911-275ddea4e44f","name":"Create collection","type":"n8n-nodes-base.httpRequest","position":[-180,-140],"parameters":{"url":"http://QDRANTURL/collections/COLLECTION","method":"PUT","options":{},"jsonBody":"{\n  \"vectors\": {\n    \"size\": 1536,\n    \"distance\": \"Cosine\"  \n  },\n  \"shard_number\": 1,  \n  \"replication_factor\": 1,  \n  \"write_consistency_factor\": 1 \n}","sendBody":true,"sendHeaders":true,"specifyBody":"json","authentication":"genericCredentialType","genericAuthType":"httpHeaderAuth","headerParameters":{"parameters":[{"name":"Content-Type","value":"application/json"}]}},"credentials":{"httpHeaderAuth":{"id":"qhny6r5ql9wwotpn","name":"Qdrant API (Hetzner)"}},"typeVersion":4.2},{"id":"e0936863-4ece-429c-bf32-49f75b5c8bf0","name":"Recursive Character Text Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","position":[1060,660],"parameters":{"options":{},"chunkSize":500,"chunkOverlap":50},"typeVersion":1},{"id":"1311350d-75d3-4edc-8fa9-584a1c36da6d","name":"Loop Over Items","type":"n8n-nodes-base.splitInBatches","position":[420,220],"parameters":{"options":{}},"typeVersion":3},{"id":"1f9b623c-4e93-44da-8c9d-cfe9f5d5be9a","name":"Wait","type":"n8n-nodes-base.wait","position":[1380,240],"webhookId":"89248db2-59f2-4b61-9cd5-71406144efee","parameters":{},"typeVersion":1.1},{"id":"22aacdc0-8ec5-42e2-b9a0-fb9e5a4aa23c","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-460,1080],"webhookId":"c9460030-9e23-41c4-9fcd-6c4c7fadf784","parameters":{"options":{}},"typeVersion":1.1},{"id":"1e132fba-00a5-414a-8f37-f34645f668ff","name":"Question and Answer Chain","type":"@n8n/n8n-nodes-langchain.chainRetrievalQa","position":[120,1280],"parameters":{"options":{}},"typeVersion":1.5},{"id":"badee75e-bca7-49e4-9095-c098cb7adcab","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[0,1500],"parameters":{"options":{},"modelName":"models/gemini-1.5-flash"},"credentials":{"googlePalmApi":{"id":"0p34rXqIqy8WuoPg","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"ad8cec62-ce1d-4e58-8e40-9a7a9f4f93c7","name":"Vector Store Retriever","type":"@n8n/n8n-nodes-langchain.retrieverVectorStore","position":[160,1500],"parameters":{"topK":5},"typeVersion":1},{"id":"0c7d1804-4525-4117-a19d-f2d59195fd47","name":"Qdrant Vector Store1","type":"@n8n/n8n-nodes-langchain.vectorStoreQdrant","position":[40,1680],"parameters":{"options":{},"qdrantCollection":{"__rl":true,"mode":"list","value":"negozio-emporio-verde","cachedResultName":"negozio-emporio-verde"}},"credentials":{"qdrantApi":{"id":"iyQ6MQiVaF3VMBmt","name":"QdrantApi account (Hetzner)"}},"typeVersion":1.1},{"id":"6cfe7e8a-e593-4e4e-a0be-3379dd85c748","name":"Embeddings OpenAI","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[20,1880],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"4zwP0MSr8zkNvvV9","name":"OpenAi account"}},"typeVersion":1.2},{"id":"d9aa08b5-ed04-4506-9a2e-f994d4694f48","name":"Embeddings OpenAI4","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[100,1140],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"4zwP0MSr8zkNvvV9","name":"OpenAi account"}},"typeVersion":1.2},{"id":"d0d32470-b1df-40ec-aac1-32e4c9cf2e4e","name":"Merge1","type":"n8n-nodes-base.merge","position":[640,1140],"parameters":{"mode":"combine","options":{},"combineBy":"combineAll"},"typeVersion":3.1},{"id":"2edbca72-220e-45a6-8295-830d58611549","name":"Aggregate","type":"n8n-nodes-base.aggregate","position":[460,940],"parameters":{"options":{},"fieldsToAggregate":{"fieldToAggregate":[{"fieldToAggregate":"document.metadata.file_id"},{"fieldToAggregate":"document.metadata.file_name"}]}},"typeVersion":1},{"id":"8d116bc2-73d8-4349-8b4e-8dc0aef7cfa3","name":"Clear collection","type":"n8n-nodes-base.httpRequest","position":[-140,220],"parameters":{"url":"http://QDRANTURL/collections/COLLECTION/points/delete","method":"POST","options":{},"jsonBody":"{\n  \"filter\": {}\n}","sendBody":true,"sendHeaders":true,"specifyBody":"json","authentication":"genericCredentialType","genericAuthType":"httpHeaderAuth","headerParameters":{"parameters":[{"name":"Content-Type","value":"application/json"}]}},"credentials":{"httpHeaderAuth":{"id":"qhny6r5ql9wwotpn","name":"Qdrant API (Hetzner)"}},"typeVersion":4.2},{"id":"0d4d3bab-2370-4ced-8f5d-2977d360f72b","name":"Get folder","type":"n8n-nodes-base.googleDrive","position":[120,220],"parameters":{"filter":{"driveId":{"__rl":true,"mode":"list","value":"My Drive","cachedResultUrl":"https://drive.google.com/drive/my-drive","cachedResultName":"My Drive"},"folderId":{"__rl":true,"mode":"list","value":"1RO5ByPhq2yvYLmbapTNC_kKdU5lZd4W5","cachedResultUrl":"https://drive.google.com/drive/folders/1RO5ByPhq2yvYLmbapTNC_kKdU5lZd4W5","cachedResultName":"Test Negozio"}},"options":{},"resource":"fileFolder"},"credentials":{"googleDriveOAuth2Api":{"id":"HEy5EuZkgPZVEa9w","name":"Google Drive account (n3w.it)"}},"typeVersion":3},{"id":"e81ee92f-db50-4c62-aac7-7bc03e63cc1a","name":"Get file","type":"n8n-nodes-base.googleDrive","position":[700,240],"parameters":{"fileId":{"__rl":true,"mode":"id","value":"={{ $json.id }}"},"options":{"googleFileConversion":{"conversion":{"docsToFormat":"text/plain"}}},"operation":"download"},"credentials":{"googleDriveOAuth2Api":{"id":"HEy5EuZkgPZVEa9w","name":"Google Drive account (n3w.it)"}},"typeVersion":3},{"id":"c9bdc00a-ca8c-4457-8720-e6dce07e6b22","name":"chatInput","type":"n8n-nodes-base.set","position":[-200,1080],"parameters":{"options":{},"assignments":{"assignments":[{"id":"282b9bed-e5fd-4edb-95d5-682bcc08e070","name":"chatInput","type":"string","value":"={{ $json.chatInput }}"}]}},"typeVersion":3.4},{"id":"b65ca747-e738-4b7a-ae02-83840ce0a460","name":"Retrive sources","type":"@n8n/n8n-nodes-langchain.vectorStoreQdrant","position":[140,940],"parameters":{"mode":"load","topK":5,"prompt":"={{ $json.chatInput }}","options":{},"qdrantCollection":{"__rl":true,"mode":"list","value":"negozio-emporio-verde","cachedResultName":"negozio-emporio-verde"}},"credentials":{"qdrantApi":{"id":"iyQ6MQiVaF3VMBmt","name":"QdrantApi account (Hetzner)"}},"typeVersion":1.1},{"id":"265e2613-0155-4585-8d5c-fcda26975585","name":"Output","type":"n8n-nodes-base.set","position":[1060,1140],"parameters":{"options":{},"assignments":{"assignments":[{"id":"b296c92b-d9ee-4322-b972-d1069d01feb8","name":"output","type":"string","value":"={{ $('Question and Answer Chain').item.json.response }}\n\nSources: {{ (JSON.stringify($json.unique_file_names)) }},"}]}},"typeVersion":3.4},{"id":"9407fcaf-d90a-46bd-9b1f-b0493a0357c1","name":"Response","type":"n8n-nodes-base.code","position":[880,1140],"parameters":{"jsCode":"const item = $input.item.json;\n\n// Creiamo Set per rimuovere duplicati\nconst uniqueFileIds = Array.from(new Set(item.file_id));\nconst uniqueFileNames = Array.from(new Set(item.file_name));\n\n// Ritorniamo un item con i valori univoci\nreturn [\n  {\n    json: {\n      unique_file_ids: uniqueFileIds,\n      unique_file_names: uniqueFileNames\n    }\n  }\n];\n"},"typeVersion":2},{"id":"0b8a715f-36eb-49fd-895e-e8e76fdbb0c1","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-360,-520],"parameters":{"width":840,"height":220,"content":"## Complete RAG System with Automatic Source Citations Using Qdrant\n\nThis workflow implements a **Retrieval-Augmented Generation (RAG)** system that:\n\n* Stores vectorized documents in **Qdrant**,\n* Retrieves relevant content based on user input,\n* Generates AI answers using **Google Gemini**,\n* Automatically **cites the document sources** (from Google Drive).\n"},"typeVersion":1},{"id":"3220c323-a3d6-4855-ad05-2aaf8761771e","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[80,-200],"parameters":{"color":6,"width":880,"height":220,"content":"# STEP 1\n\n## Create Qdrant Collection\nChange:\n- QDRANTURL\n- COLLECTION"},"typeVersion":1},{"id":"738835a3-888b-426e-a897-8ddc630b85bf","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-220,120],"parameters":{"color":4,"width":620,"height":520,"content":"# STEP 2\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Documents vectorization with Qdrant and Google Drive\nChange:\n- QDRANTURL\n- COLLECTION"},"typeVersion":1},{"id":"70205511-2c4a-4f2f-8f68-97e3ede28851","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[1200,620],"parameters":{"color":4,"width":520,"height":420,"content":"Set as metadata:\n- FILE_ID from Google Drive\n- FILE_NAME from Google Drive\n\n```\n{\n  \"source\": \"blob\",\n  \"blobType\": \"text/plain\",\n  \"loc\": {\n    \"lines\": {\n      \"from\": 1,\n      \"to\": 15\n    }\n  },\n  \"file_id\": \"xxxxxxxxxxxxxxxxxxxxxxxxxx\",\n  \"file_name\": \"FAQ\"\n}\n```\n\n\n"},"typeVersion":1},{"id":"921497ff-1beb-4bd1-aecd-81b68c5a0357","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[680,1400],"parameters":{"color":3,"width":520,"height":200,"content":"The final output is:\n\n\nRESPONSE\n\nSources: [\"FILENAME 1\", \"FILENAME 2\",...]\n\n"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"33d05a21-33dd-422a-ba58-3eafffc7d50a","connections":{"Wait":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Merge1":{"main":[[{"node":"Response","type":"main","index":0}]]},"Get file":{"main":[[{"node":"Qdrant Vector Store","type":"main","index":0}]]},"Response":{"main":[[{"node":"Output","type":"main","index":0}]]},"Aggregate":{"main":[[{"node":"Merge1","type":"main","index":0}]]},"chatInput":{"main":[[{"node":"Question and Answer Chain","type":"main","index":0},{"node":"Retrive sources","type":"main","index":0}]]},"Get folder":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Loop Over Items":{"main":[[],[{"node":"Get file","type":"main","index":0}]]},"Retrive sources":{"main":[[{"node":"Aggregate","type":"main","index":0}]]},"Clear collection":{"main":[[{"node":"Get folder","type":"main","index":0}]]},"Embeddings OpenAI":{"ai_embedding":[[{"node":"Qdrant Vector Store1","type":"ai_embedding","index":0}]]},"Embeddings OpenAI1":{"ai_embedding":[[{"node":"Qdrant Vector Store","type":"ai_embedding","index":0}]]},"Embeddings OpenAI4":{"ai_embedding":[[{"node":"Retrive sources","type":"ai_embedding","index":0}]]},"Qdrant Vector Store":{"main":[[{"node":"Wait","type":"main","index":0}]]},"Default Data Loader1":{"ai_document":[[{"node":"Qdrant Vector Store","type":"ai_document","index":0}]]},"Qdrant Vector Store1":{"ai_vectorStore":[[{"node":"Vector Store Retriever","type":"ai_vectorStore","index":0}]]},"Vector Store Retriever":{"ai_retriever":[[{"node":"Question and Answer Chain","type":"ai_retriever","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"Question and Answer Chain","type":"ai_languageModel","index":0}]]},"Question and Answer Chain":{"main":[[{"node":"Merge1","type":"main","index":1}]]},"When chat message received":{"main":[[{"node":"chatInput","type":"main","index":0}]]},"Recursive Character Text Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader1","type":"ai_textSplitter","index":0}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"Clear collection","type":"main","index":0}]]}}}


name: Build Custom Workflows Automatically with GPT-4o, RAG, and Web Search
author_name: Franz
author_username: agents-by-franz
categories: []
created_at: 2025-06-18T15:09:18.253Z
updated_at: 2025-06-18T15:09:18.253Z
url: https://n8n.io/workflows/5024
scraped_at: 2025-07-06 21:16:30
description:
  🚀 What the “Agent Builder” template does

  Need to turn a one-line chat request into a fully-wired n8n workflow template—complete with AI agents, RAG, and web-search super-powers—without lifting a finger?
  That’s exactly what Agent Builder automates:

  Listens to any incoming chat message (via the Chat Trigger).
  Spins up an AI architect that analyses the request, searches the web, reads n8n docs from a Pinecone vector store, and designs the smallest possible set of nodes.
  Auto-generates a ready-to-import JSON template and hands it back as a downloadable file—plus all the supporting assets (embeddings, vector store etc.) so the next prompt is even smarter.

  Think of it as your personal “workflow chef”: you shout the order, it shops for ingredients, cooks, plates, and serves the meal. All you do is eat.

  🤗 Who will love this?

  No-code builders / power users** who don’t want to wrestle with AI node wiring.
  Agencies & consultants** delivering lots of bespoke automations.
  Internal platform teams** who need a “workflow self-service portal” for non-technical colleagues.

  🧩 How it’s wired

  | Sub-process                | What happens inside                                                                                                                                                                              | Key nodes                                                                              |
  | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
  | Web Crawler (optional) | Firecrawl scrapes docs.n8n.io (or any URL you drop in) and streams raw markdown back.                                                                                                            | Set URL → HTTP Request (Extract) → Wait & Retry                                      |
  | RAG Trainer            | Splits the scraped docs, embeds them with OpenAI, and upserts vectors into Pinecone.                                                                                                             | Recursive Text Splitter → Embeddings OpenAI → Train Pinecone                         |
  | Agent Builder          | The star of the show – orchestrates GPT-4o (via OpenRouter), SerpAPI web-search, your Pinecone index and a Structured Output Parser to produce → validate → prettify the final n8n template. | Chat Trigger → AI Agent → OpenAI (validator) → Code (extract) → Convert to JSON file |

  Every arrow in the drawn workflow is pre-connected, so the generated template always passes n8n’s import check.

  🛠️ Getting set up (5 quick creds)

  | Service                                             | Credential type                                            |
  | --------------------------------------------------- | ---------------------------------------------------------- |
  | OpenAI / Azure OpenAI – embeddings & validation | OpenAI API                                               |
  | Pinecone – vector store                         | Pinecone API                                             |
  | OpenRouter – GPT-4o LLM                         | OpenRouter API Key                                       |
  | SerpAPI – web search                            | SerpAPI Key                                              |
  | Firecrawl (only if you plan to crawl)           | Generic Header Auth → Authorization: Bearer YOUR_KEY |

  Each node already expects those creds; just create them once, select in the dropdown, hit Activate.

  🏃‍♀️ What a typical run looks like

  User says: “Build me a workflow that monitors our support inbox, summarises new tickets with GPT and posts to Slack.”
  Chat Trigger captures the message.
  AI Agent:

     queries Pinecone for relevant n8n docs,
     fires a SerpAPI search for “n8n gmail trigger example”,
     sketches an architecture (Gmail Trigger → GPT Model → Slack).
  The agent returns JSON ➜ OpenAI node double-checks field names, connections, type versions.
  A tiny JS Code node slices the JSON out of the chat blob and saves it as template.json ready for download.
  You download, import, and… done.

  ✏️ Customising

  Switch the LLM* – plug in Claude 3, Gemini 1.5, or a local model; just swap the *OpenRouter Chat Model node.
  Point the RAG at your own docs* – change the crawl URL or feed PDFs via the *Default Data Loader.
  Hard-code preferred nodes* – edit the “User node preferences” in the system message so the agent always chooses *Notion for databases, etc.

  🥡 Take-away notes

  It's a prototype feel free to experiment with it to improve its capabilities.
  Have fun building!**

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.embeddingsOpenAi","@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","@n8n/n8n-nodes-langchain.toolSerpApi","@n8n/n8n-nodes-langchain.vectorStorePinecone","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.openAi","@n8n/n8n-nodes-langchain.lmChatOpenRouter"]

workflow_json:
  {"id":"M7saccCy1gO4g2zr","meta":{"instanceId":"5116f2f7706b559eceadfeb527d2f261505621d6d31889c13b53a0633d9b86eb","templateCredsSetupCompleted":true},"name":"Agent_Builder","tags":[],"nodes":[{"id":"ee1c8a9a-e0fb-46d2-8274-140f5b297fba","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-2320,240],"webhookId":"4e30031a-81f0-4d4d-bc44-2347530b51e8","parameters":{"options":{}},"typeVersion":1.1},{"id":"243ba102-72bf-441a-b247-d784b3b054bd","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","onError":"continueRegularOutput","position":[-1920,240],"parameters":{"options":{"systemMessage":"# General Instruction\nYou are a helpful AI agents that outputs n8n agents / workflows in JSON format.\n\n# Input\nYou receive the user request what the agent should be able to accomplish.\n\n# Output\nThe Output must be a valid n8n template JSON\n\n# Workflow\nThink carefully how the agent the user requests can be build. Start by conceptualizing the architecture. It might be helpful to reflect in how a human team would tackle the task or go backwards (starting with the desired end state). Note that most workflows need an AI agent as its \"brain\". Consult your tools whenever beneficial. Once you thought of a meaningful structure actually populate the template with the nodes. Work very iterative and use the tools EXTENSIVELY! Fill the nodes with the correct content and CONNECT them properly! In a last check everything and make sure all nodes are properly connected! All but the trigger and final Output node must be connected to at least one input and one output node. Whenever you need information regarding what is possible in n8n, with what nodes and how they are set up and connected, consult the tools as you see it fit. \n\n# Tools\nYou have access to the following tools:\n1) Pinecone vector store containing some of n8n decumentation, saved in a Pinecone Vector database\n2) SerpAPI web search tool, with which you can search for example existing n8n workflows and templates or node characteristics (leverage this a lot!)\n\n# User node preferences (if not specified differently by the user use the following nodes for the listed functionalities):\nvector database: {{ $json['vector database'] }}\nchat model: {{ $json['chat model'] }}\nembeddings: {{ $json.embedding }}\nweb search tool: {{ $json['web search tool'] }}\n\n# Examples (variables are replaced with \"...\")\n--> output refers to the final result. still do not skip an elaborate step by step thinking process and extensive tool use!\n## example 1\n### input: automation flow is designed to automatically monitor incoming Gmail messages, analyze their content and context using AI, and intelligently classify them with appropriate labels for better email organization and prioritization\n\n### output: {\n  \"id\": \"uf6t5qhnQMgilteE\",\n  \"meta\": {\n    \"instanceId\": \"f694ebfb8236012bcdeb0adbc4faa465b6fa315f9ad30732114d26f7419da901\",\n    \"templateCredsSetupCompleted\": true\n  },\n  \"name\": \"Email Manager\",\n  \"tags\": [\n    {\n      \"id\": \"xG398zgKum2bPs6D\",\n      \"name\": \"Personal Assistant\",\n      \"createdAt\": \"2025-05-28T13:58:43.876Z\",\n      \"updatedAt\": \"2025-05-28T13:58:43.876Z\"\n    }\n  ],\n  \"nodes\": [\n    {\n      \"id\": \"5e01a927-caf7-41ad-aca7-d7504e313564\",\n      \"name\": \"Gmail Trigger\",\n      \"type\": \"n8n-nodes-base.gmailTrigger\",\n      \"position\": [\n        -20,\n        -60\n      ],\n      \"parameters\": {\n        \"filters\": {},\n        \"pollTimes\": {\n          \"item\": [\n            {\n              \"mode\": \"everyMinute\"\n            }\n          ]\n        }\n      },\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"Ldq2rjN6Dod5DoKl\",\n          \"name\": \"Gmail account\"\n        }\n      },\n      \"typeVersion\": 1.2\n    },\n    {\n      \"id\": \"a8644856-a8bf-49de-84a7-3fd9f93550d3\",\n      \"name\": \"Gmail\",\n      \"type\": \"n8n-nodes-base.gmail\",\n      \"position\": [\n        200,\n        -20\n      ],\n      \"webhookId\": \"01c91a6b-4d45-4630-8e81-0f82ee5d6524\",\n      \"parameters\": {\n        \"simple\": false,\n        \"options\": {},\n        \"messageId\": \"=...\",\n        \"operation\": \"get\"\n      },\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"Ldq2rjN6Dod5DoKl\",\n          \"name\": \"Gmail account\"\n        }\n      },\n      \"typeVersion\": 2.1\n    },\n    {\n      \"id\": \"f6ddae9f-303b-46cd-980d-1d46fc4ecbec\",\n      \"name\": \"Structured Output Parser\",\n      \"type\": \"@n8n/n8n-nodes-langchain.outputParserStructured\",\n      \"position\": [\n        1000,\n        100\n      ],\n      \"parameters\": {\n        \"jsonSchemaExample\": \"{\\n\\t\\\"label\\\": \\\"Label name\\\", \\n\\\"label ID\\\": \\\"label ID\\\" \\n}\"\n      },\n      \"typeVersion\": 1.2\n    },\n    {\n      \"id\": \"cc6b0990-a778-4199-a0fe-80c83dfb9934\",\n      \"name\": \"Gmail1\",\n      \"type\": \"n8n-nodes-base.gmail\",\n      \"position\": [\n        1020,\n        -220\n      ],\n      \"webhookId\": \"575a4038-3b07-46b9-be69-39cfc1d47d7e\",\n      \"parameters\": {\n        \"labelIds\": \"= ... \",\n        \"messageId\": \"=...\",\n        \"operation\": \"addLabels\"\n      },\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"Ldq2rjN6Dod5DoKl\",\n          \"name\": \"Gmail account\"\n        }\n      },\n      \"typeVersion\": 2.1\n    },\n    {\n      \"id\": \"f47e8e55-f634-417f-b62f-60e47af71827\",\n      \"name\": \"Anthropic Chat Model\",\n      \"type\": \"@n8n/n8n-nodes-langchain.lmChatAnthropic\",\n      \"position\": [\n        380,\n        160\n      ],\n      \"parameters\": {\n        \"model\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"claude-sonnet-4-20250514\",\n          \"cachedResultName\": \"Claude Sonnet 4\"\n        },\n        \"options\": {}\n      },\n      \"credentials\": {\n        \"anthropicApi\": {\n          \"id\": \"BVgmqTRcPinCIX4S\",\n          \"name\": \"Anthropic account 3\"\n        }\n      },\n      \"typeVersion\": 1.3\n    },\n    {\n      \"id\": \"b0ed86c7-5ddd-48dc-aa93-5c4d5c1cacf7\",\n      \"name\": \"AI Agent\",\n      \"type\": \"@n8n/n8n-nodes-langchain.agent\",\n      \"position\": [\n        500,\n        -140\n      ],\n      \"parameters\": {\n        \"text\": \"Run the task.\",\n        \"options\": {\n          \"systemMessage\": \"=**Objective:** Analyze the provided email data and classify it with the most appropriate label. **Utilize the capability to check for prior email history (emails sent to or received from the sender by `max@trigify.io`)** to determine if this is a first-time interaction (cold email) or part of an existing relationship. This context is crucial for accurate labeling, especially for distinguishing between Marketing, Notifications, and FYI. Respond with *only* the corresponding Label ID.\\n\\n**Your Email Address (for context):** `max@trigify.io`\\n\\n**Key Capabilities (to be used by the system executing this prompt):**\\n* **Check Prior Email History:** Before full classification, determine if any prior email correspondence exists between `max@trigify.io` and `...`. This check should yield \\\"Yes\\\" (history exists) or \\\"No\\\" (no history found).\\n\\n**Input Email Data (from n8n JSON item for the *current* email):**\\n* **Sender Email:** `...`\\n* **Sender Name:** `...`\\n* **Direct Recipient Emails (To):** `...`\\n* **CC Recipient Emails:** `...` *(Added this based on your JSON, use if populated)*\\n* **Subject:** `...`\\n* **Body (Plain Text):** `...`\\n* **Existing Gmail Labels (for current email):** `...`\\n* **Auto-Submitted Header:** `...`\\n* **Original Sender Header (if different from From):** `...`\\n* **In-Reply-To Header (for current email):** `...`\\n* **References Header (for current email):** `...`\\n* **List-Unsubscribe Header:** `...`\\n* **Precedence Header:** `...` (e.g., \\\"Bulk\\\")\\n\\n**Labels, Descriptions, and Prioritization Logic:**\\n\\n**Guidance on Using Prior Email History & Unsubscribe Links:**\\n* **Prior Email History = \\\"No\\\":** Strong indicator of a **cold/unsolicited email**.\\n    * If promotional/sales pitch: Likely \\\"Marketing.\\\"\\n    * If exceptionally personalized & high-value for Trigify: Rare \\\"To Respond.\\\"\\n* **Prior Email History = \\\"Yes\\\":** Indicates an **existing relationship/conversation**.\\n    * If it's an update on terms, policies, or service changes from this known entity: Likely \\\"Notification.\\\"\\n    * If it's a newsletter Max subscribed to: Could be \\\"FYI\\\" or \\\"Marketing\\\" based on content.\\n    * If it's a direct message requiring action: Likely \\\"To Respond.\\\"\\n* **`List-Unsubscribe` Header or Unsubscribe Links in Body:**\\n    * Common in \\\"Marketing\\\" emails.\\n    * Also present in many legitimate \\\"Notification\\\" emails (e.g., service updates, policy changes like the DPA example) and some \\\"FYI\\\" newsletters for compliance.\\n    * **Therefore, an unsubscribe link alone does not define the category. Consider it alongside Prior Email History and email content/purpose.**\\n* **`Precedence: Bulk` Header:** Often indicates mass mailings, common for Marketing, Notifications, and some FYIs.\\n\\n---\\n\\n* **To Respond (Label ID: `Label_5151750749488724401`):**\\n    * **Primary Criteria:** Requires direct, timely action/reply from `max@trigify.io`.\\n    * **Key Indicators (especially if Prior Email History = \\\"Yes\\\"):** Direct questions to Max, assigned tasks, requests for info for Trigify, deadlines for Max, part of an active conversation (indicated by `In-Reply-To`/`References`).\\n    * **Sales Process Prioritization (Warm Leads/Active Processes - typically Prior Email History = \\\"Yes\\\"):** Ongoing, active Trigify sales process discussions.\\n    * **High-Value Cold Outreach (Exceptional Cases - Prior Email History = \\\"No\\\"):** Highly personalized, strategic opportunity for Trigify requiring Max's personal attention. (Default for cold sales is \\\"Marketing\\\").\\n\\n* **FYI (Label ID: `Label_7518716752151077752`):**\\n    * **Primary Criteria:** For Max's awareness; no immediate action/reply required.\\n    * **Key Indicators:**\\n        * Max is CC'd, primary action for others.\\n        * General announcements, *non-promotional* newsletters from *known entities/subscriptions* (Prior Email History = \\\"Yes\\\" or sender is clearly a subscribed source) that aren't critical service notifications.\\n        * Informational updates within ongoing projects where Max isn't the primary actor.\\n    * If an email is a mass mailing (`Precedence: Bulk`, `List-Unsubscribe` present) from a *known entity* (Prior Email History = \\\"Yes\\\") and is purely informational without a direct call to action or critical service update, it could be \\\"FYI.\\\"\\n\\n* **Comment (Label ID: `Label_1470120230130814788`):**\\n    * Comment/feedback on a document, task, system (e.g., subject \\\"New comment on...\\\").\\n\\n* **Notification (Label ID: `Label_9`):**\\n    * **Primary Criteria:** Provides important, often non-promotional, updates or alerts regarding an existing service, account, or system that `max@trigify.io` or Trigify uses or is affected by. Action is typically awareness, potential configuration change, or noting a deadline, rather than a conversational reply.\\n    * **Key Indicators:**\\n        * **Updates from Known Service Providers (Prior Email History = \\\"Yes\\\" is common):**\\n            * Changes to Terms of Service, Privacy Policies, Data Processing Agreements (DPAs like the \\\"Plain\\\" example).\\n            * Critical service availability announcements (outages, maintenance).\\n            * Security alerts related to an account Max uses.\\n            * Important updates about features or functionality of a service Trigify relies on, which are not primarily marketing new features.\\n        * System-generated alerts (e.g., `Auto-Submitted Header` = `auto-generated`) like social media notifications, non-meeting calendar reminders, some financial transaction alerts.\\n        * Subject lines may contain: \\\"Important Update,\\\" \\\"Service Notification,\\\" \\\"Policy Change,\\\" \\\"DPA Update,\\\" \\\"Security Alert.\\\"\\n        * Even if a `List-Unsubscribe` link is present (for compliance), if the core content is a critical service/account/legal update from a company Max/Trigify does business with, it's a \\\"Notification.\\\"\\n        * The `Existing Gmail Labels` might include `CATEGORY_UPDATES`.\\n\\n* **Meeting Update (Label ID: `Label_7958083858424702466`):**\\n    * Update specifically regarding a scheduled meeting (e.g., \\\"Accepted:\\\", \\\"Declined:\\\", \\\"Updated Invitation:\\\", \\\"Cancelled:\\\").\\n\\n* **Marketing (Label ID: `Label_5274550748854913384`):**\\n    * **Primary Criteria:** Unsolicited promotional sales pitch, advertisement, or general marketing newsletter, especially if **Prior Email History = \\\"No.\\\"**\\n    * **Key Indicators:**\\n        * **No prior email history found with the `Sender Email`,** AND the email is primarily aimed at selling a product/service or promoting a company/event to Max/Trigify.\\n        * Content is generic, focused on features/benefits without strong personalization to Max's known, active projects.\\n        * Contains a `List-Unsubscribe Header` AND the content is promotional.\\n        * `Existing Gmail Labels` may include `CATEGORY_PROMOTIONS`.\\n    * If **Prior Email History = \\\"Yes\\\"**: Could still be \\\"Marketing\\\" if it's a clearly promotional newsletter/offer from a known contact that doesn't fit \\\"Notification\\\" or demand a \\\"To Respond.\\\"\\n\\n---\\n\\n**Email Data for Classification (Summary):**\\n* **Prior Email History with Sender (Yes/No) - From the new capability**\\n* Sender Email: `...`\\n* Sender Name: `...`\\n* Direct Recipient Emails (To): `...`\\n* CC Recipient Emails: `...`\\n* Subject: `...`\\n* Body (Plain Text): `...`\\n* Existing Gmail Labels: `...`\\n* Auto-Submitted Header: `...`\\n* Original Sender Header: `...`\\n* In-Reply-To Header: `...`\\n* References Header: `...`\\n* List-Unsubscribe Header: `...`\\n* Precedence Header: `...`\\n\\n**Output:** [Provide ONLY the Label ID here]\"\n        },\n        \"promptType\": \"define\",\n        \"hasOutputParser\": true\n      },\n      \"typeVersion\": 1.9\n    },\n    {\n      \"id\": \"f4bbdda0-dcd8-41a7-a870-69dfcb747a4f\",\n      \"name\": \"Get Email\",\n      \"type\": \"n8n-nodes-base.gmailTool\",\n      \"position\": [\n        760,\n        140\n      ],\n      \"webhookId\": \"c30886d9-3d98-464d-82b8-e7649c87610a\",\n      \"parameters\": {\n        \"filters\": {\n          \"q\": \"=from:...\"\n        },\n        \"operation\": \"getAll\",\n        \"returnAll\": \"=...\"\n      },\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"Kv7fHf3kWbBam6RH\",\n          \"name\": \"Gmail account 2\"\n        }\n      },\n      \"typeVersion\": 2.1\n    },\n    {\n      \"id\": \"64c3b465-d2be-43cc-ad41-cc1298038640\",\n      \"name\": \"Check Sent\",\n      \"type\": \"n8n-nodes-base.gmailTool\",\n      \"position\": [\n        560,\n        180\n      ],\n      \"webhookId\": \"0854fad3-622e-44b4-9d61-5aae13c61433\",\n      \"parameters\": {\n        \"filters\": {\n          \"q\": \"=...\",\n          \"labelIds\": [\n            \"SENT\"\n          ]\n        },\n        \"operation\": \"getAll\"\n      },\n      \"credentials\": {\n        \"gmailOAuth2\": {\n          \"id\": \"Ldq2rjN6Dod5DoKl\",\n          \"name\": \"Gmail account\"\n        }\n      },\n      \"typeVersion\": 2.1\n    }\n  ],\n  \"active\": true,\n  \"pinData\": {\n    \"Gmail Trigger\": [\n      {\n        \"json\": {\n          \"To\": \"max@trigify.io\",\n          \"id\": \"1971723eacc72f08\",\n          \"From\": \"Coresignal <info@coresignal.com>\",\n          \"labels\": [\n            {\n              \"id\": \"INBOX\",\n              \"name\": \"INBOX\"\n            },\n            {\n              \"id\": \"IMPORTANT\",\n              \"name\": \"IMPORTANT\"\n            },\n            {\n              \"id\": \"CATEGORY_PROMOTIONS\",\n              \"name\": \"CATEGORY_PROMOTIONS\"\n            }\n          ],\n          \"Subject\": \"New MCP server: Direct data access for smarter AI\",\n          \"payload\": {\n            \"mimeType\": \"multipart/alternative\"\n          },\n          \"snippet\": \"What&#39;s new Empower your AI agent with Coresignal&#39;s data We&#39;re excited to unveil our latest news, the Coresignal MCP server that connects your LLM tools directly to our company, employee,\",\n          \"threadId\": \"1971723eacc72f08\",\n          \"historyId\": \"5524551\",\n          \"internalDate\": \"1748439919000\",\n          \"sizeEstimate\": 62610\n        }\n      },\n      {\n        \"json\": {\n          \"Cc\": \"\",\n          \"To\": \"max@trigify.io\",\n          \"id\": \"1971723cfa14c3df\",\n          \"From\": \"Plain <hello@plain.com>\",\n          \"labels\": [\n            {\n              \"id\": \"INBOX\",\n              \"name\": \"INBOX\"\n            },\n            {\n              \"id\": \"IMPORTANT\",\n              \"name\": \"IMPORTANT\"\n            },\n            {\n              \"id\": \"CATEGORY_UPDATES\",\n              \"name\": \"CATEGORY_UPDATES\"\n            },\n            {\n              \"id\": \"UNREAD\",\n              \"name\": \"UNREAD\"\n            }\n          ],\n          \"Subject\": \" Important update to Plain’s Data Processing Agreement (DPA)\",\n          \"payload\": {\n            \"mimeType\": \"multipart/alternative\"\n          },\n          \"snippet\": \"Hi Max, We&#39;re writing to let you know about an upcoming change to our Data Processing Agreement (DPA). What&#39;s changing? We are simplifying our notification process for subprocessor updates.\",\n          \"threadId\": \"1971723cfa14c3df\",\n          \"historyId\": \"5524408\",\n          \"internalDate\": \"1748439911000\",\n          \"sizeEstimate\": 45077\n        }\n      }\n    ]\n  },\n  \"settings\": {\n    \"executionOrder\": \"v1\"\n  },\n  \"versionId\": \"644d8154-7912-436a-8c05-e8e2f1092993\",\n  \"connections\": {\n    \"Gmail\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"AI Agent\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Gmail1\": {\n      \"main\": [\n        []\n      ]\n    },\n    \"AI Agent\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Gmail1\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Get Email\": {\n      \"ai_tool\": [\n        [\n          {\n            \"node\": \"AI Agent\",\n            \"type\": \"ai_tool\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Check Sent\": {\n      \"ai_tool\": [\n        [\n          {\n            \"node\": \"AI Agent\",\n            \"type\": \"ai_tool\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Gmail Trigger\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Gmail\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Anthropic Chat Model\": {\n      \"ai_languageModel\": [\n        [\n          {\n            \"node\": \"AI Agent\",\n            \"type\": \"ai_languageModel\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Structured Output Parser\": {\n      \"ai_outputParser\": [\n        [\n          {\n            \"node\": \"AI Agent\",\n            \"type\": \"ai_outputParser\",\n            \"index\": 0\n          }\n        ]\n      ]\n    }\n  }\n}\n\n\n## example 2: \n### input: Automate LinkedIn Posts with Claude AI, DALL-E Images & Google Sheets Approval\n\n### output: {\n  \"meta\": {\n    \"instanceId\": \"4e229722e6c43a4914d2d66178b48335adf795d73afbee5b0ea0c52938ef4d8e\"\n  },\n  \"nodes\": [\n    {\n      \"id\": \"2d694354-6ab0-42fd-abbf-d3085813fd49\",\n      \"name\": \"Idea Generator\",\n      \"type\": \"@n8n/n8n-nodes-langchain.agent\",\n      \"position\": [\n        1100,\n        200\n      ],\n      \"parameters\": {\n        \"text\": \"=Generate materials for my next LinkedIn post.\\n\\nHere are the ideas that we've already used: ....\\n\\nCome up with a new, super valuable and concrete post, and prepare all the needed materials for it:\\n- idea\\n- title\\n- text\\n- image description\\n\\nUse the least used bucket of content (out of my 4 buckets).\\n\\nBegin:\",\n        \"options\": {\n          \"systemMessage\": \"=ROLE: You're an expert in viral LinkedIn posts content creation with 10 years of experience. You've created viral posts that have gotten 10 billion views in total.\\n\\nOBJECTIVE: Your goal is to write a 1) name, 2) idea, 3) title, 4) text, and 5) image description for my next LinkedIn Post. They should be super valuable to my audience.\\n\\nSCENARIO: I run a LinkedIn blog about marketing and sales. My audience is marketers, salespeople, founders, B2B business owners, B2C business owners, brands. My goal is to help them build better brands with valuable, and practical content. \\nI have 4 main buckets of content on my page:\\n1) timeless principles. ideas for this videos are taken from timeless books: Influnece and Pre-Suasion by Robert Cialdini, $100M Leads and $100M Offers by Alex Hormozi, Ogilvy on Advertising.\\n2) case studies. for instance a case study breaking down on of the famous ads from the latest SuperBowl.\\n3) growth hacks. latest trends on how to grow with a proof. for instance an SEO tactic that became known in the last year.\\n4) contraversial ads. breakdowns of interesting and famous contraversial ads.\\nEvery video that I post is focused solely on one of the content buckets. That makes my content more diverse and covering more cool topics.\\n\\nEXPECTATION: Write me 1) name (short name for the post, less than 50 characters), 2) idea (detailed description in 3 sentences max), 3) title (the first sentence of the post, less than 80 characters, it should be ultra hooking), 4) full text of the post, 5) image description (the image is the first thing people will look at, so make it ultra hooking; write the image description to be super clear and ultra simple, so the AI image generator will precisely know that to generate; the image should be minimalistic) for a 200-300 words LinkedIn post from one of the content buckets described above.\\nMake sure to have great: hook, retention, and reward at the end.\\nThe post should clearly lead to a marketing/sales insight.\\nYour output should be in the JSON format.\\nIdea should always start with a category: Timeless principle, Case study, Growth hack, Contraversial ad.\\nExample output:\\n{\\\"name\\\": \\\"The Power of Social Proof\\\",\\n\\\"idea\\\": \\\"Timeless principle: Social proof is a psychological phenomenon that influences decision-making by showing how others' actions affect our own choices. It works universally across physical spaces and digital platforms. Marketers who strategically implement social proof elements can significantly increase conversion rates and customer trust.\\\",\\n\\\"title\\\": \\\"Why we can't resist looking up when others do (and what it means for sales)\\\",\\n\\\"text\\\": \\\"Why we can't resist looking up when others do (and what it means for sales)\\\\n\\\\nA psychology experiment once placed actors on a street corner to stare upward at nothing.\\\\n\\\\nWithin minutes, dozens of passersby stopped to look up too.\\\\n\\\\nThis is social proof in action—our natural tendency to follow others when uncertain.\\\\n\\\\nIn marketing, this same principle powers your conversion rates.\\\\n\\\\nNotice how differently you perceive:\\\\n\\\\n• A product with 5,000+ five-star reviews\\\\n• A service used by \\\\\\\"67% of Fortune 500 companies\\\\\\\"\\\\n• A landing page showing \\\\\\\"10,000+ satisfied customers\\\\\\\"\\\\n\\\\nCompared to identical offerings without these trust signals.\\\\n\\\\nBut here's what many marketers miss: social proof must feel authentic to work.\\\\n\\\\nGeneric testimonials or inflated numbers create skepticism, not confidence.\\\\n\\\\nThe most effective social proof strategies I've implemented for clients:\\\\n\\\\n1. Specificity: \\\\\\\"503 marketing agencies use our platform daily\\\\\\\" beats \\\\\\\"Hundreds of satisfied customers\\\\\\\"\\\\n\\\\n2. Relevance: Highlight testimonials from users who match your prospect's profile\\\\n\\\\n3. Recency: Fresh testimonials outperform older ones by 35% in our tests\\\\n\\\\n4. Visibility: Place social proof elements near decision points (like \\\\\\\"Buy Now\\\\\\\" buttons)\\\\n\\\\nImplement these four tactics, and you'll see the same psychological force that makes us look up at the sky work to increase your conversion rates.\\\\n\\\\nWhat's your most effective social proof strategy? Share below.\\\",\\n\\\"image\\\": \\\"Simple black background with grainy texture. Six basic stick figure silhouettes in white - five figures on the left all looking up, one figure on the right just starting to look up. Bold text in Inter Bold font at the center reads \\\\\\\"FOLLOW THE CROWD\\\\\\\" with \\\\\\\"FOLLOW\\\\\\\" in white and \\\\\\\"CROWD\\\\\\\" in light green (#cff150). No other elements or details. Clean, minimal design with plenty of empty space.\\\"}\\nNOTES:\\n- THE BACKGROUND OF THE IMAGE SHOULD ALWAYS BE BLACK AND DARK GRAINY FILM\\nTo accomplish your task you can use the web search.\"\n        },\n        \"promptType\": \"define\",\n        \"hasOutputParser\": true\n      },\n      \"retryOnFail\": true,\n      \"typeVersion\": 1.7\n    },\n    {\n      \"id\": \"991032b8-6839-4c5a-9df9-6e8e7a924c9e\",\n      \"name\": \"Sticky Note7\",\n      \"type\": \"n8n-nodes-base.stickyNote\",\n      \"position\": [\n        480,\n        100\n      ],\n      \"parameters\": {\n        \"color\": 6,\n        \"width\": 980,\n        \"height\": 480,\n        \"content\": \"# Generate a New Post Idea and All Materials\"\n      },\n      \"typeVersion\": 1\n    },\n    {\n      \"id\": \"40294f91-5002-44a2-91e7-5bee74c30698\",\n      \"name\": \"Sticky Note8\",\n      \"type\": \"n8n-nodes-base.stickyNote\",\n      \"position\": [\n        1480,\n        100\n      ],\n      \"parameters\": {\n        \"color\": 6,\n        \"width\": 1140,\n        \"height\": 480,\n        \"content\": \"# Generate an Image and Save\"\n      },\n      \"typeVersion\": 1\n    },\n    {\n      \"id\": \"b3e2d972-f763-4fa5-88eb-bbb1afa7fc2d\",\n      \"name\": \"Structured Output Parser\",\n      \"type\": \"@n8n/n8n-nodes-langchain.outputParserStructured\",\n      \"position\": [\n        1300,\n        400\n      ],\n      \"parameters\": {\n        \"jsonSchemaExample\": \"{\\n\\t\\\"name\\\": \\\"name\\\",\\n    \\\"idea\\\": \\\"idea\\\",\\n    \\\"title\\\": \\\"title\\\",\\n    \\\"text\\\": \\\"text\\\",\\n    \\\"image\\\": \\\"image\\\"\\n}\"\n      },\n      \"typeVersion\": 1.2\n    },\n    {\n      \"id\": \"77a4755a-0d64-4bce-b8a1-90b649d21039\",\n      \"name\": \"Anthropic Chat Model\",\n      \"type\": \"@n8n/n8n-nodes-langchain.lmChatAnthropic\",\n      \"position\": [\n        960,\n        400\n      ],\n      \"parameters\": {\n        \"model\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"claude-3-7-sonnet-20250219\",\n          \"cachedResultName\": \"Claude 3.7 Sonnet\"\n        },\n        \"options\": {}\n      },\n      \"typeVersion\": 1.3\n    },\n    {\n      \"id\": \"431ac158-ed33-4fdc-ae28-9a8fe1829f7e\",\n      \"name\": \"Perplexity Research\",\n      \"type\": \"@n8n/n8n-nodes-langchain.toolWorkflow\",\n      \"position\": [\n        1120,\n        400\n      ],\n      \"parameters\": {\n        \"name\": \"web_search\",\n        \"workflowId\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"eALld0YaOZuUCU5q\",\n          \"cachedResultName\": \"Perplexity Research\"\n        },\n        \"description\": \"Call this tool to make a web search query using Perplexity AI. It will automatically look at multiple relevant websites and combine all the valuable information in one clean response.\",\n        \"workflowInputs\": {\n          \"value\": {},\n          \"schema\": [\n            {\n              \"id\": \"query\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"removed\": false,\n              \"required\": false,\n              \"displayName\": \"query\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            }\n          ],\n          \"mappingMode\": \"defineBelow\",\n          \"matchingColumns\": [\n            \"query\"\n          ],\n          \"attemptToConvertTypes\": false,\n          \"convertFieldsToString\": false\n        }\n      },\n      \"typeVersion\": 2.1\n    },\n    {\n      \"id\": \"9098aa0e-e707-4825-a848-50f8a3ad767d\",\n      \"name\": \"Convert to File\",\n      \"type\": \"n8n-nodes-base.convertToFile\",\n      \"position\": [\n        1960,\n        280\n      ],\n      \"parameters\": {\n        \"options\": {},\n        \"operation\": \"toBinary\",\n        \"sourceProperty\": \"data[0].b64_json\"\n      },\n      \"typeVersion\": 1.1\n    },\n    {\n      \"id\": \"e7782adf-936a-47a5-8174-469e9d439b76\",\n      \"name\": \"Schedule\",\n      \"type\": \"n8n-nodes-base.scheduleTrigger\",\n      \"position\": [\n        560,\n        200\n      ],\n      \"parameters\": {\n        \"rule\": {\n          \"interval\": [\n            {\n              \"triggerAtHour\": 5\n            }\n          ]\n        }\n      },\n      \"typeVersion\": 1.2\n    },\n    {\n      \"id\": \"67704ef3-a0b3-4401-88aa-edc9b332c5fb\",\n      \"name\": \"Join Ideas\",\n      \"type\": \"n8n-nodes-base.code\",\n      \"position\": [\n        920,\n        200\n      ],\n      \"parameters\": {\n        \"jsCode\": \"// Get all incoming items\\nconst items = $input.all();\\n\\n// Extract the text field from each item\\nconst texts = items.map(item => item.json.idea);\\n\\n// Concatenate them (adjust the separator as needed)\\nconst concatenated = texts.join(\\\", \\\");\\n\\n// Return a single item with the concatenated text\\nreturn [{ json: { mergedText: concatenated } }];\"\n      },\n      \"typeVersion\": 2\n    },\n    {\n      \"id\": \"766ba040-6217-460e-a285-7dd3fe612654\",\n      \"name\": \"Pick One\",\n      \"type\": \"n8n-nodes-base.limit\",\n      \"position\": [\n        920,\n        700\n      ],\n      \"parameters\": {},\n      \"typeVersion\": 1\n    },\n    {\n      \"id\": \"ab433d53-9946-4778-bb59-bf636388da03\",\n      \"name\": \"Sticky Note1\",\n      \"type\": \"n8n-nodes-base.stickyNote\",\n      \"position\": [\n        480,\n        600\n      ],\n      \"parameters\": {\n        \"color\": 4,\n        \"width\": 1340,\n        \"height\": 300,\n        \"content\": \"# Auto Posting\"\n      },\n      \"typeVersion\": 1\n    },\n    {\n      \"id\": \"35b01ea3-8a91-4bdb-8b0b-e1e99f3c0482\",\n      \"name\": \"X\",\n      \"type\": \"n8n-nodes-base.twitter\",\n      \"disabled\": true,\n      \"position\": [\n        1140,\n        980\n      ],\n      \"parameters\": {\n        \"additionalFields\": {}\n      },\n      \"typeVersion\": 2\n    },\n    {\n      \"id\": \"25628428-075e-449c-8585-fc33d9185522\",\n      \"name\": \"Prepare Data for Instagram API\",\n      \"type\": \"n8n-nodes-base.set\",\n      \"disabled\": true,\n      \"position\": [\n        1400,\n        980\n      ],\n      \"parameters\": {\n        \"options\": {},\n        \"assignments\": {\n          \"assignments\": [\n            {\n              \"id\": \"8a4260ba-3bde-4444-8f42-8a8abd51ff0c\",\n              \"name\": \"ImageURL\",\n              \"type\": \"string\",\n              \"value\": \"=...\"\n            },\n            {\n              \"id\": \"1953ae03-6a86-4847-8686-5a928637be1d\",\n              \"name\": \"Caption\",\n              \"type\": \"string\",\n              \"value\": \"=...\"\n            }\n          ]\n        }\n      },\n      \"typeVersion\": 3.4\n    },\n    {\n      \"id\": \"61af7e71-5470-44a1-a157-2c15311b9dff\",\n      \"name\": \"Create Instagram Media Container\",\n      \"type\": \"n8n-nodes-base.facebookGraphApi\",\n      \"disabled\": true,\n      \"position\": [\n        1580,\n        980\n      ],\n      \"parameters\": {\n        \"edge\": \"media\",\n        \"node\": \"17841473009917118\",\n        \"options\": {\n          \"queryParameters\": {\n            \"parameter\": [\n              {\n                \"name\": \"caption\",\n                \"value\": \"=...\"\n              },\n              {\n                \"name\": \"image_url\",\n                \"value\": \"=...\"\n              }\n            ]\n          }\n        },\n        \"graphApiVersion\": \"v22.0\",\n        \"httpRequestMethod\": \"POST\"\n      },\n      \"typeVersion\": 1\n    },\n    {\n      \"id\": \"177e67d6-2783-4691-a90f-4b6fb398ab5e\",\n      \"name\": \"Wait for Container Processing\",\n      \"type\": \"n8n-nodes-base.wait\",\n      \"disabled\": true,\n      \"position\": [\n        1780,\n        980\n      ],\n      \"webhookId\": \"1b14c8bf-151a-4054-8215-093dd5b6cbcc\",\n      \"parameters\": {},\n      \"typeVersion\": 1.1\n    },\n    {\n      \"id\": \"8ef68b10-af6c-4f05-91ae-43586098b051\",\n      \"name\": \"Publish Post to Instagram\",\n      \"type\": \"n8n-nodes-base.facebookGraphApi\",\n      \"disabled\": true,\n      \"position\": [\n        1980,\n        980\n      ],\n      \"parameters\": {\n        \"edge\": \"media_publish\",\n        \"node\": \"17841473009917118\",\n        \"options\": {\n          \"queryParameters\": {\n            \"parameter\": [\n              {\n                \"name\": \"creation_id\",\n                \"value\": \"=...\"\n              }\n            ]\n          }\n        },\n        \"graphApiVersion\": \"v22.0\",\n        \"httpRequestMethod\": \"POST\"\n      },\n      \"typeVersion\": 1\n    },\n    {\n      \"id\": \"9702cd17-9bd3-429e-842e-56089b50d50b\",\n      \"name\": \"Sticky Note\",\n      \"type\": \"n8n-nodes-base.stickyNote\",\n      \"position\": [\n        1080,\n        920\n      ],\n      \"parameters\": {\n        \"width\": 1120,\n        \"height\": 260,\n        \"content\": \"## Twitter & Instagram\"\n      },\n      \"typeVersion\": 1\n    },\n    {\n      \"id\": \"8633b8e7-0119-4b60-a42e-362e26134772\",\n      \"name\": \"Sticky Note6\",\n      \"type\": \"n8n-nodes-base.stickyNote\",\n      \"position\": [\n        -260,\n        100\n      ],\n      \"parameters\": {\n        \"width\": 720,\n        \"height\": 1800,\n        \"content\": \"# 🛠️ Setup Guide  \\n**Author:** [Usman Liaqat](https://www.linkedin.com/in/usmanliaqat404)\\n\\nThis guide will walk you through the 7 steps to fully configure your automation workflow using Google Sheets, Google Drive, Anthropic, OpenAI, Perplexity AI and LinkedIn.\\n\\n---\\n\\n## ✅ Step 1: Set Up Google Sheets Credential\\n1. In the n8n Google Sheets node create a new credential using your Google account\\n\\n---\\n\\n## ✅ Step 2: Set Up Google Drive Credential\\n1. Go to the [Google Cloud Console](https://console.cloud.google.com) and create or select a project\\n2. Enable the Google Drive API under APIs & Services > Library\\n3. Still in APIs & Services, select Credentials from the left menu\\n4. Click + CREATE CREDENTIALS > OAuth client ID\\n5. For Application type, choose Web application\\n6. Under Authorized redirect URIs, paste the OAuth Redirect URL: https://oauth.n8n.cloud/oauth2/callback\\n7. Click Create, then copy the Client ID and Client Secret shown in the modal\\n8. In the n8n Google Drive node click Create Credential\\n9. Paste in the Client ID and Client Secret from Google Cloud\\n10. Click Sign in with Google, complete the OAuth consent flow, then Save your credential\\n\\n---\\n\\n## ✅ Step 3: Set Up Anthropic Credential\\n1. Navigate to the [Anthropic Console](https://console.anthropic.com/) and sign in or sign up\\n2. Generate an API key\\n3. In the n8n \\\"Anthropic Chat Model\\\" node click Create Credential, past the API key and save\\n\\n---\\n\\n## ✅ Step 4: Configure OpenAI via HTTP Request Node\\n1. Visit the [OpenAI API Keys](https://platform.openai.com/account/api-keys) page and create a new secret key\\n2. In the n8n OpenAI Image node in the Authentication select Generic Credential Type\\n3. In Generic Auth Type select Header Auth\\n4. Create a new Header Auth, Name = Authorization, Value = Bearer YOUR_TOKEN_HERE\\n\\n---\\n\\n## ✅ Step 5: Configure Perplexity AI via HTTP Request Node\\n1. Go to the [Perplexity API Portal](https://www.perplexity.ai/account/api/keys) and click Create Key\\n2. Copy the generated API key\\n3. Inside n8n, in the sub-workflow, open the Perplexity Research node\\n4. In the Authentication select Generic Credential Type\\n5. In Generic Auth Type select Header Auth\\n6. Create a new Header Auth, Name = Authorization, Value = Bearer YOUR_TOKEN_HERE\\n\\n---\\n\\n## ✅ Step 6: Set Up LinkedIn Credential\\n1. In the n8n LinkedIn node create a new credential using your LinkedIn account\\n\\n---\\n\\n## ✅ Step 7: Customize The System For Your Use Case\\n1. In the Idea Generator node adjust the prompts to reflect your content style and your topics\\n2. Create a folder in your Google Drive where you will store all the images\\n3. Put in that folder the image with the style of your brand, that you want to replicate every time\\n4. Paste the shared link to this image in the \\\"Image Style\\\" node\\n5. In the OpenAI Image node adjust the prompt to reflect your image style\\n6. Copy my [Google Sheet](https://docs.google.com/spreadsheets/d/1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs/edit?usp=sharing)\\n7. Select your Google Sheet in the Google Sheets nodes\\n8. Activate the system, now every day a new post will be created inside the Google Sheet, and once you've reviewed it (might edit it as well), set the status to \\\"ready\\\" and it will be posted; the posting mechanism is set to work every day, one post at a time\\n\\n---\\n\\nNow you're ready to run your workflow. Happy automating!\\n\"\n      },\n      \"typeVersion\": 1\n    },\n    {\n      \"id\": \"e853ea9d-5b19-4b7b-8dc4-110bcc481471\",\n      \"name\": \"OpenAI Image\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"position\": [\n        1760,\n        280\n      ],\n      \"parameters\": {\n        \"url\": \"https://api.openai.com/v1/images/edits\",\n        \"method\": \"POST\",\n        \"options\": {},\n        \"sendBody\": true,\n        \"contentType\": \"multipart-form-data\",\n        \"authentication\": \"genericCredentialType\",\n        \"bodyParameters\": {\n          \"parameters\": [\n            {\n              \"name\": \"model\",\n              \"value\": \"gpt-image-1\"\n            },\n            {\n              \"name\": \"image\",\n              \"parameterType\": \"formBinaryData\",\n              \"inputDataFieldName\": \"data\"\n            },\n            {\n              \"name\": \"prompt\",\n              \"value\": \"=You're a professional graphic designer.\\n\\nMake a new image in the style very very similar to the reference.\\n\\nCopy the style, spacing, minimalistic structure, especially copy the FONTS, and everything else.\\n\\nUse black and dark grainy film (mainly for the background), white and salad green (#cff150).\\n\\nMake the image super aestetic and minimalistic.\\n\\nMake it vertical 3x4.\\n\\nIt will be an image for a LinkedIn post.\\n\\nHere is the description of the new image:\\n...\"\n            }\n          ]\n        },\n        \"genericAuthType\": \"httpHeaderAuth\"\n      },\n      \"typeVersion\": 4.2\n    },\n    {\n      \"id\": \"2642278d-235c-46f0-994e-aa1ebec5ae64\",\n      \"name\": \"Image Style\",\n      \"type\": \"n8n-nodes-base.googleDrive\",\n      \"position\": [\n        1540,\n        280\n      ],\n      \"parameters\": {\n        \"fileId\": {\n          \"__rl\": true,\n          \"mode\": \"url\",\n          \"value\": \"=https://drive.google.com/file/d/1wm4anhC6ygXl4ZJAjJryWfEXTG-VeH8s/view?usp=sharing\"\n        },\n        \"options\": {},\n        \"operation\": \"download\"\n      },\n      \"typeVersion\": 3\n    },\n    {\n      \"id\": \"31218124-74e6-4117-bd76-125545aaf969\",\n      \"name\": \"Get Past Ideas\",\n      \"type\": \"n8n-nodes-base.googleSheets\",\n      \"position\": [\n        740,\n        200\n      ],\n      \"parameters\": {\n        \"options\": {},\n        \"sheetName\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"gid=0\",\n          \"cachedResultUrl\": \"https://docs.google.com/spreadsheets/d/1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs/edit#gid=0\",\n          \"cachedResultName\": \"Posts\"\n        },\n        \"documentId\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs\",\n          \"cachedResultUrl\": \"https://docs.google.com/spreadsheets/d/1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs/edit?usp=drivesdk\",\n          \"cachedResultName\": \"AI Posts Content Machine\"\n        }\n      },\n      \"typeVersion\": 4.5,\n      \"alwaysOutputData\": true\n    },\n    {\n      \"id\": \"b4776d32-d742-42d8-8454-048ccadc8ecd\",\n      \"name\": \"Save Image\",\n      \"type\": \"n8n-nodes-base.googleDrive\",\n      \"position\": [\n        2180,\n        280\n      ],\n      \"parameters\": {\n        \"name\": \"=...\",\n        \"driveId\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"My Drive\"\n        },\n        \"options\": {},\n        \"folderId\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"1PZW0Hef8yKwKtBZuRxZAMkakzdyyP0iZ\",\n          \"cachedResultUrl\": \"https://drive.google.com/drive/folders/1PZW0Hef8yKwKtBZuRxZAMkakzdyyP0iZ\",\n          \"cachedResultName\": \"AI Posts Content Machine\"\n        }\n      },\n      \"typeVersion\": 3\n    },\n    {\n      \"id\": \"c6a71846-4538-4204-9ddc-f5c0fb18ac1a\",\n      \"name\": \"Save Post\",\n      \"type\": \"n8n-nodes-base.googleSheets\",\n      \"position\": [\n        2380,\n        280\n      ],\n      \"parameters\": {\n        \"columns\": {\n          \"value\": {\n            \"idea\": \"=...\",\n            \"name\": \"=...\",\n            \"text\": \"=...\",\n            \"image\": \"=...\",\n            \"status\": \"review\"\n          },\n          \"schema\": [\n            {\n              \"id\": \"name\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"required\": false,\n              \"displayName\": \"name\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            },\n            {\n              \"id\": \"idea\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"required\": false,\n              \"displayName\": \"idea\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            },\n            {\n              \"id\": \"text\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"required\": false,\n              \"displayName\": \"text\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            },\n            {\n              \"id\": \"image\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"required\": false,\n              \"displayName\": \"image\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            },\n            {\n              \"id\": \"status\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"required\": false,\n              \"displayName\": \"status\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            }\n          ],\n          \"mappingMode\": \"defineBelow\",\n          \"matchingColumns\": [],\n          \"attemptToConvertTypes\": false,\n          \"convertFieldsToString\": false\n        },\n        \"options\": {},\n        \"operation\": \"append\",\n        \"sheetName\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"gid=0\",\n          \"cachedResultUrl\": \"https://docs.google.com/spreadsheets/d/1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs/edit#gid=0\",\n          \"cachedResultName\": \"Posts\"\n        },\n        \"documentId\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs\",\n          \"cachedResultUrl\": \"https://docs.google.com/spreadsheets/d/1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs/edit?usp=drivesdk\",\n          \"cachedResultName\": \"AI Posts Content Machine\"\n        }\n      },\n      \"typeVersion\": 4.5\n    },\n    {\n      \"id\": \"7b8e2c00-2c14-4bb7-acee-0181990e9434\",\n      \"name\": \"Schedule 2\",\n      \"type\": \"n8n-nodes-base.scheduleTrigger\",\n      \"position\": [\n        560,\n        700\n      ],\n      \"parameters\": {\n        \"rule\": {\n          \"interval\": [\n            {\n              \"triggerAtHour\": 16\n            }\n          ]\n        }\n      },\n      \"typeVersion\": 1.2\n    },\n    {\n      \"id\": \"66c0ae82-6ba3-4fa0-8033-3726796cdc0a\",\n      \"name\": \"Get Ready Posts\",\n      \"type\": \"n8n-nodes-base.googleSheets\",\n      \"position\": [\n        740,\n        700\n      ],\n      \"parameters\": {\n        \"options\": {},\n        \"filtersUI\": {\n          \"values\": [\n            {\n              \"lookupValue\": \"ready\",\n              \"lookupColumn\": \"status\"\n            }\n          ]\n        },\n        \"sheetName\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"gid=0\",\n          \"cachedResultUrl\": \"https://docs.google.com/spreadsheets/d/1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs/edit#gid=0\",\n          \"cachedResultName\": \"Posts\"\n        },\n        \"documentId\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs\",\n          \"cachedResultUrl\": \"https://docs.google.com/spreadsheets/d/1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs/edit?usp=drivesdk\",\n          \"cachedResultName\": \"AI Posts Content Machine\"\n        }\n      },\n      \"typeVersion\": 4.5\n    },\n    {\n      \"id\": \"7ee9c81f-00ca-4f89-95bb-61d224b06a2e\",\n      \"name\": \"Download Image\",\n      \"type\": \"n8n-nodes-base.googleDrive\",\n      \"position\": [\n        1120,\n        700\n      ],\n      \"parameters\": {\n        \"fileId\": {\n          \"__rl\": true,\n          \"mode\": \"url\",\n          \"value\": \"=...\"\n        },\n        \"options\": {},\n        \"operation\": \"download\"\n      },\n      \"typeVersion\": 3\n    },\n    {\n      \"id\": \"94fbbd95-fe52-4eda-ac78-2201ff72fe50\",\n      \"name\": \"Publish Post\",\n      \"type\": \"n8n-nodes-base.linkedIn\",\n      \"position\": [\n        1320,\n        700\n      ],\n      \"parameters\": {\n        \"text\": \"=...\",\n        \"person\": \"-NknGiXASA\",\n        \"additionalFields\": {},\n        \"shareMediaCategory\": \"IMAGE\"\n      },\n      \"typeVersion\": 1\n    },\n    {\n      \"id\": \"0893a7f2-490b-49f1-96cb-56090cb59c10\",\n      \"name\": \"Update Status\",\n      \"type\": \"n8n-nodes-base.googleSheets\",\n      \"position\": [\n        1520,\n        700\n      ],\n      \"parameters\": {\n        \"columns\": {\n          \"value\": {\n            \"name\": \"=...\",\n            \"status\": \"posted\"\n          },\n          \"schema\": [\n            {\n              \"id\": \"name\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"removed\": false,\n              \"required\": false,\n              \"displayName\": \"name\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            },\n            {\n              \"id\": \"idea\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"removed\": true,\n              \"required\": false,\n              \"displayName\": \"idea\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            },\n            {\n              \"id\": \"text\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"removed\": true,\n              \"required\": false,\n              \"displayName\": \"text\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            },\n            {\n              \"id\": \"image\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"removed\": true,\n              \"required\": false,\n              \"displayName\": \"image\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            },\n            {\n              \"id\": \"status\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"required\": false,\n              \"displayName\": \"status\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            },\n            {\n              \"id\": \"row_number\",\n              \"type\": \"string\",\n              \"display\": true,\n              \"removed\": true,\n              \"readOnly\": true,\n              \"required\": false,\n              \"displayName\": \"row_number\",\n              \"defaultMatch\": false,\n              \"canBeUsedToMatch\": true\n            }\n          ],\n          \"mappingMode\": \"defineBelow\",\n          \"matchingColumns\": [\n            \"name\"\n          ],\n          \"attemptToConvertTypes\": false,\n          \"convertFieldsToString\": false\n        },\n        \"options\": {},\n        \"operation\": \"update\",\n        \"sheetName\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"gid=0\",\n          \"cachedResultUrl\": \"https://docs.google.com/spreadsheets/d/1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs/edit#gid=0\",\n          \"cachedResultName\": \"Posts\"\n        },\n        \"documentId\": {\n          \"__rl\": true,\n          \"mode\": \"list\",\n          \"value\": \"1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs\",\n          \"cachedResultUrl\": \"https://docs.google.com/spreadsheets/d/1-F3ZioIs3oWOKMyDPMuquaH-qiuaZs6qdZXP-yNeRbs/edit?usp=drivesdk\",\n          \"cachedResultName\": \"AI Posts Content Machine\"\n        }\n      },\n      \"typeVersion\": 4.5\n    }\n  ],\n  \"pinData\": {},\n  \"connections\": {\n    \"Pick One\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Download Image\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Schedule\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Get Past Ideas\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Join Ideas\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Idea Generator\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Save Image\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Save Post\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Schedule 2\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Get Ready Posts\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Image Style\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"OpenAI Image\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"OpenAI Image\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Convert to File\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Publish Post\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Update Status\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Download Image\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Publish Post\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Get Past Ideas\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Join Ideas\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Idea Generator\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Image Style\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Convert to File\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Save Image\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Get Ready Posts\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Pick One\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Perplexity Research\": {\n      \"ai_tool\": [\n        [\n          {\n            \"node\": \"Idea Generator\",\n            \"type\": \"ai_tool\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Anthropic Chat Model\": {\n      \"ai_languageModel\": [\n        [\n          {\n            \"node\": \"Idea Generator\",\n            \"type\": \"ai_languageModel\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Structured Output Parser\": {\n      \"ai_outputParser\": [\n        [\n          {\n            \"node\": \"Idea Generator\",\n            \"type\": \"ai_outputParser\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Wait for Container Processing\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Publish Post to Instagram\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Prepare Data for Instagram API\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Create Instagram Media Container\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    },\n    \"Create Instagram Media Container\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"Wait for Container Processing\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ]\n      ]\n    }\n  }\n}\n\n\n## example 2: \n### input: GPT 4o Agent with SerpAPI Websearch and Memory\n### output: {\n  \"id\": \"ai-agent-gpt4o-serpapi-manual\",\n  \"name\": \"GPT-4o Agent with SerpAPI & Memory (Manual Trigger)\",\n  \"nodes\": [\n  {\n  \"id\": \"dba53fd3-6bf0-46c9-9659-286f643fd6d1\",\n  \"name\": \"Manual Trigger\",\n  \"type\": \"n8n-nodes-base.manualTrigger\",\n  \"position\": [\n  -420,\n  -40\n  ],\n  \"parameters\": {},\n  \"typeVersion\": 1\n  },\n  {\n  \"id\": \"dd16c4ff-c7d4-45fc-b75a-29bdb6dcc0c2\",\n  \"name\": \"Window Buffer Memory\",\n  \"type\": \"@n8n/n8n-nodes-langchain.memoryBufferWindow\",\n  \"position\": [\n  -140,\n  -40\n  ],\n  \"parameters\": {},\n  \"typeVersion\": 1.3\n  },\n  {\n  \"id\": \"32a1cc05-dab8-4be1-bd6a-8396fbe0df0e\",\n  \"name\": \"GPT-4o Chat Model\",\n  \"type\": \"@n8n/n8n-nodes-langchain.lmChatOpenAi\",\n  \"position\": [\n  -140,\n  -220\n  ],\n  \"parameters\": {\n  \"model\": {\n  \"__rl\": true,\n  \"mode\": \"list\",\n  \"value\": \"gpt-4o\",\n  \"cachedResultName\": \"gpt-4o\"\n  },\n  \"options\": {}\n  },\n  \"credentials\": {\n  \"openAiApi\": {\n  \"id\": \"<OPENROUTER_CREDENTIAL_ID>\",\n  \"name\": \"OpenRouter API Key\"\n  }\n  },\n  \"typeVersion\": 1.2\n  },\n  {\n  \"id\": \"ea7379d9-b6dd-49ff-ac01-2d9c608f7c11\",\n  \"name\": \"SerpAPI\",\n  \"type\": \"@n8n/n8n-nodes-langchain.toolSerpApi\",\n  \"position\": [\n  -140,\n  140\n  ],\n  \"parameters\": {\n  \"options\": {}\n  },\n  \"credentials\": {\n  \"serpApi\": {\n  \"id\": \"<SERPAPI_CREDENTIAL_ID>\",\n  \"name\": \"SerpAPI Key\"\n  }\n  },\n  \"typeVersion\": 1\n  },\n  {\n  \"id\": \"10a3f41d-4f1a-4efa-92b3-7adb3f98f604\",\n  \"name\": \"AI Agent\",\n  \"type\": \"@n8n/n8n-nodes-langchain.agent\",\n  \"position\": [\n  160,\n  -40\n  ],\n  \"parameters\": {\n  \"text\": \"=Respond to the user’s request given in the trigger item.\",\n  \"options\": {\n  \"systemMessage\": \"You are an AI assistant that can perform web searches with SerpAPI when helpful.\"\n  },\n  \"promptType\": \"define\"\n  },\n  \"typeVersion\": 1.7\n  },\n  {\n  \"id\": \"f8b0c3ae-8423-4db9-a287-3e3c640ef0bb\",\n  \"name\": \"Set Response\",\n  \"type\": \"n8n-nodes-base.set\",\n  \"position\": [\n  400,\n  -40\n  ],\n  \"parameters\": {\n  \"assignments\": {\n  \"assignments\": [\n  {\n  \"id\": \"acb7e4d0-f718-4eae-8f50-0ca15c5c68e2\",\n  \"name\": \"answer\",\n  \"type\": \"string\",\n  \"value\": \"={{ $json.output }}\"\n  }\n  ]\n  },\n  \"options\": {}\n  },\n  \"typeVersion\": 3.4\n  }\n  ],\n  \"connections\": {\n  \"Manual Trigger\": {\n  \"main\": [\n  [\n  {\n  \"node\": \"Window Buffer Memory\",\n  \"type\": \"main\",\n  \"index\": 0\n  }\n  ]\n  ]\n  },\n  \"Window Buffer Memory\": {\n  \"main\": [\n  [\n  {\n  \"node\": \"AI Agent\",\n  \"type\": \"main\",\n  \"index\": 0\n  }\n  ]\n  ],\n  \"ai_memory\": [\n  [\n  {\n  \"node\": \"AI Agent\",\n  \"type\": \"ai_memory\",\n  \"index\": 0\n  }\n  ]\n  ]\n  },\n  \"GPT-4o Chat Model\": {\n  \"ai_languageModel\": [\n  [\n  {\n  \"node\": \"AI Agent\",\n  \"type\": \"ai_languageModel\",\n  \"index\": 0\n  }\n  ]\n  ]\n  },\n  \"SerpAPI\": {\n  \"ai_tool\": [\n  [\n  {\n  \"node\": \"AI Agent\",\n  \"type\": \"ai_tool\",\n  \"index\": 0\n  }\n  ]\n  ]\n  },\n  \"AI Agent\": {\n  \"main\": [\n  [\n  {\n  \"node\": \"Set Response\",\n  \"type\": \"main\",\n  \"index\": 0\n  }\n  ]\n  ]\n  }\n  },\n  \"active\": true,\n  \"settings\": {\n  \"executionOrder\": \"v1\"\n  }\n  }\n\n\n\n# User request: \n"}},"retryOnFail":true,"typeVersion":1.9,"alwaysOutputData":false},{"id":"e36992ff-fa9c-469c-a669-267bcdccae99","name":"Embeddings OpenAI2","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[-2120,-380],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"1BZb0tEHsbNtfnre","name":"OpenAi account"}},"typeVersion":1.2},{"id":"5e709878-fc9d-4ed3-bfbb-b019f9c287db","name":"Default Data Loader1","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[-2000,-380],"parameters":{"options":{}},"typeVersion":1},{"id":"f70e1fe1-618f-45c8-8379-f4742effb93b","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-2320,-1060],"parameters":{},"typeVersion":1},{"id":"b34a7b23-f5b9-4046-9c92-a663698c0e92","name":"Extract","type":"n8n-nodes-base.httpRequest","position":[-1880,-1060],"parameters":{"url":"={{ $json.URL }}","options":{}},"typeVersion":4.2},{"id":"ea2a97ef-f2bb-4934-a040-7fa96b918101","name":"If","type":"n8n-nodes-base.if","onError":"continueErrorOutput","position":[-1240,-1060],"parameters":{"options":{}},"typeVersion":2.2},{"id":"a34dea8f-fb4f-4c94-834d-eb5948cc7286","name":"Get Results","type":"n8n-nodes-base.httpRequest","position":[-1440,-1060],"parameters":{"options":{}},"typeVersion":4.2},{"id":"63cd8437-92c9-4a33-aabf-3238b7b4a919","name":"30 Secs","type":"n8n-nodes-base.wait","position":[-1660,-1060],"webhookId":"e4866198-b806-4746-b57f-97333c497dbf","parameters":{},"typeVersion":1.1},{"id":"c6830132-8d74-4209-9d41-6c42c1fb7e66","name":"10 Seconds","type":"n8n-nodes-base.wait","position":[-1120,-1260],"webhookId":"6cc8c637-bafb-4d64-9cd4-8ae2a9f5b7ca","parameters":{},"typeVersion":1.1},{"id":"95161389-9ea0-484b-abdf-82a8a0479b9a","name":"SerpAPI","type":"@n8n/n8n-nodes-langchain.toolSerpApi","position":[-1980,580],"parameters":{"options":{}},"credentials":{"serpApi":{"id":"Je4LoeQ61nFMK2Fl","name":"SerpAPI account"}},"typeVersion":1},{"id":"da8d5a8a-c641-453f-a7bb-817099e8592f","name":"Pinecone Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStorePinecone","position":[-1860,580],"parameters":{"mode":"retrieve-as-tool","options":{},"toolName":"n8n_documentation","pineconeIndex":{"__rl":true,"mode":"list","value":"agentbuilder","cachedResultName":"agentbuilder"},"toolDescription":"This vectorstore contains some of n8n's technical documentations."},"credentials":{"pineconeApi":{"id":"Lf0fQva4BsvfbRrC","name":"PineconeApi account"}},"typeVersion":1.1},{"id":"0838fd0e-8e1b-4c37-8c31-8ab9306fff89","name":"Train Pinecone Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStorePinecone","position":[-2120,-540],"parameters":{"mode":"insert","options":{},"pineconeIndex":{"__rl":true,"mode":"list","value":"agentbuilder","cachedResultName":"agentbuilder"}},"credentials":{"pineconeApi":{"id":"Lf0fQva4BsvfbRrC","name":"PineconeApi account"}},"typeVersion":1.1},{"id":"b4bca1b1-80bc-42fa-b434-00eabd926aff","name":"OpenRouter Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[-2100,580],"parameters":{"options":{}},"credentials":{"openRouterApi":{"id":"6NJ9tdhq29wdtm6s","name":"OpenRouter account"}},"typeVersion":1},{"id":"e9f693e5-4733-4987-a7a8-7f6b7823b221","name":"Embeddings OpenAI","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[-1840,720],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"1BZb0tEHsbNtfnre","name":"OpenAi account"}},"typeVersion":1.2},{"id":"ebe6227a-4f12-44d0-ae8c-516e89e31f9f","name":"OpenAI","type":"@n8n/n8n-nodes-langchain.openAi","position":[-1520,240],"parameters":{"modelId":{"__rl":true,"mode":"list","value":"o4-mini-2025-04-16","cachedResultName":"O4-MINI-2025-04-16"},"options":{},"messages":{"values":[{"role":"system","content":"Transform the input into valid n8n template JSON format. make sure all nodes are correctly set up and CONNECTED!\n\nmake especially sure the AI agent(s) are correctly set up and connected. here is an example:\n\n{\n  \"id\": \"ai-agent-gpt4o-serpapi-manual\",\n  \"name\": \"GPT-4o Agent with SerpAPI & Memory (Manual Trigger)\",\n  \"nodes\": [\n  {\n  \"id\": \"dba53fd3-6bf0-46c9-9659-286f643fd6d1\",\n  \"name\": \"Manual Trigger\",\n  \"type\": \"n8n-nodes-base.manualTrigger\",\n  \"position\": [\n  -420,\n  -40\n  ],\n  \"parameters\": {},\n  \"typeVersion\": 1\n  },\n  {\n  \"id\": \"dd16c4ff-c7d4-45fc-b75a-29bdb6dcc0c2\",\n  \"name\": \"Window Buffer Memory\",\n  \"type\": \"@n8n/n8n-nodes-langchain.memoryBufferWindow\",\n  \"position\": [\n  -140,\n  -40\n  ],\n  \"parameters\": {},\n  \"typeVersion\": 1.3\n  },\n  {\n  \"id\": \"32a1cc05-dab8-4be1-bd6a-8396fbe0df0e\",\n  \"name\": \"GPT-4o Chat Model\",\n  \"type\": \"@n8n/n8n-nodes-langchain.lmChatOpenAi\",\n  \"position\": [\n  -140,\n  -220\n  ],\n  \"parameters\": {\n  \"model\": {\n  \"__rl\": true,\n  \"mode\": \"list\",\n  \"value\": \"gpt-4o\",\n  \"cachedResultName\": \"gpt-4o\"\n  },\n  \"options\": {}\n  },\n  \"credentials\": {\n  \"openAiApi\": {\n  \"id\": \"<OPENROUTER_CREDENTIAL_ID>\",\n  \"name\": \"OpenRouter API Key\"\n  }\n  },\n  \"typeVersion\": 1.2\n  },\n  {\n  \"id\": \"ea7379d9-b6dd-49ff-ac01-2d9c608f7c11\",\n  \"name\": \"SerpAPI\",\n  \"type\": \"@n8n/n8n-nodes-langchain.toolSerpApi\",\n  \"position\": [\n  -140,\n  140\n  ],\n  \"parameters\": {\n  \"options\": {}\n  },\n  \"credentials\": {\n  \"serpApi\": {\n  \"id\": \"<SERPAPI_CREDENTIAL_ID>\",\n  \"name\": \"SerpAPI Key\"\n  }\n  },\n  \"typeVersion\": 1\n  },\n  {\n  \"id\": \"10a3f41d-4f1a-4efa-92b3-7adb3f98f604\",\n  \"name\": \"AI Agent\",\n  \"type\": \"@n8n/n8n-nodes-langchain.agent\",\n  \"position\": [\n  160,\n  -40\n  ],\n  \"parameters\": {\n  \"text\": \"=Respond to the user’s request given in the trigger item.\",\n  \"options\": {\n  \"systemMessage\": \"You are an AI assistant that can perform web searches with SerpAPI when helpful.\"\n  },\n  \"promptType\": \"define\"\n  },\n  \"typeVersion\": 1.7\n  },\n  {\n  \"id\": \"f8b0c3ae-8423-4db9-a287-3e3c640ef0bb\",\n  \"name\": \"Set Response\",\n  \"type\": \"n8n-nodes-base.set\",\n  \"position\": [\n  400,\n  -40\n  ],\n  \"parameters\": {\n  \"assignments\": {\n  \"assignments\": [\n  {\n  \"id\": \"acb7e4d0-f718-4eae-8f50-0ca15c5c68e2\",\n  \"name\": \"answer\",\n  \"type\": \"string\",\n  \"value\": \"={{ $json.output }}\"\n  }\n  ]\n  },\n  \"options\": {}\n  },\n  \"typeVersion\": 3.4\n  }\n  ],\n  \"connections\": {\n  \"Manual Trigger\": {\n  \"main\": [\n  [\n  {\n  \"node\": \"Window Buffer Memory\",\n  \"type\": \"main\",\n  \"index\": 0\n  }\n  ]\n  ]\n  },\n  \"Window Buffer Memory\": {\n  \"main\": [\n  [\n  {\n  \"node\": \"AI Agent\",\n  \"type\": \"main\",\n  \"index\": 0\n  }\n  ]\n  ],\n  \"ai_memory\": [\n  [\n  {\n  \"node\": \"AI Agent\",\n  \"type\": \"ai_memory\",\n  \"index\": 0\n  }\n  ]\n  ]\n  },\n  \"GPT-4o Chat Model\": {\n  \"ai_languageModel\": [\n  [\n  {\n  \"node\": \"AI Agent\",\n  \"type\": \"ai_languageModel\",\n  \"index\": 0\n  }\n  ]\n  ]\n  },\n  \"SerpAPI\": {\n  \"ai_tool\": [\n  [\n  {\n  \"node\": \"AI Agent\",\n  \"type\": \"ai_tool\",\n  \"index\": 0\n  }\n  ]\n  ]\n  },\n  \"AI Agent\": {\n  \"main\": [\n  [\n  {\n  \"node\": \"Set Response\",\n  \"type\": \"main\",\n  \"index\": 0\n  }\n  ]\n  ]\n  }\n  },\n  \"active\": true,\n  \"settings\": {\n  \"executionOrder\": \"v1\"\n  }\n  }\n"},{"content":"={{ $json.output }}"}]}},"credentials":{"openAiApi":{"id":"1BZb0tEHsbNtfnre","name":"OpenAi account"}},"typeVersion":1.8},{"id":"afcb27aa-257f-4c9a-8cb2-d54f23123443","name":"Code","type":"n8n-nodes-base.code","position":[-1160,240],"parameters":{"jsCode":"const items = $input.all();\nconst extractedJsons = items.map((item) => {\n  const content = item?.json?.message?.content;\n  const jsonStart = content.indexOf(\"```json\") + 7;\n  const jsonEnd = content.indexOf(\"```\", jsonStart);\n  const jsonContent = content.slice(jsonStart, jsonEnd);\n  try {\n    const parsedJson = JSON.parse(jsonContent);\n    return { extractedJson: parsedJson };\n  } catch (error) {\n    console.log(\"Failed to parse JSON:\", error);\n    return { extractedJson: null };\n  }\n});\nreturn extractedJsons;\n"},"typeVersion":2},{"id":"8b7a4793-141f-499d-b52d-a397be147d12","name":"Web Crawler Logic","type":"n8n-nodes-base.stickyNote","position":[-3940,-1200],"parameters":{"color":6,"width":780,"height":340,"content":"🕸️ **Web Crawler (Sub-process #1)**\n\n*Triggered manually.*\n1. **Edit Fields → Extract** – sends a Firecrawl request to scrape docs.n8n.io.\n2. **Wait (30 s) → Get Results** – polls Firecrawl until scraping is finished.\n3. **If / Wait (10 s)** – simple retry logic.\n\n**Output:** Raw markdown/HTML that feeds the *RAG Trainer*.\n\n_No credentials needed here apart from the Firecrawl API key (see separate note)._"},"typeVersion":1},{"id":"ac612a9e-d148-4b24-a98a-c672de2177e8","name":"RAG Trainer Logic","type":"n8n-nodes-base.stickyNote","position":[-3940,-520],"parameters":{"color":6,"width":780,"height":320,"content":"🧠 **RAG Trainer (Sub-process #2)**\n\n1. **Default Data Loader → Recursive Splitter** – loads the crawled pages and breaks them into ~1-2 k-token chunks.\n2. **Embeddings (OpenAI) → Train Pinecone** – turns chunks into vectors and upserts them into Pinecone.\n\nRun this sub-process once (or on a schedule) whenever you update your docs.\n\n> The resulting Pinecone index will later be queried by the agent to answer user questions with n8n documentation context."},"typeVersion":1},{"id":"b25bafe7-c25c-4b79-9e1b-0e9610f6f815","name":"Agent Builder Logic","type":"n8n-nodes-base.stickyNote","position":[-3940,240],"parameters":{"color":6,"width":820,"height":520,"content":"🤖 **AI Agent Builder (Sub-process #3)**\n\n1. **Chat Trigger** – waits for a user request (e.g. in GPT-style chat).\n2. **AI Agent (LangChain)** – orchestrates:\n   • **OpenRouter GPT-4o** (LLM)\n   • **SerpAPI** (web-search tool)\n   • **Pinecone Vector Store** (RAG)\n   • **Structured Output Parser** to guarantee valid JSON.\n3. **OpenAI (validator)** – double-checks the JSON and pretty-prints errors.\n4. **Code → Convert to File** – extracts the final template and returns it as a downloadable file.\n\nResult: a fully wired n8n workflow template matching the user’s prompt."},"typeVersion":1},{"id":"4d5e930d-1d9d-479d-a9fd-c57b8824b57c","name":"Configure Firecrawl","type":"n8n-nodes-base.stickyNote","position":[-3140,-1200],"parameters":{"color":4,"width":660,"height":340,"content":"⚙️ **Firecrawl API**\nNodes: **HTTP Request – “Extract”** & **“Get Results”**\n1. Create a *Generic Credential (Header Auth)*.\n2. Header name: `Authorization`\n3. Value: `Bearer YOUR_TOKEN_HERE`.\n4. Select the credential in both HTTP Request nodes."},"typeVersion":1},{"id":"2c058520-9532-4108-a514-9db857250cd0","name":"Configure Pinecone","type":"n8n-nodes-base.stickyNote","position":[-3140,-520],"parameters":{"color":4,"width":660,"height":140,"content":"⚙️ **Pinecone Vector Store**\nNodes: **“Train Pinecone Vector Store”** & **“Pinecone Vector Store”**\n• Add a *Pinecone API* credential with **Environment**, **API Key**, and **Index Name**.\n• Make sure both nodes point to the same index."},"typeVersion":1},{"id":"b8b327e6-069f-4dff-a5ce-6fed6e9a117d","name":"Configure OpenAI API","type":"n8n-nodes-base.stickyNote","position":[-3140,-360],"parameters":{"color":4,"width":660,"content":"⚙️ **OpenAI / Azure OpenAI**\nNodes: **“Embeddings OpenAI”**, **“Embeddings OpenAI 2”**, **“OpenAI (validator)”**\n1. Create an *OpenAI API* credential (or Azure equivalent).\n2. Select the credential in all three nodes.\n3. Ensure the embedding model (e.g. `text-embedding-3-small`) is available in your account."},"typeVersion":1},{"id":"42784df1-903f-43d5-92ed-c25cf2df5323","name":"Configure OpenRouter GPT-4o","type":"n8n-nodes-base.stickyNote","position":[-3100,240],"parameters":{"color":4,"width":620,"height":100,"content":"⚙️ **OpenRouter API**\nNode: **“OpenRouter Chat Model”**\n• Create an *OpenRouter API Key* credential and select it here.\n• The example uses model `o4-mini-2025-04-16`; adjust if your plan differs."},"typeVersion":1},{"id":"debda5ff-2309-410a-a8f6-7e6fd011fdc1","name":"Configure SerpAPI","type":"n8n-nodes-base.stickyNote","position":[-3100,360],"parameters":{"color":4,"width":620,"height":100,"content":"⚙️ **SerpAPI Key**\nNode: **“SerpAPI”**\n1. Sign up at serpapi.com and copy your key.\n2. Add a *SerpAPI* credential and select it in the node."},"typeVersion":1},{"id":"f2d27faa-06f4-42bf-882f-3ce35ad6f876","name":"Configure Pinecone1","type":"n8n-nodes-base.stickyNote","position":[-3100,480],"parameters":{"color":4,"width":620,"height":100,"content":"⚙️ **Pinecone Vector Store**\nNodes: **“Train Pinecone Vector Store”** & **“Pinecone Vector Store”**\n• Add a *Pinecone API* credential with **Environment**, **API Key**, and **Index Name**.\n• Make sure both nodes point to the same index."},"typeVersion":1},{"id":"3b78511a-b49a-46cf-b3ca-6dba4a6d68cf","name":"Configure OpenAI API1","type":"n8n-nodes-base.stickyNote","position":[-3100,600],"parameters":{"color":4,"width":620,"content":"⚙️ **OpenAI / Azure OpenAI**\nNodes: **“Embeddings OpenAI”**, **“Embeddings OpenAI 2”**, **“OpenAI (validator)”**\n1. Create an *OpenAI API* credential (or Azure equivalent).\n2. Select the credential in all three nodes.\n3. Ensure the embedding model (e.g. `text-embedding-3-small`) is available in your account."},"typeVersion":1},{"id":"a802de97-238c-4f7f-9024-43d3fb14f7a8","name":"Extract JSON","type":"n8n-nodes-base.set","position":[-920,240],"parameters":{"mode":"raw","options":{},"jsonOutput":"=\n {{ $json.extractedJson }}"},"typeVersion":3.4},{"id":"d67d0970-0f58-41f4-8d48-077247eb4b0a","name":"Set Preferences","type":"n8n-nodes-base.set","position":[-2320,80],"parameters":{"options":{},"assignments":{"assignments":[{"id":"6905b43a-c181-4c14-a746-c4d82325cccf","name":"vector database","type":"string","value":"Pinecone"},{"id":"cfe18b2f-051d-492d-bb63-dd91076bce68","name":"chat model","type":"string","value":"Open Router"},{"id":"bb2d75ad-9544-4d48-b9d1-ddc2e5a124c1","name":"embedding","type":"string","value":"text-embedding-3-large"},{"id":"1a763e6b-22df-477f-941b-4933231d636a","name":"web search tool","type":"string","value":"SerpAPI"}]}},"typeVersion":3.4},{"id":"392f160f-5ffd-4799-a63d-adc240b7f26a","name":"Convert to JSON File","type":"n8n-nodes-base.convertToFile","position":[-720,240],"parameters":{"mode":"each","options":{"format":true,"encoding":"utf8","fileName":""},"operation":"toJson","binaryPropertyName":"="},"typeVersion":1.1},{"id":"efc08c98-cb77-45f0-b824-de2a22dee2fc","name":"Convert to File","type":"n8n-nodes-base.convertToFile","position":[-2320,-540],"parameters":{"options":{}},"typeVersion":1.1},{"id":"9ff243d3-1871-4634-b5a6-dd9a745a7a84","name":"Set URL","type":"n8n-nodes-base.set","position":[-2100,-1060],"parameters":{"options":{},"assignments":{"assignments":[{"id":"60871e95-afba-4ff9-ba56-315ae39cd6f9","name":"URL","type":"string","value":"https://api.firecrawl.dev/v1/crawl/6cd9b912-bf11-498d-8f31-197aaf8efa1c"}]}},"typeVersion":3.4},{"id":"03e4cd15-b458-4601-a9d4-c365a27e846e","name":"Recursive Character Text Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","position":[-1980,-240],"parameters":{"options":{}},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"c3f351d9-a5ae-4a18-9d2d-fc28242e81d3","connections":{"If":{"main":[[{"node":"10 Seconds","type":"main","index":0}],[{"node":"Convert to File","type":"main","index":0}]]},"Code":{"main":[[{"node":"Extract JSON","type":"main","index":0}]]},"OpenAI":{"main":[[{"node":"Code","type":"main","index":0}]]},"30 Secs":{"main":[[{"node":"Get Results","type":"main","index":0}]]},"Extract":{"main":[[{"node":"30 Secs","type":"main","index":0}]]},"SerpAPI":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"Set URL":{"main":[[{"node":"Extract","type":"main","index":0}]]},"AI Agent":{"main":[[{"node":"OpenAI","type":"main","index":0}]]},"10 Seconds":{"main":[[{"node":"Get Results","type":"main","index":0}]]},"Get Results":{"main":[[{"node":"If","type":"main","index":0}]]},"Extract JSON":{"main":[[{"node":"Convert to JSON File","type":"main","index":0}]]},"Convert to File":{"main":[[{"node":"Train Pinecone Vector Store","type":"main","index":0}]]},"Set Preferences":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Embeddings OpenAI":{"ai_embedding":[[{"node":"Pinecone Vector Store","type":"ai_embedding","index":0}]]},"Embeddings OpenAI2":{"ai_embedding":[[{"node":"Train Pinecone Vector Store","type":"ai_embedding","index":0}]]},"Convert to JSON File":{"main":[[]]},"Default Data Loader1":{"ai_document":[[{"node":"Train Pinecone Vector Store","type":"ai_document","index":0}]]},"OpenRouter Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Pinecone Vector Store":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"When chat message received":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Recursive Character Text Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader1","type":"ai_textSplitter","index":0}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"Set URL","type":"main","index":0}]]}}}


name: Generate AI Avatar Videos with HeyGen and Google Sheets Integration
author_name: Sagar
author_username: sagarmasand9
nodes_used: ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest"]
categories: []
created_at: 2025-06-18T16:47:19.959Z
updated_at: 2025-06-18T16:47:19.959Z
url: https://n8n.io/workflows/5027
scraped_at: 2025-07-06 21:16:30
description:
  This template streamlines your AI Avatar Video Automation workflow by connecting Google sheets for Voice Text & AI Avatar Video Link storage, using HTTP Nodes for connecting Heygen API & AI Avatar/Voice Id for automated Video generation.

  Pre-requisites
  Before setting up this workflow, ensure you have:

  A Google account with access to Google Sheets

  A Heygen Account with API access in account's settings.



  n8n.io account with workflow access

  Setup Instructions

  Configure Data Source
  Create a Google Sheet with the following columns: Script/Voice Text & Final AI Avatar Video Link.

  Connect Google Sheet
  Add your Google sheet credentials in the “Google Sheet” node
  Specify the folder path where your columns are stored.

  Configure the node to retrieve files based on filenames from your Google Sheet

  Set Up HTTP Node with Heygen API Credentials

  Configure the node to generate AI Video based on Script/Voice Text.


  Configure HTTP Node 2
  Connect Heygen API Credentials
  Set up the API node to Get the AI Avatar Video Link.

  then finally setup Google sheet node again to get & upload the final AI Avatar video link in the column "the Final AI Avatar Video Link"

  Workflow Automation Setup
  Configure the scheduler node to run at your preferred frequency
  Set up error handling to notify you of any posting failures


  Execution Instructions
  After completing all connections, test the workflow.

  Monitor the execution in the n8n dashboard to ensure proper functioning

  View the “Executions” tab to track successful  and troubleshoot any errors.

  This template saves hours of manual AI Avatar video Creation Process. use this without the daily manual effort.


  Details
  Nodes used in workflow
  Manual Trigger Node
  Google Sheet Node 1
  HTTP Node 1
  HTTP Node 2
  Google Sheets Node 2

workflow_json:
  {"meta":{"instanceId":"de145373c7ed10b34e35f8898916fdf37d53e7782c6f05bbe7b831e31042db96","templateCredsSetupCompleted":true},"nodes":[{"id":"43bde8be-dd80-43d5-93fa-bbed038d1fc0","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-660,80],"parameters":{},"typeVersion":1},{"id":"6530a519-264d-41ef-87db-280c425f481f","name":"Get Video","type":"n8n-nodes-base.httpRequest","position":[440,80],"parameters":{"url":"https://api.heygen.com/v2/avatar/avatar_id/details","options":{},"sendHeaders":true,"authentication":"genericCredentialType","genericAuthType":"httpHeaderAuth","headerParameters":{"parameters":[{"name":"video_id","value":"={{ $json.data.video_id }}"}]}},"credentials":{"httpHeaderAuth":{"id":"hHUxPUb01H0Ij0se","name":"Header Auth account"}},"typeVersion":4.2},{"id":"dcc4ed71-81da-4fe2-a865-cdda8a81ab2d","name":"creating Video","type":"n8n-nodes-base.httpRequest","position":[80,80],"parameters":{"url":"https://api.heygen.com/v2/video/generate","method":"POST","options":{},"jsonBody":"{\n  \"video_inputs\": [\n    {\n      \"character\": {\n        \"type\": \"avatar\",\n        \"avatar_id\": \"84c521ab0e4b4527a33423e1b813ea0c\",\n        \"avatar_style\": \"normal\"\n      },\n      \"voice\": {\n        \"type\": \"text\",\n        \"input_text\": \"hey, this is sagar and it is my avatar\",\n        \"voice_id\": \"2aa0fed15bbf424bb3a4f9c9537ab058\",\n        \"speed\": 1.1\n      }\n    }\n  ],\n  \"dimension\": {\n    \"width\": 1280,\n    \"height\": 720\n  }\n}\n","sendBody":true,"sendHeaders":true,"specifyBody":"json","authentication":"genericCredentialType","genericAuthType":"httpHeaderAuth","headerParameters":{"parameters":[{"name":"accept","value":"application/json"}]}},"credentials":{"httpHeaderAuth":{"id":"hHUxPUb01H0Ij0se","name":"Header Auth account"}},"typeVersion":4.2},{"id":"5c6f7c73-3301-4e62-9cc2-1a4181e03fd4","name":"Google Sheets","type":"n8n-nodes-base.googleSheets","position":[-280,80],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1xqIDGIYCCHlZyfWYMMHBisz4YggRKycygWzBfYaYI08/edit#gid=0","cachedResultName":"New Script Uploaded"},"documentId":{"__rl":true,"mode":"list","value":"1xqIDGIYCCHlZyfWYMMHBisz4YggRKycygWzBfYaYI08","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1xqIDGIYCCHlZyfWYMMHBisz4YggRKycygWzBfYaYI08/edit?usp=drivesdk","cachedResultName":"New Script"}},"credentials":{"googleSheetsOAuth2Api":{"id":"K7LQI1nT7J8NyxSW","name":"Google Sheets account"}},"typeVersion":4.6},{"id":"3f5f9b1d-7854-4814-b0af-8b630032e00f","name":"Google Sheets1","type":"n8n-nodes-base.googleSheets","position":[820,80],"parameters":{"columns":{"value":{"Final Video":"={{ $json.data.video_url }}"},"schema":[{"id":"New Script","type":"string","display":true,"removed":true,"required":false,"displayName":"New Script","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Final Video","type":"string","display":true,"removed":false,"required":false,"displayName":"Final Video","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["New Script"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"append","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1xqIDGIYCCHlZyfWYMMHBisz4YggRKycygWzBfYaYI08/edit#gid=0","cachedResultName":"New Script Uploaded"},"documentId":{"__rl":true,"mode":"list","value":"1xqIDGIYCCHlZyfWYMMHBisz4YggRKycygWzBfYaYI08","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1xqIDGIYCCHlZyfWYMMHBisz4YggRKycygWzBfYaYI08/edit?usp=drivesdk","cachedResultName":"New Script"}},"credentials":{"googleSheetsOAuth2Api":{"id":"K7LQI1nT7J8NyxSW","name":"Google Sheets account"}},"typeVersion":4.6},{"id":"eb08b935-e956-4756-9fd5-b0a196524535","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-720,260],"parameters":{"color":4,"width":255,"height":239,"content":"👈\nSet up Manual Trigger Node.\n\nthis trigger will be activated.\n\nFollow the steps (YouTube video):\nhttps://youtu.be/llm60n03x3c?si=vO4jU6EZms-ZpDvL"},"typeVersion":1},{"id":"b372533b-4de6-48d1-bb53-3a1a364da590","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-720,-100],"parameters":{"color":3,"width":272,"height":140,"content":"### Your AI Avatar Videos Automation Agent with Google Sheets, HTTP Nodes (Easy to set-up in 5 steps only)"},"typeVersion":1},{"id":"f0de3751-d50f-4ca6-b2e4-0e9c38d21557","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[0,260],"parameters":{"color":5,"width":275,"height":359,"content":"👈\nSet up HTTP Node.\n\nMethod : Post\nURL : https://api.heygen.com/v2/video/generate\n\nFor Set up Authentication credentials (open & check the node parameters.)\n\nThis node will create AI Video with your video id and voice id using json code.\n\nFollow the steps (YouTube video):\nhttps://youtu.be/llm60n03x3c?si=vO4jU6EZms-ZpDvL"},"typeVersion":1},{"id":"cab8d398-fe34-4f64-b325-fe6ce1ad8406","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-360,260],"parameters":{"width":275,"height":279,"content":"👈\nSet up Google Sheets Node.\n\nSet up credentials.\n\nCreate a new sheet in Google Sheets (e.g., AI Avatar Script).\n\nCreate 2 columns: Script/voice text, Final Video Link.\n\nFollow the steps (YouTube video):\nhttps://youtu.be/llm60n03x3c?si=vO4jU6EZms-ZpDvL"},"typeVersion":1},{"id":"e046ae61-1f98-4eff-8a6a-d445623520d7","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[360,260],"parameters":{"color":3,"width":275,"height":359,"content":"👈\nSet up HTTP Node.\n\nuse given cURL json code.\n\nMethod : Get\nURL : https://api.heygen.com/v2/avatar/avatar_id/details\n\nFor Set up Authentication credentials (open & check the node parameters.)\n\nput parameter name: video-id  & paste value: video_id from past http node. his node will create AI Video with your video id and voice id using json code.\n\n\nOutput : Your AI Avatar Video Link\nFollow the steps (YouTube video): https://youtu.be/llm60n03x3c?si=vO4jU6EZms-ZpDvL\n"},"typeVersion":1},{"id":"99a5275c-3f72-4a75-94eb-276e620a6545","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[740,260],"parameters":{"width":275,"height":359,"content":"👈\nSet up Google Sheets Node.\n\nSet up credentials.\n\nuse given sheet in Google Sheets (e.g., AI Avatar Script).\n\nconnect the sheet parametr with Your AI Avatar Video Link in the - Final Video Link.\n\nOutput your AI Avatar video link will be uploaded in your google sheet - just open the sheet and download the video.\nFollow the steps (YouTube video):\nhttps://youtu.be/llm60n03x3c?si=vO4jU6EZms-ZpDvL"},"typeVersion":1}],"connections":{"Get Video":{"main":[[{"node":"Google Sheets1","type":"main","index":0}]]},"Google Sheets":{"main":[[{"node":"creating Video","type":"main","index":0}]]},"creating Video":{"main":[[{"node":"Get Video","type":"main","index":0}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"Google Sheets","type":"main","index":0}]]}}}


name: Basic RAG chat
author_name: JustinLee
author_username: justin
categories: []
created_at: 2025-06-18T16:55:03.909Z
updated_at: 2025-06-18T16:55:03.909Z
url: https://n8n.io/workflows/5028
scraped_at: 2025-07-06 21:16:30
description:
  This workflow demonstrates a simple Retrieval-Augmented Generation (RAG) pipeline in n8n, split into two main sections:

  🔹 Part 1: Load Data into Vector Store
  Reads files from disk (or Google Drive).

  Splits content into manageable chunks using a recursive text splitter.

  Generates embeddings using the Cohere Embedding API.

  Stores the vectors into an In-Memory Vector Store (for simplicity; can be replaced with Pinecone, Qdrant, etc.).

  🔹 Part 2: Chat with the Vector Store
  Takes user input from a chat UI or trigger node.

  Embeds the query using the same Cohere embedding model.

  Retrieves similar chunks from the vector store via similarity search.

  Uses Groq-hosted LLM to generate a final answer based on the context.

  🛠️ Technologies Used:
  📦 Cohere Embedding API

  ⚡ Groq LLM for fast inference

  🧠 n8n for orchestrating and visualizing the flow

  🧲 In-Memory Vector Store (for prototyping)

  🧪 Usage:
  Upload or point to your source documents.

  Embed them and populate the vector store.

  Ask questions through the chat trigger node.

  Receive context-aware responses based on retrieved content.

nodes_used:
  ["@n8n/n8n-nodes-langchain.chainRetrievalQa","@n8n/n8n-nodes-langchain.embeddingsCohere","@n8n/n8n-nodes-langchain.retrieverVectorStore","@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","@n8n/n8n-nodes-langchain.vectorStoreInMemory","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.lmChatGroq"]

workflow_json:
  {"nodes":[{"id":"3bc2f88b-c14e-4ee5-84ce-dc16a54aa12b","name":"Recursive Character Text Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","position":[-580,320],"parameters":{"options":{"splitCode":"markdown"},"chunkOverlap":50},"typeVersion":1},{"id":"6bd91468-17db-4918-a232-87fb295a30c2","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1240,-140],"parameters":{"color":7,"width":978.0454109366399,"height":806.6556079800943,"content":"### Load data into database\nFetch file from Google Drive, split it into chunks and insert into Pinecone index"},"typeVersion":1},{"id":"3af4e8e9-0503-470e-b449-4551191fb405","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[0,-160],"parameters":{"color":7,"width":795.4336844920119,"height":849.4411596574598,"content":"### Chat with database\nEmbed the incoming chat message and use it retrieve relevant chunks from the vector store. These are passed to the model to formulate an answer "},"typeVersion":1},{"id":"6f94ec58-4fca-40ee-a1a0-012998093589","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[-580,200],"parameters":{"options":{},"dataType":"binary"},"typeVersion":1},{"id":"3e145342-458d-4222-a707-9fee78e91c4d","name":"Question and Answer Chain","type":"@n8n/n8n-nodes-langchain.chainRetrievalQa","position":[60,-20],"parameters":{"options":{}},"typeVersion":1.2},{"id":"7f2b288a-a002-4cd3-93c0-b2a0e491699c","name":"Vector Store Retriever","type":"@n8n/n8n-nodes-langchain.retrieverVectorStore","position":[240,200],"parameters":{},"typeVersion":1},{"id":"ca930ba7-b45d-47d8-9f36-9db3a25ee77a","name":"When clicking 'Test Workflow' button","type":"n8n-nodes-base.manualTrigger","position":[-1420,-20],"parameters":{},"typeVersion":1},{"id":"90782052-5df2-4f1e-84fc-c47095a81852","name":"When clicking 'Chat' button below","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-140,-20],"webhookId":"066b342b-f2b6-401e-b560-12f5d23b6103","parameters":{},"typeVersion":1},{"id":"712dc9d3-af2d-4436-9315-78f66f748b91","name":"Read/Write Files from Disk","type":"n8n-nodes-base.readWriteFile","position":[-1200,-20],"parameters":{"options":{},"fileSelector":"/tmp/external_data/news.txt"},"typeVersion":1,"alwaysOutputData":true},{"id":"1cd768c1-fcc0-480a-8b33-fbe714788b32","name":"In-Memory Vector Store1","type":"@n8n/n8n-nodes-langchain.vectorStoreInMemory","position":[240,380],"parameters":{},"typeVersion":1},{"id":"2393e667-7e4f-4392-9a7e-b2b4d74d46e8","name":"In-Memory Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStoreInMemory","position":[-980,-20],"parameters":{"mode":"insert","clearStore":true},"typeVersion":1},{"id":"e53f51f3-04f3-46ef-aebd-e0b32b415101","name":"Embeddings Cohere","type":"@n8n/n8n-nodes-langchain.embeddingsCohere","position":[-940,300],"parameters":{"modelName":"embed-multilingual-v3.0"},"credentials":{"cohereApi":{"id":"rXh87ikYuJfDKuCk","name":"CohereApi account"}},"typeVersion":1},{"id":"cf1333b6-b69b-4ff1-bfc3-d3d579585efb","name":"Groq Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGroq","notes":"使用繁體中文","position":[100,220],"parameters":{"model":"llama-3.3-70b-versatile","options":{}},"credentials":{"groqApi":{"id":"dznjL979E8j0L4Zc","name":"Groq account"}},"typeVersion":1},{"id":"e49cfb2e-5eca-4b43-973d-4bf7285b5d94","name":"Embeddings Cohere1","type":"@n8n/n8n-nodes-langchain.embeddingsCohere","position":[340,560],"parameters":{"modelName":"embed-multilingual-v3.0"},"credentials":{"cohereApi":{"id":"rXh87ikYuJfDKuCk","name":"CohereApi account"}},"typeVersion":1}],"connections":{"Groq Chat Model":{"ai_languageModel":[[{"node":"Question and Answer Chain","type":"ai_languageModel","index":0}]]},"Embeddings Cohere":{"ai_embedding":[[{"node":"In-Memory Vector Store","type":"ai_embedding","index":0}]]},"Embeddings Cohere1":{"ai_embedding":[[{"node":"In-Memory Vector Store1","type":"ai_embedding","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"In-Memory Vector Store","type":"ai_document","index":0}]]},"Vector Store Retriever":{"ai_retriever":[[{"node":"Question and Answer Chain","type":"ai_retriever","index":0}]]},"In-Memory Vector Store1":{"ai_vectorStore":[[{"node":"Vector Store Retriever","type":"ai_vectorStore","index":0}]]},"Read/Write Files from Disk":{"main":[[{"node":"In-Memory Vector Store","type":"main","index":0}]]},"Recursive Character Text Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader","type":"ai_textSplitter","index":0}]]},"When clicking 'Chat' button below":{"main":[[{"node":"Question and Answer Chain","type":"main","index":0}]]},"When clicking 'Test Workflow' button":{"main":[[{"node":"Read/Write Files from Disk","type":"main","index":0}]]}}}


name: AI Text-to-Image for Telegram (Gemini + Hugging Face FLUX)
author_name: Malik Hashir
author_username: malikx
categories: []
created_at: 2025-06-18T19:49:11.964Z
updated_at: 2025-06-18T19:49:11.964Z
url: https://n8n.io/workflows/5031
scraped_at: 2025-07-06 21:16:30
description:
  Turn text prompts into stunning AI-generated images—automatically!

  What it does?

  This workflow lets your Telegram bot:

  Receive a user’s image description (e.g., "a cyberpunk cat wearing sunglasses").
  Refine the prompt using AI (Gemini/OpenAI) for better results.
  Generate the image via Hugging Face’s free API (no costs!).
  Send the final image back to the user—all in seconds!

  How It Works?
  Telegram Trigger**
  Listens for user messages (e.g., “/image a futuristic cityscape”).

  AI Prompt Refinement**
  Uses Google Gemini (or OpenAI) to optimize the input for the image model.

  AI Image Generation**
  Calls Hugging Face’s Together API (free tier) to create the image.
  Supports models like black-forest-labs/FLUX.1-schnell.

  Auto-Delivery**
  Downloads the image and sends it in the Telegram chat.

  Setup Guide (3 Minutes!)

  1. Prerequisites

  An n8n instance (cloud/self-hosted).
  A Telegram bot token (get it from @BotFather).
  A Hugging Face API token (free: https://huggingface.co/).

  2. Installation

  Import the JSON template into n8n.
  Replace placeholders:
  Telegram API token (in the Telegram nodes).
  Hugging Face API token (in the HTTP Request node).

  (Optional) Swap Gemini for OpenAI if preferred.

  3. Done!

  Activate the workflow—your bot is now ready to create stunning images! Simply send a command like:
  “Hey, generate an image of a warrior standing on top of a mountain.”

  You can keep your prompt casual or get as detailed as you like. The AI will interpret your request and craft a full, descriptive prompt for image generation. For example:
  “Generate an image of a warrior wearing tattered clothes, chest out, standing on a snowy mountain.”

  Why Use This Template?
  100% Free – Uses Hugging Face’s free tier (no OpenAI costs).
  No Coding – Fully visual n8n workflow.
  Customizable – Swap AI models (Gemini/OpenAI) or image APIs.
  Instant Results – Users get images in seconds.

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.telegram","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatGoogleGemini"]

workflow_json:
  {"meta":{"instanceId":"d04643ba872bb0fb252ed2c8197858d58cc47dd3c15ff6d08b19addd679e927b","templateCredsSetupCompleted":true},"nodes":[{"id":"c81aef50-92fc-461e-9dae-45fb936f1fb6","name":"Telegram Trigger","type":"n8n-nodes-base.telegramTrigger","position":[-460,-220],"webhookId":"1eb2042d-f833-49eb-b69c-115cf5c4e729","parameters":{},"typeVersion":1.2},{"id":"c753e481-79f5-4171-a7db-895c423154a2","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[-180,-220],"parameters":{},"typeVersion":1.9},{"id":"2fda98bd-bc78-45dd-ad82-047904965df1","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[-80,80],"parameters":{},"typeVersion":1},{"id":"f69e1aee-4bce-4eaf-afce-0dcff517e779","name":"Telegram","type":"n8n-nodes-base.telegram","position":[1060,-180],"webhookId":"12236037-3950-42b7-9121-83076bcb24f7","parameters":{},"typeVersion":1.2},{"id":"f0fc7c0c-609b-4714-be3e-40423a1a5e9f","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-580,-500],"parameters":{"content":""},"typeVersion":1},{"id":"6031ea65-9875-4c7c-ac8c-812546c0bd08","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-200,0],"parameters":{"content":""},"typeVersion":1},{"id":"435da6ad-401f-4912-b943-4d93722e696e","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[180,-700],"parameters":{"content":""},"typeVersion":1},{"id":"fcccddcb-6af2-4a88-99c6-c43077527d2f","name":"HTTP Request (Huggingface)","type":"n8n-nodes-base.httpRequest","position":[540,-180],"parameters":{},"typeVersion":4.2},{"id":"15aab548-038b-4349-9233-4c7ed03ea843","name":"HTTP Request(download_image)","type":"n8n-nodes-base.httpRequest","position":[840,-180],"parameters":{},"typeVersion":4.2}],"connections":{"AI Agent":{"main":[[{"node":"HTTP Request (Huggingface)","type":"main","index":0}]]},"Telegram Trigger":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"HTTP Request (Huggingface)":{"main":[[{"node":"HTTP Request(download_image)","type":"main","index":0}]]},"HTTP Request(download_image)":{"main":[[{"node":"Send Image (back to the chat via telegram)","type":"main","index":0}]]}}}


name: Create AI Generated Videos 4x cheaper than veo3 with Google Sheets & Fal.AI
author_name: Maximiliano Rojas-Delgado
author_username: maxr
nodes_used: ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest","@n8n/n8n-nodes-langchain.openAi"]
categories: []
created_at: 2025-06-18T22:02:00.703Z
updated_at: 2025-06-18T22:02:00.703Z
url: https://n8n.io/workflows/5034
scraped_at: 2025-07-06 21:16:30
description:
  Turn Your Ideas into Videos—Right from Google Sheets!

  This workflow helps you make cool 5-second videos using Fal.AI and Kling 2.1, just by typing your idea into a Google Sheet. You can even choose if you want your video to have sound or not. It’s super easy—no tech skills needed! 

  And the best?
  4x Cheaper than Veo3 model with similar quality!

  Why use this?

  Just type your idea in a sheet—no fancy tools or uploads.

  Get a video link back in the same sheet.

  Works with or without sound—your choice!

  How does it work?

  You write your idea, pick the video shape, and say if you want sound (true or false) in the Google Sheet.

  n8n reads your idea and asks Fal.AI to make your video.

  When your video is ready, the link shows up in your sheet.

  What do you need?

  A Google account and Google Sheets connected with service account (check this link for reference)

  A copy of the following Google Spreadsheet:
  Spreadsheet to copy

  An OpenAI API key

  A Fal.AI account with some money in it

  That’s it! Just add your ideas and let the workflow make the videos for you. Have fun creating!

  if you have any questions, just contact me at max@nervoai.com

workflow_json:
  {"id":"wGQOrU5qak5K99FT","meta":{"instanceId":"d59922ccaab8f9a216dbe3eacc226c7a17998a61f6c4177822cd8e33edb224d7"},"name":"Create AI Generated Videos 4x cheaper than veo3 with Google Sheets & Fal.AI","tags":[{"id":"I8yfdg9mSqeqo4nX","name":"creator","createdAt":"2025-06-11T19:44:30.157Z","updatedAt":"2025-06-11T19:44:30.157Z"},{"id":"fElGhCk9TINqseuM","name":"templates","createdAt":"2025-06-11T19:44:28.283Z","updatedAt":"2025-06-11T19:44:28.283Z"}],"nodes":[{"id":"7beb408f-128b-4e4c-8d03-e5625fbcb2eb","name":"Wait 5s","type":"n8n-nodes-base.wait","position":[340,620],"webhookId":"150069ed-885b-497f-a32a-09e7088136e6","parameters":{},"typeVersion":1.1},{"id":"77d6a74f-b704-40f2-b054-fbf91c93726a","name":"Check if video is ready","type":"n8n-nodes-base.if","position":[160,620],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"ac50759b-e2f3-4efd-a2af-f28b7d209b45","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.status }}","rightValue":"COMPLETED"}]}},"typeVersion":2.2},{"id":"cd94d480-3562-4ce3-aff0-9caf5dee9f72","name":"Get video url","type":"n8n-nodes-base.httpRequest","position":[20,940],"parameters":{"url":"={{ $json.response_url }}","options":{},"sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Key <YOUR_API_KEY>"}]}},"typeVersion":4.2},{"id":"a5864945-030e-4d80-83cb-2f558399d8bf","name":"Submit Request to generate video","type":"n8n-nodes-base.httpRequest","position":[340,300],"parameters":{"url":"https://queue.fal.run/fal-ai/kling-video/v2.1/master/text-to-video","method":"POST","options":{},"jsonBody":"={\n  \"prompt\": \"{{ $json.prompt }}\",\n  \"aspect_ratio\": \"9:16\"\n}","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"Content-Type","value":"application/json"},{"name":"authorization","value":"Key <YOUR_API_KEY>"}]}},"typeVersion":4.2},{"id":"00f339c8-f6e3-42b3-aa56-abe34268c68a","name":"Set variables for Video generation","type":"n8n-nodes-base.set","position":[0,300],"parameters":{"options":{},"assignments":{"assignments":[{"id":"4807c116-ed98-4a0e-8dba-aab1dd2ee971","name":"prompt","type":"string","value":"={{ $json.message.content }}"},{"id":"32437b05-fa7a-4f3b-bad0-fc7201cc7371","name":"ratio","type":"string","value":"={{ $('Google Sheets Trigger').item.json.Ratio }}"}]}},"typeVersion":3.4},{"id":"88429b78-fe9f-42ca-81e1-0b364703ab2a","name":"Check video status","type":"n8n-nodes-base.httpRequest","position":[0,620],"parameters":{"url":"=https://queue.fal.run/fal-ai/kling-video/requests/{{ $json.request_id }}/status","options":{},"sendHeaders":true,"headerParameters":{"parameters":[{"name":"Authorization","value":"Key <YOUR_API_KEY>"}]}},"typeVersion":4.2},{"id":"26e74f30-575f-407a-99ee-f75daad9a2e4","name":"Google Sheets Trigger","type":"n8n-nodes-base.googleSheetsTrigger","position":[0,-20],"parameters":{"event":"rowAdded","options":{},"pollTimes":{"item":[{"mode":"everyMinute"}]},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1VGhoJU-qHzav53pTUSPtX6PNVPrRp9e38E34AmHoWvg/edit#gid=0","cachedResultName":"Results"},"documentId":{"__rl":true,"mode":"list","value":"1VGhoJU-qHzav53pTUSPtX6PNVPrRp9e38E34AmHoWvg","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1VGhoJU-qHzav53pTUSPtX6PNVPrRp9e38E34AmHoWvg/edit?usp=drivesdk","cachedResultName":"Instantly create Kling 2.1 AI Generated Videos 4x cheaper than veo3"}},"credentials":{"googleSheetsTriggerOAuth2Api":{"id":"CUMqe7iFy7F1KIF9","name":"Google Sheets account NervoAI"}},"typeVersion":1},{"id":"57f0306d-3b12-4717-afc6-c548863c2f7f","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-900,-120],"parameters":{"color":5,"width":820,"height":1220,"content":"## Create AI Generated Videos 4x cheaper than veo3 with Google Sheets & Fal.AI\n\nEasily generate 5-second videos using Fal.AI’s Kling 2.1 model—just add a row to your Google Sheet with your idea, the video ratio, and whether you want audio (true/false).\n\nHere’s what Fal.AI charges:\n\n1s video: $0.28\n\n5s video (default): $1.40\n\nHere are the execution times:\n\n5s video (default): 6 minutes\n\n**Step 1: Connect Google Sheets**\n\nAdd your Google service account credentials and make sure Google Sheets API is enabled in your Google Cloud project.\n\nCopy the shared template sheet in the description.\nif you can't find it, you need to create a sheet with the following columns:\n- Idea\n- Ratio\n- Prompt Generated\n- Video Generated\n\nDouble-check that your n8n Google Sheets nodes are linked to the correct spreadsheet.\n\n**Step 2: Connect OpenAI**\n\nGet your OpenAI API key.\n\nAdd your OpenAI credentials in n8n.\n\n**Step 3: Set Up Fal.ai**\n\nSign up at fal.ai and top up your account.\n\nGrab your API key from the Fal.ai dashboard.\n\nIn n8n, update the \"Submit Request to generate video,\" \"Check video status,\" and \"Get video url\" nodes. Replace the authorization header with your API key: 'Key <YOUR_API_KEY>'\n\n**Step 4: View Results in the Sheet**\n\nOnce your sheet updates, you’ll see the prompt used and the video URL.\n\n** Troubleshoot**\nIf the “Audio” column shows as a boolean instead of text and gives error generating the video, enter it as '=\"true\"' or '=\"false\"' in the spreadsheet.\n\nif any other issue, please contact me at max@nervoai.com\n\n\nThat’s it! You’re ready to create Veo 3 videos straight from Google Sheets.\n"},"typeVersion":1},{"id":"774b9b76-4cd8-4d5a-8b8b-587ee1cae464","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-40,-140],"parameters":{"color":3,"width":540,"height":300,"content":"## Stage 1: Trigger & Prompt Generation\nStarts the workflow when a new row is added in Google Sheets, then when the workflow is actioned, it generates a prompt for the Kling 2.1 video model based on the sheet data."},"typeVersion":1},{"id":"169699a3-6208-4586-8c3c-a3df7f3cdaf2","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-40,180],"parameters":{"color":6,"width":540,"height":300,"content":"## Stage 2: Prepare & Submit Video Request\nSets up all necessary variables for video creation and sends a request to Fal.AI to generate the video."},"typeVersion":1},{"id":"739cdf63-5e11-4364-b4f8-3b65e962ce3e","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-40,500],"parameters":{"width":540,"height":300,"content":"## Stage 3: Monitor Video Status\nChecks the status of the video generation. Waits and repeatedly checks every 5 seconds until the video is ready."},"typeVersion":1},{"id":"49c27097-de0e-4516-8ee0-8936507d7455","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-40,820],"parameters":{"color":4,"width":540,"height":300,"content":"## Stage 4: Retrieve & Update Results\nGets the final video URL and updates the Google Sheet with the video link and the prompt used."},"typeVersion":1},{"id":"9dc75bc3-25a7-4c3c-bb65-8372acb2703b","name":"Update sheet with video url and prompt used in Kling 2.1","type":"n8n-nodes-base.googleSheets","position":[340,940],"parameters":{"columns":{"value":{"Idea":"={{ $('Google Sheets Trigger').item.json.Idea }}","Video Generated":"={{ $json.video.url }}","Prompt Generated":"={{ $('Generate prompt for Kling 2.1 model').item.json.message.content }}"},"schema":[{"id":"Idea","type":"string","display":true,"removed":false,"required":false,"displayName":"Idea","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Ratio","type":"string","display":true,"required":false,"displayName":"Ratio","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Audio","type":"string","display":true,"required":false,"displayName":"Audio","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Prompt Generated","type":"string","display":true,"required":false,"displayName":"Prompt Generated","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Video Generated","type":"string","display":true,"required":false,"displayName":"Video Generated","defaultMatch":false,"canBeUsedToMatch":true},{"id":"row_number","type":"string","display":true,"removed":true,"readOnly":true,"required":false,"displayName":"row_number","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["Idea"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"update","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/100ur8DnU_q2YIAx15ccMfEWC43Di_G7hj19csjxg73A/edit#gid=0","cachedResultName":"Results"},"documentId":{"__rl":true,"mode":"list","value":"1VGhoJU-qHzav53pTUSPtX6PNVPrRp9e38E34AmHoWvg","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1VGhoJU-qHzav53pTUSPtX6PNVPrRp9e38E34AmHoWvg/edit?usp=drivesdk","cachedResultName":"Instantly create Kling 2.1 AI Generated Videos 4x cheaper than veo3"}},"credentials":{"googleSheetsOAuth2Api":{"id":"f8o05SKiFZmuFhu9","name":"Google Sheets account nervoAI"}},"typeVersion":4.6},{"id":"5267ac1d-36ad-449a-9f5f-cae01a090b33","name":"Generate prompt for Kling 2.1 model","type":"@n8n/n8n-nodes-langchain.openAi","position":[180,-20],"parameters":{"modelId":{"__rl":true,"mode":"list","value":"gpt-4.1-nano-2025-04-14","cachedResultName":"GPT-4.1-NANO-2025-04-14"},"options":{},"messages":{"values":[{"role":"assistant","content":"=You are a creative prompt engineer for Kling 2.1 video generation model. For any concept provided, craft a detailed, visually immersive prompt that specifies the subject, setting, lighting, mood, era or style, object details, composition, and background elements. Use evocative, sensory-rich language and guide the model to produce authentic, high-quality images. Match the style and depth of the following example:\n\nA casual street interview on a busy New York City sidewalk in the afternoon. The interviewer holds a plain, unbranded microphone and asks: Have you seen Google's new Veo3 model It is a super good model. Person replies: Yeah I saw it, it's already available on fal. It's crazy good.\n\nRespond only with the crafted prompt."},{"content":"=the input is: {{ $json.Idea }}"}]}},"credentials":{"openAiApi":{"id":"6iZ86Vz38pnHnAuF","name":"OpenAi account"}},"typeVersion":1.8}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"4a9e4bf8-ae9b-40c8-aeed-8a61fbc383a6","connections":{"Wait 5s":{"main":[[{"node":"Check video status","type":"main","index":0}]]},"Get video url":{"main":[[{"node":"Update sheet with video url and prompt used in Kling 2.1","type":"main","index":0}]]},"Check video status":{"main":[[{"node":"Check if video is ready","type":"main","index":0}]]},"Google Sheets Trigger":{"main":[[{"node":"Generate prompt for Kling 2.1 model","type":"main","index":0}]]},"Check if video is ready":{"main":[[{"node":"Get video url","type":"main","index":0}],[{"node":"Wait 5s","type":"main","index":0}]]},"Submit Request to generate video":{"main":[[{"node":"Check video status","type":"main","index":0}]]},"Set variables for Video generation":{"main":[[{"node":"Submit Request to generate video","type":"main","index":0}]]},"Generate prompt for Kling 2.1 model":{"main":[[{"node":"Set variables for Video generation","type":"main","index":0}]]}}}


name: Generate & Auto-post AI Videos to Social Media with Veo3 and Blotato
author_name: Dr. Firas
author_username: drfiras
categories: []
created_at: 2025-06-18T22:44:00.392Z
updated_at: 2025-06-18T22:44:00.392Z
url: https://n8n.io/workflows/5035
scraped_at: 2025-07-06 21:16:30
description:
  Automate video creation with Veo3 and auto-post to Instagram, TikTok via Blotato

  Who is this for?

  This template is ideal for content creators, social media managers, YouTubers, and digital marketers who want to generate high-quality videos daily using AI and distribute them effortlessly across multiple platforms.

  It’s perfect for anyone who wants to scale short-form content creation without video editing tools.

  What problem is this workflow solving?

  Creating and distributing consistent video content requires:
  Generating ideas
  Writing scripts and prompts
  Rendering videos
  Manually posting to platforms

  This workflow automates all of that. It transforms one prompt into a professional AI-generated video and publishes it automatically — saving time and increasing reach.

  What this workflow does

  Triggers daily to generate a new idea with OpenAI (or your custom prompt).
  Creates a video prompt formatted specifically for Google Veo3.
  Generates a cinematic video using the Veo3 API.
  Logs the video data into a Google Sheet.
  Retrieves the final video URL once Veo3 finishes rendering.
  Uploads the video to Blotato for publishing.
  Auto-posts the video to Instagram, TikTok, YouTube, Facebook, LinkedIn, Threads, Twitter (X), Pinterest, and Bluesky.

  Setup

  Add your OpenAI API key to the GPT-4.1 nodes.
  Connect your Veo3 API credentials in the video generation node.
  Link your Google Sheets account and use a sheet with columns: Prompt, Video URL, Status.
  Connect your Blotato API key and set your platform IDs in the Assign Social Media IDs node.
  Adjust the Schedule Trigger to your desired posting frequency.

  How to customize this workflow to your needs

  Edit the AI prompt** to align with your niche (fitness, finance, education, etc.).
  Add your own branding overlays** using JSON2Video or similar tools.
  Change platform selection** by enabling/disabling specific HTTP Request nodes.
  Add a Telegram step** to preview the video before auto-posting.
  Track performance** by adding metrics columns in Google Sheets.

  📄 Documentation: Notion Guide

  Need help customizing?
  Contact me for consulting and support : Linkedin / Youtube

nodes_used:
  ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.outputParserStructured","@n8n/n8n-nodes-langchain.toolThink"]

workflow_json:
  {"id":"eFkkWqS5KdrxZ43P","meta":{"instanceId":"a2b23892dd6989fda7c1209b381f5850373a7d2b85609624d7c2b7a092671d44","templateCredsSetupCompleted":true},"name":"Automate video creation with Veo3 and auto-post to Instagram, TikTok via Blotato - vide","tags":[],"nodes":[{"id":"11a7c5b6-0db7-4d99-a1a0-e34e05c23ff5","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[340,480],"parameters":{"width":1200,"height":500,"content":"# ✅ STEP 1 — Generate Script & Prompt with AI"},"typeVersion":1},{"id":"2f3aec5c-4144-4e0c-b1c8-7f96dfe14370","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[340,1020],"parameters":{"color":3,"width":1200,"height":280,"content":"# ✅ STEP 2 — Create Video Using Veo3\n\n"},"typeVersion":1},{"id":"45a5a9f4-fe6a-43a7-a032-c69750826209","name":"Assign Social Media IDs","type":"n8n-nodes-base.set","position":[420,1680],"parameters":{"mode":"raw","options":{},"jsonOutput":"{\n  \"instagram_id\": \"1111\",\n  \"youtube_id\": \"1111\",\n  \"threads_id\": \"1111\",\n  \"tiktok_id\": \"1111\",\n  \"facebook_id\": \"1111\",\n  \"facebook_page_id\": \"1111\",\n  \"twitter_id\": \"1111\",\n  \"linkedin_id\": \"1111\",\n  \"pinterest_id\": \"1111\",\n  \"pinterest_board_id\": \"1111\",\n  \"bluesky_id\": \"1111\"\n}\n"},"typeVersion":3.4},{"id":"6d125a85-b626-4981-8cfc-bcac4ea0ca89","name":"Get my video","type":"n8n-nodes-base.googleSheets","position":[520,1440],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"id","value":"="},"documentId":{"__rl":true,"mode":"id","value":"="}},"credentials":{"googleSheetsOAuth2Api":{"id":"51us92xkOlrvArhV","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"779818a1-97bd-4bf9-ba17-995c1439df6f","name":"Upload Video to Blotato","type":"n8n-nodes-base.httpRequest","position":[640,1680],"parameters":{"url":"https://backend.blotato.com/v2/media","method":"POST","options":{},"sendBody":true,"sendHeaders":true,"bodyParameters":{"parameters":[{"name":"url","value":"={{ $('Get my video').item.json['final_output'] }}"}]},"headerParameters":{"parameters":[{"name":"blotato-api-key","value":"YOUR_API_HERE"}]}},"typeVersion":4.2},{"id":"113d635c-bf8f-4ed3-801e-de78b0df9437","name":"INSTAGRAM","type":"n8n-nodes-base.httpRequest","position":[920,1440],"parameters":{"url":"https://backend.blotato.com/v2/posts","method":"POST","options":{},"jsonBody":"={\n  \"post\": {\n    \"accountId\": \"{{ $('Assign Social Media IDs').item.json.instagram_id }}\",\n    \"target\": {\n      \"targetType\": \"instagram\"\n    },\n    \"content\": {\n      \"text\": \"{{ $('Get my video').item.json.DESCRIPTION }}\",\n      \"platform\": \"instagram\",\n      \"mediaUrls\": [\n        \"{{ $json.url }}\"\n      ]\n    }\n  }\n}\n\n","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"blotato-api-key","value":"YOUR_API_HERE"}]}},"typeVersion":4.2},{"id":"02aa72ee-e5b9-44ee-9cbf-e8ddbc259570","name":"YOUTUBE","type":"n8n-nodes-base.httpRequest","position":[1140,1440],"parameters":{"url":"https://backend.blotato.com/v2/posts","method":"POST","options":{},"jsonBody":"={\n  \"post\": {\n    \"accountId\": \"{{ $('Assign Social Media IDs').item.json.youtube_id }}\",\n    \"target\": {\n      \"targetType\": \"youtube\",\n      \"title\": \"{{ $('Get my video').item.json.Titre }}\",\n      \"privacyStatus\": \"unlisted\",\n      \"shouldNotifySubscribers\": \"false\"\n    },\n    \"content\": {\n      \"text\": \"{{ $('Get my video').item.json.DESCRIPTION }}\",\n      \"platform\": \"youtube\",\n      \"mediaUrls\": [\n        \"{{ $json.url }}\"\n      ]\n    }\n  }\n}\n","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"blotato-api-key","value":"YOUR_API_HERE"}]}},"typeVersion":4.2},{"id":"b9e82889-b753-43e7-b417-213a99763802","name":"TIKTOK","type":"n8n-nodes-base.httpRequest","position":[1340,1440],"parameters":{"url":"https://backend.blotato.com/v2/posts","method":"POST","options":{},"jsonBody":"={\n  \"post\": {\n    \"accountId\": \"{{ $('Assign Social Media IDs').item.json.tiktok_id }}\",\n    \"target\": {\n      \"targetType\": \"tiktok\",\n      \"isYourBrand\": \"false\", \n      \"disabledDuet\": \"false\",\n      \"privacyLevel\": \"PUBLIC_TO_EVERYONE\",\n      \"isAiGenerated\": \"true\",\n      \"disabledStitch\": \"false\",\n      \"disabledComments\": \"false\",\n      \"isBrandedContent\": \"false\"\n      \n    },\n    \"content\": {\n      \"text\": \"{{ $('Get my video').item.json.DESCRIPTION }}\",\n      \"platform\": \"tiktok\",\n      \"mediaUrls\": [\n        \"{{ $json.url }}\"\n      ]\n    }\n  }\n}\n","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"blotato-api-key","value":"=YOUR_API_HERE"}]}},"typeVersion":4.2},{"id":"edf4cd31-ae48-4996-816e-8a32ac411e75","name":"FACEBOOK","type":"n8n-nodes-base.httpRequest","position":[920,1680],"parameters":{"url":"https://backend.blotato.com/v2/posts","method":"POST","options":{},"jsonBody":"={\n  \"post\": {\n    \"accountId\": \"{{ $('Assign Social Media IDs').item.json.facebook_id }}\",\n    \"target\": {\n      \"targetType\": \"facebook\",\n      \"pageId\": \"{{ $('Assign Social Media IDs').item.json.facebook_page_id }}\"\n\n      \n    },\n    \"content\": {\n      \"text\": \"{{ $('Get my video').item.json.DESCRIPTION }}\",\n      \"platform\": \"facebook\",\n      \"mediaUrls\": [\n        \"{{ $json.url }}\"\n      ]\n    }\n  }\n}","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"blotato-api-key","value":"=YOUR_API_HERE"}]}},"typeVersion":4.2},{"id":"edeb50af-020e-4118-af73-2a4fbb3bf6a2","name":"THREADS","type":"n8n-nodes-base.httpRequest","position":[1140,1680],"parameters":{"url":"https://backend.blotato.com/v2/posts","method":"POST","options":{},"jsonBody":"={\n  \"post\": {\n    \"accountId\": \"{{ $('Assign Social Media IDs').item.json.threads_id }}\",\n    \"target\": {\n      \"targetType\": \"threads\"\n      \n    },\n    \"content\": {\n      \"text\": \"{{ $('Get my video').item.json.DESCRIPTION }}\",\n      \"platform\": \"threads\",\n      \"mediaUrls\": [\n        \"{{ $json.url }}\"\n      ]\n    }\n  }\n}\n","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"blotato-api-key","value":"YOUR_API_HERE"}]}},"typeVersion":4.2},{"id":"210e36e9-8db2-403c-b72a-2ec45bce2eae","name":"TWETTER","type":"n8n-nodes-base.httpRequest","position":[1340,1680],"parameters":{"url":"https://backend.blotato.com/v2/posts","method":"POST","options":{},"jsonBody":"={\n  \"post\": {\n    \"accountId\": \"{{ $('Assign Social Media IDs').item.json.twitter_id }}\",\n    \"target\": {\n      \"targetType\": \"twitter\"\n      \n    },\n    \"content\": {\n      \"text\": \"{{ $('Get my video').item.json.DESCRIPTION }}\",\n      \"platform\": \"twitter\",\n      \"mediaUrls\": [\n        \"{{ $json.url }}\"\n      ]\n    }\n  }\n}\n","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"blotato-api-key","value":"YOUR_API_HERE"}]}},"typeVersion":4.2},{"id":"ac3069e4-4fe6-4146-a0e2-973b3c374c55","name":"LINKEDIN","type":"n8n-nodes-base.httpRequest","position":[920,1920],"parameters":{"url":"https://backend.blotato.com/v2/posts","method":"POST","options":{},"jsonBody":"={\n  \"post\": {\n    \"accountId\": \"{{ $('Assign Social Media IDs').item.json.linkedin_id }}\",\n    \"target\": {\n      \"targetType\": \"linkedin\"\n      \n    },\n    \"content\": {\n      \"text\": \"{{ $('Get my video').item.json.DESCRIPTION }}\",\n      \"platform\": \"linkedin\",\n      \"mediaUrls\": [\n        \"{{ $json.url }}\"\n      ]\n    }\n  }\n}\n","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"blotato-api-key","value":"YOUR_API_HERE"}]}},"typeVersion":4.2},{"id":"d9c919d8-ae9c-47cf-9b6f-8cb3e7e1f500","name":"BLUESKY","type":"n8n-nodes-base.httpRequest","position":[1140,1920],"parameters":{"url":"https://backend.blotato.com/v2/posts","method":"POST","options":{},"jsonBody":"= {\n  \"post\": {\n    \"accountId\": \"{{ $('Assign Social Media IDs').item.json.bluesky_id }}\",\n    \"target\": {\n      \"targetType\": \"bluesky\"\n      \n    },\n    \"content\": {\n      \"text\": \"{{ $('Get my video').item.json.DESCRIPTION }}\",\n      \"platform\": \"bluesky\",\n      \"mediaUrls\": [\n        \"https://pbs.twimg.com/media/GE8MgIiWEAAfsK3.jpg\"\n      ]\n    }\n  }\n}\n","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"blotato-api-key","value":"YOUR_API_HERE"}]}},"typeVersion":4.2},{"id":"a0a0a8fe-f6b0-458c-846e-409200a7b12f","name":"PINTEREST","type":"n8n-nodes-base.httpRequest","position":[1340,1920],"parameters":{"url":"https://backend.blotato.com/v2/posts","method":"POST","options":{},"jsonBody":"={\n  \"post\": {\n    \"accountId\": \"{{ $('Assign Social Media IDs').item.json.pinterest_id }}\",\n    \"target\": {\n      \"targetType\": \"pinterest\",\n      \"boardId\": \"{{ $('Assign Social Media IDs').item.json.pinterest_board_id }}\"      \n    },\n    \"content\": {\n      \"text\": \"{{ $('Get my video').item.json.DESCRIPTION }}\",\n      \"platform\": \"pinterest\",\n      \"mediaUrls\": [\n        \"https://pbs.twimg.com/media/GE8MgIiWEAAfsK3.jpg\"\n      ]\n    }\n  }\n}\n\n","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"blotato-api-key","value":"YOUR_API_HERE"}]}},"typeVersion":4.2},{"id":"38c75425-36a5-45c7-98cb-ed5eb20af249","name":"Google Sheets","type":"n8n-nodes-base.googleSheets","position":[640,1920],"parameters":{"columns":{"value":{"STATUS":"Publish","row_number":"={{ $('Get my video').item.json.row_number }}"},"schema":[{"id":"PROMPT","type":"string","display":true,"required":false,"displayName":"PROMPT","defaultMatch":false,"canBeUsedToMatch":true},{"id":"DESCRIPTION","type":"string","display":true,"required":false,"displayName":"DESCRIPTION","defaultMatch":false,"canBeUsedToMatch":true},{"id":"URL VIDEO","type":"string","display":true,"required":false,"displayName":"URL VIDEO","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Titre","type":"string","display":true,"required":false,"displayName":"Titre","defaultMatch":false,"canBeUsedToMatch":true},{"id":"STATUS","type":"string","display":true,"required":false,"displayName":"STATUS","defaultMatch":false,"canBeUsedToMatch":true},{"id":"row_number","type":"string","display":true,"removed":false,"readOnly":true,"required":false,"displayName":"row_number","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["row_number"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"update","sheetName":{"__rl":true,"mode":"id","value":"="},"documentId":{"__rl":true,"mode":"id","value":"="}},"credentials":{"googleSheetsOAuth2Api":{"id":"51us92xkOlrvArhV","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"94db7d6e-ce83-4c9a-916c-c35c802f8d4d","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[340,1340],"parameters":{"color":4,"width":1200,"height":760,"content":"# ✅ STEP 3 — Publish Video to Social Media\n"},"typeVersion":1},{"id":"3ac616bc-67bb-494c-bd24-3753fc03e7dc","name":"Trigger: Run Daily Script Generator","type":"n8n-nodes-base.scheduleTrigger","position":[500,560],"parameters":{"rule":{"interval":[{}]}},"typeVersion":1.2},{"id":"8ae30b31-2ac9-4b62-9094-ce36197d319d","name":"AI Agent: Generate Video Concept","type":"@n8n/n8n-nodes-langchain.agent","position":[660,560],"parameters":{"text":"Give me an idea about [a Yeti speaking to a camera and doing a Vlog through his selfie stick]. ","options":{"systemMessage":"=You are an AI designed to generate 1 immersive, realistic idea based on a user-provided topic. Your output must be formatted as a JSON array (single line) and follow all the rules below exactly.\n\nRULES:\n\nOnly return 1 idea at a time.\n\nThe user will provide a key topic (e.g. “urban farming,” “arctic survival,” “street food in Vietnam”).\n\nThe Idea must:\n\nBe under 13 words.\n\nDescribe an interesting and viral-worthy moment, action, or event related to the provided topic.\n\nCan be as surreal as you can get, doesn't have to be real-world!\n\nInvolves a character.\n\nThe Caption must be:\n\nShort, punchy, and viral-friendly.\n\nInclude one relevant emoji.\n\nInclude exactly 12 hashtags in this order:\n** 4 topic-relevant hashtags\n** 4 all-time most popular hashtags\n** 4 currently trending hashtags (based on live research)\n\nAll hashtags must be lowercase.\n\nSet Status to \"for production\" (always).\n\nThe Environment must:\n\nBe under 20 words.\n\nMatch the action in the Idea exactly.\n\nClearly describe:\n\nWhere the event is happening (e.g. rooftop, jungle trail, city alley, frozen lake)\n\nKey visuals or background details (e.g. smoke rising, neon lights, fog, birds overhead)\n\nMain participants (e.g. farmer, cook, mechanic, rescue team, animal)\n\nStyle of scene (e.g. cinematic realism, handheld docu-style, aerial tracking shot, macro close-up)\n\nOk with fictional settings\n\nOUTPUT FORMAT (single-line JSON array):\n\n\n[\n  {\n    \"Caption\": \"Short viral title with emoji #4_topic_hashtags #4_all_time_popular_hashtags #4_trending_hashtags\",\n    \"Idea\": \"Short idea under 13 words\",\n    \"Environment\": \"Brief vivid setting under 20 words matching the action\",\n    \"Status\": \"for production\"\n  }\n]\n"},"promptType":"define","hasOutputParser":true},"typeVersion":1.9},{"id":"1685126b-bd11-4798-aae9-c676d6cf743d","name":"Tool: Inject Creativity","type":"@n8n/n8n-nodes-langchain.toolThink","position":[740,820],"parameters":{},"typeVersion":1},{"id":"30b4a035-33df-4826-972d-0ed2dd8fbed9","name":"LLM: Generate Idea & Caption (GPT-4.1)","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[580,820],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4.1","cachedResultName":"gpt-4.1"},"options":{}},"credentials":{"openAiApi":{"id":"6h3DfVhNPw9I25nO","name":"OpenAi account"}},"typeVersion":1.2},{"id":"c1e92152-aa05-43dd-8522-23f1514cf0ad","name":"Parser: Extract JSON from Idea","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[900,820],"parameters":{"jsonSchemaExample":"[\n  {\n    \"Caption\": \"Diver Removes Nets Off Whale 🐋 #whalerescue #marinelife #oceanrescue #seahelpers #love #nature #instagood #explore #viral #savenature #oceanguardians #cleanoceans\",\n    \"Idea\": \"Diver carefully cuts tangled net from distressed whale in open sea\",\n    \"Environment\": \"Open ocean, sunlight beams through water, diver and whale, cinematic realism\",\n    \"Status\": \"for production\"\n  }\n]\n"},"typeVersion":1.2},{"id":"432c7648-f9f9-4807-abf5-64d8f9a6bafb","name":"Google Sheets: Save Script Idea","type":"n8n-nodes-base.googleSheets","position":[1020,560],"parameters":{"columns":{"value":{"id":"==ROW()-1","idea":"={{ $json.output[0].Idea }}","caption":"={{ $json.output[0].Caption }}","production":"={{ $json.output[0].Status }}","environment_prompt":"={{ $json.output[0].Environment }}"},"schema":[{"id":"id","type":"string","display":true,"removed":false,"required":false,"displayName":"id","defaultMatch":true,"canBeUsedToMatch":true},{"id":"idea","type":"string","display":true,"required":false,"displayName":"idea","defaultMatch":false,"canBeUsedToMatch":true},{"id":"caption","type":"string","display":true,"required":false,"displayName":"caption","defaultMatch":false,"canBeUsedToMatch":true},{"id":"production","type":"string","display":true,"required":false,"displayName":"production","defaultMatch":false,"canBeUsedToMatch":true},{"id":"environment_prompt","type":"string","display":true,"required":false,"displayName":"environment_prompt","defaultMatch":false,"canBeUsedToMatch":true},{"id":"final_output","type":"string","display":true,"required":false,"displayName":"final_output","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["id"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"append","sheetName":{"__rl":true,"mode":"id","value":"="},"documentId":{"__rl":true,"mode":"id","value":"="}},"credentials":{"googleSheetsOAuth2Api":{"id":"51us92xkOlrvArhV","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"02c2e969-0bb6-44fa-8707-37edc2cc77fd","name":"AI Agent: Create Veo3-Compatible Prompt","type":"@n8n/n8n-nodes-langchain.agent","position":[1180,560],"parameters":{"text":"=Give me a Veo3 prompt for this idea:\n{{ $json.idea }}\n\nThis is the environment:\n{{ $json.environment_prompt }}\n\n","options":{"systemMessage":"=SYSTEM PROMPT FOR GOOGLE VEO3 PROMPT AGENT\n\nYou are an AI agent that writes hyper-realistic, cinematic video prompts for Google VEO3. Each prompt should describe a short, vivid selfie-style video clip featuring one unnamed character speaking or acting in a specific moment. The final video should look like found footage or documentary-style film — grounded, realistic, and immersive.\n\nREQUIRED STRUCTURE (FILL IN THE BRACKETS BELOW):\n\n[Scene paragraph prompt here]\n\nMain character: [description of character]\nThey say: [insert one line of dialogue, fits the scene and mood].\nThey [describe a physical action or subtle camera movement, e.g. pans the camera, shifts position, glances around].\nTime of Day: [day / night / dusk / etc.]\nLens: [describe lens]\nAudio: (implied) [ambient sounds, e.g. lion growls, wind, distant traffic, birdsong]\nBackground: [brief restatement of what is visible behind them]\n\nRULES FOR PROMPT GENERATION\n\nSingle paragraph only, 750–1500 characters. No line breaks or headings.\n\nOnly one human character. Never give them a name.\n\nInclude one spoken line of dialogue and describe how it’s delivered.\n\nCharacter must do something physical, even if subtle (e.g. glance, smirk, pan camera).\n\nUse selfie-style framing. Always describe the lens, stock, and camera behavior.\n\nScene must feel real and cinematic — like a short clip someone might record on a stylized camera.\n\nAlways include the five key technical elements: Time of Day, Lens, Film Stock, Audio, and Background.\n\nDO NOT DO THIS:\n\nDon’t name the character.\n\nDon’t include more than one character.\n\nDon’t describe subtitles or on-screen text.\n\nDon’t break the paragraph or use formatting.\n\nDon’t write vague or abstract scenes — always keep them grounded in physical detail."},"promptType":"define","hasOutputParser":true},"typeVersion":1.9},{"id":"010485e3-7b3f-496b-bcd5-05087a41805c","name":"Tool: Build Prompt Structure","type":"@n8n/n8n-nodes-langchain.toolThink","position":[1380,820],"parameters":{},"typeVersion":1},{"id":"acec06a9-c36d-4bff-a152-4a5b8b73808d","name":"LLM: Format Prompt for Veo3 (GPT-4.1)","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1200,820],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4.1","cachedResultName":"gpt-4.1"},"options":{}},"credentials":{"openAiApi":{"id":"6h3DfVhNPw9I25nO","name":"OpenAi account"}},"typeVersion":1.2},{"id":"4f8e53f5-d0a1-46c1-a855-a7067b493d66","name":"Call Veo3 API to Generate Video","type":"n8n-nodes-base.httpRequest","position":[520,1100],"parameters":{"url":"https://queue.fal.run/fal-ai/veo3","body":"={ \"prompt\": \"{{ $json.output }}\" }\n","method":"POST","options":{"batching":{"batch":{"batchSize":1,"batchInterval":2000}}},"sendBody":true,"contentType":"raw","authentication":"genericCredentialType","rawContentType":"application/json","genericAuthType":"httpHeaderAuth"},"credentials":{"httpHeaderAuth":{"id":"QhpKhFJMiQAReugp","name":"Header Auth account 4"}},"typeVersion":4.2},{"id":"27881cbe-df1c-463d-8baa-5c482f0b1c04","name":"Wait for Veo3 Processing (5 mins)","type":"n8n-nodes-base.wait","position":[740,1100],"webhookId":"861e2761-369b-407b-9e88-1b176e617cd8","parameters":{},"typeVersion":1.1},{"id":"671eaf67-367a-41a0-b127-b06adbd5a3c9","name":"Retrieve Final Video URL from Veo3","type":"n8n-nodes-base.httpRequest","position":[1020,1100],"parameters":{"url":"=https://queue.fal.run/fal-ai/veo3/requests/{{ $json.request_id }}","options":{},"authentication":"genericCredentialType","genericAuthType":"httpHeaderAuth"},"credentials":{"httpHeaderAuth":{"id":"QhpKhFJMiQAReugp","name":"Header Auth account 4"}},"typeVersion":4.2},{"id":"3555e042-a420-49fe-889e-62455616ed7c","name":"Google Sheets: Log Final Video Output","type":"n8n-nodes-base.googleSheets","position":[1340,1100],"parameters":{"columns":{"value":{"idea":"={{ $('Google Sheets: Save Script Idea').first().json.idea }}","production":"done","final_output":"={{ $json.video.url }}"},"schema":[{"id":"id","type":"string","display":true,"removed":false,"required":false,"displayName":"id","defaultMatch":true,"canBeUsedToMatch":true},{"id":"idea","type":"string","display":true,"removed":false,"required":false,"displayName":"idea","defaultMatch":false,"canBeUsedToMatch":true},{"id":"caption","type":"string","display":true,"required":false,"displayName":"caption","defaultMatch":false,"canBeUsedToMatch":true},{"id":"production","type":"string","display":true,"required":false,"displayName":"production","defaultMatch":false,"canBeUsedToMatch":true},{"id":"environment_prompt","type":"string","display":true,"required":false,"displayName":"environment_prompt","defaultMatch":false,"canBeUsedToMatch":true},{"id":"final_output","type":"string","display":true,"required":false,"displayName":"final_output","defaultMatch":false,"canBeUsedToMatch":true},{"id":"row_number","type":"string","display":true,"removed":true,"readOnly":true,"required":false,"displayName":"row_number","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["idea"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"update","sheetName":{"__rl":true,"mode":"id","value":"="},"documentId":{"__rl":true,"mode":"id","value":"="}},"credentials":{"googleSheetsOAuth2Api":{"id":"51us92xkOlrvArhV","name":"Google Sheets account"}},"typeVersion":4.5}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"4ae2a231-a655-4a35-bc69-d4bb1af20b67","connections":{"Get my video":{"main":[[{"node":"Assign Social Media IDs","type":"main","index":0}]]},"Assign Social Media IDs":{"main":[[{"node":"Upload Video to Blotato","type":"main","index":0}]]},"Tool: Inject Creativity":{"ai_tool":[[{"node":"AI Agent: Generate Video Concept","type":"ai_tool","index":0}]]},"Upload Video to Blotato":{"main":[[{"node":"INSTAGRAM","type":"main","index":0},{"node":"YOUTUBE","type":"main","index":0},{"node":"TIKTOK","type":"main","index":0},{"node":"FACEBOOK","type":"main","index":0},{"node":"THREADS","type":"main","index":0},{"node":"TWETTER","type":"main","index":0},{"node":"LINKEDIN","type":"main","index":0},{"node":"BLUESKY","type":"main","index":0},{"node":"PINTEREST","type":"main","index":0},{"node":"Google Sheets","type":"main","index":0}]]},"Tool: Build Prompt Structure":{"ai_tool":[[{"node":"AI Agent: Create Veo3-Compatible Prompt","type":"ai_tool","index":0}]]},"Parser: Extract JSON from Idea":{"ai_outputParser":[[{"node":"AI Agent: Generate Video Concept","type":"ai_outputParser","index":0}]]},"Call Veo3 API to Generate Video":{"main":[[{"node":"Wait for Veo3 Processing (5 mins)","type":"main","index":0}]]},"Google Sheets: Save Script Idea":{"main":[[{"node":"AI Agent: Create Veo3-Compatible Prompt","type":"main","index":0}]]},"AI Agent: Generate Video Concept":{"main":[[{"node":"Google Sheets: Save Script Idea","type":"main","index":0}]]},"Wait for Veo3 Processing (5 mins)":{"main":[[{"node":"Retrieve Final Video URL from Veo3","type":"main","index":0}]]},"Retrieve Final Video URL from Veo3":{"main":[[{"node":"Google Sheets: Log Final Video Output","type":"main","index":0}]]},"Trigger: Run Daily Script Generator":{"main":[[{"node":"AI Agent: Generate Video Concept","type":"main","index":0}]]},"Google Sheets: Log Final Video Output":{"main":[[{"node":"Get my video","type":"main","index":0}]]},"LLM: Format Prompt for Veo3 (GPT-4.1)":{"ai_languageModel":[[{"node":"AI Agent: Create Veo3-Compatible Prompt","type":"ai_languageModel","index":0}]]},"LLM: Generate Idea & Caption (GPT-4.1)":{"ai_languageModel":[[{"node":"AI Agent: Generate Video Concept","type":"ai_languageModel","index":0}]]},"AI Agent: Create Veo3-Compatible Prompt":{"main":[[{"node":"Call Veo3 API to Generate Video","type":"main","index":0}]]}}}


