# templates

name: Building Your First WhatsApp Chatbot
author_name: Jimleuk
author_username: jimleuk
categories: []
created_at: 2024-10-17T10:20:43.714Z
updated_at: 2024-10-17T10:20:43.714Z
url: https://n8n.io/workflows/2465
scraped_at: 2025-07-06 21:16:30
description:
  This n8n template builds a simple WhatsApp chabot acting as a Sales Agent. The Agent is backed by a product catalog vector store to better answer user's questions.

  This template is intended to help introduce n8n users interested in building with WhatsApp.

  How it works
  This template is in 2 parts: creating the product catalog vector store and building the WhatsApp AI chatbot.
  A product brochure is imported via HTTP request node and its text contents extracted.
  The text contents are then uploaded to the in-memory vector store to build a knowledgebase for the chatbot.
  A WhatsApp trigger is used to capture messages from customers where non-text messages are filtered out.
  The customer's message is sent to the AI Agent which queries the product catalogue using the vector store tool.
  The Agent's response is sent back to the user via the WhatsApp node.

  How to use

  Once you've setup and configured your WhatsApp account and credentials
  First, populate the vector store by clicking the "Test Workflow" button.
  Next, activate the workflow to enable the WhatsApp chatbot.
  Message your designated WhatsApp number and you should receive a message from the AI sales agent.
  Tweak datasource and behaviour as required.

  Requirements
  WhatsApp Business Account
  OpenAI for LLM

  Customising this workflow

  Upgrade the vector store to Qdrant for persistance and production use-cases.
  Handle different WhatsApp message types for a more rich and engaging experience for customers.

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.whatsApp","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.embeddingsOpenAi","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.memoryBufferWindow","@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","@n8n/n8n-nodes-langchain.vectorStoreInMemory","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.toolVectorStore"]

workflow_json:
  {"meta":{"instanceId":"408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9"},"nodes":[{"id":"77ee6494-4898-47dc-81d9-35daf6f0beea","name":"WhatsApp Trigger","type":"n8n-nodes-base.whatsAppTrigger","position":[1360,-280],"webhookId":"aaa71f03-f7af-4d18-8d9a-0afb86f1b554","parameters":{"updates":["messages"]},"credentials":{"whatsAppTriggerApi":{"id":"H3uYNtpeczKMqtYm","name":"WhatsApp OAuth account"}},"typeVersion":1},{"id":"57210e27-1f89-465a-98cc-43f890a4bf58","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1960,-200],"parameters":{"model":"gpt-4o-2024-08-06","options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1},{"id":"e1053235-0ade-4e36-9ad2-8b29c78fced8","name":"Window Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[2080,-200],"parameters":{"sessionKey":"=whatsapp-75-{{ $json.messages[0].from }}","sessionIdType":"customKey"},"typeVersion":1.2},{"id":"69f1b78b-7c93-4713-863a-27e04809996f","name":"Vector Store Tool","type":"@n8n/n8n-nodes-langchain.toolVectorStore","position":[2200,-200],"parameters":{"name":"query_product_brochure","description":"Call this tool to query the product brochure. Valid for the year 2024."},"typeVersion":1},{"id":"170e8f7d-7e14-48dd-9f80-5352cc411fc1","name":"Embeddings OpenAI","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[2200,80],"parameters":{"model":"text-embedding-3-small","options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1},{"id":"ee78320b-d407-49e8-b4b8-417582a44709","name":"OpenAI Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[2440,-60],"parameters":{"model":"gpt-4o-2024-08-06","options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1},{"id":"9dd89378-5acf-4ca6-8d84-e6e64254ed02","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[0,-240],"parameters":{},"typeVersion":1},{"id":"e68fc137-1bcb-43f0-b597-3ae07f380c15","name":"Embeddings OpenAI1","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[760,-20],"parameters":{"model":"text-embedding-3-small","options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1},{"id":"2d31e92b-18d4-4f6b-8cdb-bed0056d50d7","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[900,-20],"parameters":{"options":{},"jsonData":"={{ $('Extract from File').item.json.text }}","jsonMode":"expressionData"},"typeVersion":1},{"id":"ca0c015e-fba2-4dca-b0fe-bac66681725a","name":"Recursive Character Text Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","position":[900,100],"parameters":{"options":{},"chunkSize":2000,"chunkOverlap":{}},"typeVersion":1},{"id":"63abb6b2-b955-4e65-9c63-3211dca65613","name":"Extract from File","type":"n8n-nodes-base.extractFromFile","position":[360,-240],"parameters":{"options":{},"operation":"pdf"},"typeVersion":1},{"id":"be2add9c-3670-4196-8c38-82742bf4f283","name":"get Product Brochure","type":"n8n-nodes-base.httpRequest","position":[180,-240],"parameters":{"url":"https://usa.yamaha.com/files/download/brochure/1/1474881/Yamaha-Powered-Loudspeakers-brochure-2024-en-web.pdf","options":{}},"typeVersion":4.2},{"id":"1ae5a311-36d7-4454-ab14-6788d1331780","name":"Reply To User","type":"n8n-nodes-base.whatsApp","position":[2820,-280],"parameters":{"textBody":"={{ $json.output }}","operation":"send","phoneNumberId":"477115632141067","requestOptions":{},"additionalFields":{"previewUrl":false},"recipientPhoneNumber":"={{ $('WhatsApp Trigger').item.json.messages[0].from }}"},"credentials":{"whatsAppApi":{"id":"9SFJPeqrpChOkAmw","name":"WhatsApp account"}},"typeVersion":1},{"id":"b6efba81-18b0-4378-bb91-51f39ca57f3e","name":"Reply To User1","type":"n8n-nodes-base.whatsApp","position":[1760,80],"parameters":{"textBody":"=I'm unable to process non-text messages. Please send only text messages. Thanks!","operation":"send","phoneNumberId":"477115632141067","requestOptions":{},"additionalFields":{"previewUrl":false},"recipientPhoneNumber":"={{ $('WhatsApp Trigger').item.json.messages[0].from }}"},"credentials":{"whatsAppApi":{"id":"9SFJPeqrpChOkAmw","name":"WhatsApp account"}},"typeVersion":1},{"id":"52decd86-ac6c-4d91-a938-86f93ec5f822","name":"Product Catalogue","type":"@n8n/n8n-nodes-langchain.vectorStoreInMemory","position":[2200,-60],"parameters":{"memoryKey":"whatsapp-75"},"typeVersion":1},{"id":"6dd5a652-2464-4ab8-8e5f-568529299523","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-88.75,-473.4375],"parameters":{"color":7,"width":640.4375,"height":434.6875,"content":"## 1. Download Product Brochure PDF\n[Read more about the HTTP Request Tool](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest)\n\nImport your marketing PDF document to build your vector store. This will be used as the knowledgebase by the Sales AI Agent.\n\nFor this demonstration, we'll use the HTTP request node to import the YAMAHA POWERED LOUDSPEAKERS 2024 brochure ([Source](https://usa.yamaha.com/files/download/brochure/1/1474881/Yamaha-Powered-Loudspeakers-brochure-2024-en-web.pdf)) and an Extract from File node to extract the text contents. "},"typeVersion":1},{"id":"116663bc-d8d6-41a5-93dc-b219adbb2235","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[580,-476],"parameters":{"color":7,"width":614.6875,"height":731.1875,"content":"## 2. Create Product Brochure Vector Store\n[Read more about the In-Memory Vector Store](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreinmemory/)\n\nVector stores are powerful databases which serve the purpose of matching a user's questions to relevant parts of a document. By creating a vector store of our product catalog, we'll allow users to query using natural language.\n\nTo keep things simple, we'll use the **In-memory Vector Store** which comes built-in to n8n and doesn't require a separate service. For production deployments, I'd recommend replacing the in-memory vector store with either [Qdrant](https://qdrant.tech) or [Pinecone](https://pinecone.io)."},"typeVersion":1},{"id":"86bd5334-d735-4650-aeff-06230119d705","name":"Create Product Catalogue","type":"@n8n/n8n-nodes-langchain.vectorStoreInMemory","position":[760,-200],"parameters":{"mode":"insert","memoryKey":"whatsapp-75","clearStore":true},"typeVersion":1},{"id":"b8078b0d-cbd7-423f-bb30-13902988be38","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[1254,-552],"parameters":{"color":7,"width":546.6875,"height":484.1875,"content":"## 3. Use the WhatsApp Trigger\n[Learn more about the WhatsApp Trigger](https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.whatsapptrigger/)\n\nThe WhatsApp Trigger allows you to receive incoming WhatsApp messages from customers. It requires a bit of setup so remember to follow the documentation carefully! Once ready however, it's quite easy to build powerful workflows which are easily accessible to users.\n\nNote that WhatsApp can send many message types such as audio and video so in this demonstration, we'll filter them out and just accept the text messages."},"typeVersion":1},{"id":"5bf7ed07-282b-4198-aa90-3e5ae5180404","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[1640,280],"parameters":{"width":338,"height":92,"content":"### Want to handle all message types?\nCheck out my other WhatsApp template in my creator page! https://n8n.io/creators/jimleuk/"},"typeVersion":1},{"id":"a3661b59-25d2-446e-8462-32b4d692b69d","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1640,-40],"parameters":{"color":7,"width":337.6875,"height":311.1875,"content":"### 3a. Handle Unsupported Message Types\nFor non-text messages, we'll just reply with a simple message to inform the sender."},"typeVersion":1},{"id":"ea3c9ee1-505a-40e7-82fe-9169bdbb80af","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1840,-682.5],"parameters":{"color":7,"width":746.6875,"height":929.1875,"content":"## 4. Sales AI Agent Responds To Customers\n[Learn more about using AI Agents](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/)\n\nn8n's AI agents are powerful nodes which make it incredibly easy to use state-of-the-art AI in your workflows. Not only do they have the ability to remember conversations per individual customer but also tap into resources such as our product catalogue vector store to pull factual information and data for every question.\n\nIn this demonstration, we use an AI agent which is directed to help the user navigate the product brochure. A Chat memory subnode is attached to identify and keep track of the customer session. A Vector store tool is added to allow the Agent to tap into the product catalogue knowledgebase we built earlier."},"typeVersion":1},{"id":"5c72df8d-bca1-4634-b1ed-61ffec8bd103","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[2620,-560],"parameters":{"color":7,"width":495.4375,"height":484.1875,"content":"## 5. Repond to WhatsApp User\n[Learn more about the WhatsApp Node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.whatsapp/)\n\nThe WhatsApp node is the go-to if you want to interact with WhatsApp users. With this node, you can send text, images, audio and video messages as well as use your WhatsApp message templates.\n\nHere, we'll keep it simple by replying with a text message which is the output of the AI agent."},"typeVersion":1},{"id":"48ec809f-ca0e-4052-b403-9ad7077b3fff","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-520,-620],"parameters":{"width":401.25,"height":582.6283033962263,"content":"## Try It Out!\n\n### This n8n template builds a simple WhatsApp chabot acting as a Sales Agent. The Agent is backed by a product catalog vector store to better answer user's questions.\n\n* This template is in 2 parts: creating the product catalog vector store and building the WhatsApp AI chatbot.\n* A product brochure is imported via HTTP request node and its text contents extracted.\n* The text contents are then uploaded to the in-memory vector store to build a knowledgebase for the chatbot.\n* A WhatsApp trigger is used to capture messages from customers where non-text messages are filtered out.\n* The customer's message is sent to the AI Agent which queries the product catalogue using the vector store tool.\n* The Agent's response is sent back to the user via the WhatsApp node.\n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!"},"typeVersion":1},{"id":"87cf9b41-66de-49a7-aeb0-c8809191b5a0","name":"Handle Message Types","type":"n8n-nodes-base.switch","position":[1560,-280],"parameters":{"rules":{"values":[{"outputKey":"Supported","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.messages[0].type }}","rightValue":"text"}]},"renameOutput":true},{"outputKey":"Not Supported","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"89971d8c-a386-4e77-8f6c-f491a8e84cb6","operator":{"type":"string","operation":"notEquals"},"leftValue":"={{ $json.messages[0].type }}","rightValue":"text"}]},"renameOutput":true}]},"options":{}},"typeVersion":3.2},{"id":"e52f0a50-0c34-4c4a-b493-4c42ba112277","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[-80,-20],"parameters":{"color":5,"width":345.10906976744184,"height":114.53583720930231,"content":"### You only have to run this part once!\nRun this step to populate our product catalogue vector. Run again if you want to update the vector store with a new version."},"typeVersion":1},{"id":"c1a7d6d1-191e-4343-af9f-f2c9eb4ecf49","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[1260,-40],"parameters":{"color":5,"width":364.6293255813954,"height":107.02804651162779,"content":"### Activate your workflow to use!\nTo start using the WhatsApp chatbot, you'll need to activate the workflow. If you are self-hosting ensure WhatsApp is able to connect to your server."},"typeVersion":1},{"id":"a36524d0-22a6-48cc-93fe-b4571cec428a","name":"AI Sales Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[1960,-400],"parameters":{"text":"={{ $json.messages[0].text.body }}","options":{"systemMessage":"You are an assistant working for a company who sells Yamaha Powered Loudspeakers and helping the user navigate the product catalog for the year 2024. Your goal is not to facilitate a sale but if the user enquires, direct them to the appropriate website, url or contact information.\n\nDo your best to answer any questions factually. If you don't know the answer or unable to obtain the information from the datastore, then tell the user so."},"promptType":"define"},"typeVersion":1.6}],"connections":{"AI Sales Agent":{"main":[[{"node":"Reply To User","type":"main","index":0}]]},"WhatsApp Trigger":{"main":[[{"node":"Handle Message Types","type":"main","index":0}]]},"Embeddings OpenAI":{"ai_embedding":[[{"node":"Product Catalogue","type":"ai_embedding","index":0}]]},"Extract from File":{"main":[[{"node":"Create Product Catalogue","type":"main","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"AI Sales Agent","type":"ai_languageModel","index":0}]]},"Product Catalogue":{"ai_vectorStore":[[{"node":"Vector Store Tool","type":"ai_vectorStore","index":0}]]},"Vector Store Tool":{"ai_tool":[[{"node":"AI Sales Agent","type":"ai_tool","index":0}]]},"Embeddings OpenAI1":{"ai_embedding":[[{"node":"Create Product Catalogue","type":"ai_embedding","index":0}]]},"OpenAI Chat Model1":{"ai_languageModel":[[{"node":"Vector Store Tool","type":"ai_languageModel","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"Create Product Catalogue","type":"ai_document","index":0}]]},"Handle Message Types":{"main":[[{"node":"AI Sales Agent","type":"main","index":0}],[{"node":"Reply To User1","type":"main","index":0}]]},"Window Buffer Memory":{"ai_memory":[[{"node":"AI Sales Agent","type":"ai_memory","index":0}]]},"get Product Brochure":{"main":[[{"node":"Extract from File","type":"main","index":0}]]},"Recursive Character Text Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader","type":"ai_textSplitter","index":0}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"get Product Brochure","type":"main","index":0}]]}}}


name: Scrape business emails from Google Maps without the use of any third party APIs
author_name: Akram Kadri
author_username: akramkadri
nodes_used: ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest","n8n-nodes-base.code"]
categories: []
created_at: 2024-11-24T10:56:50.080Z
updated_at: 2024-11-24T10:56:50.080Z
url: https://n8n.io/workflows/2567
scraped_at: 2025-07-06 21:16:30
description:
  Who is this template for?
  This workflow template is designed for sales, marketing, and business development professionals who want a cost-effective and efficient way to generate leads. By leveraging n8n core nodes, it scrapes business emails from Google Maps without relying on third-party APIs or paid services, ensuring there are no additional costs involved.

  Ideal for small business owners, freelancers, and agencies, this template automates the process of collecting contact information for targeted outreach, making it a powerful tool for anyone looking to scale their lead generation efforts without incurring extra expenses.

  You can watch the video tutorial here: https://youtu.be/HaiO-UeiKBA

  How it works
  This template streamlines email scraping from Google Maps using only n8n core nodes, ensuring a completely free and self-contained solution. Here’s how it operates:

  Input Queries
  You provide a list of queries, each consisting of keywords related to the type of business you want to target and the specific region or subregion you’re interested in.

  Iterates through Queries
  The workflow processes each query one at a time. For each query, it triggers a sub-workflow dedicated to handling the scraping tasks.

  Scrapes Google Maps for URLs
  Using these queries, the workflow scrapes Google Maps to collect URLs of business listings matching the provided criteria.

  Fetches HTML Content
  The workflow then fetches the HTML pages of the collected URLs for further processing.

  Extracts Emails

  Using a Code Node with custom JavaScript, the workflow runs regular expressions on the HTML content to extract business email addresses.

  Setup
  Add Queries:
  Open the first node, "Run Workflow" and input a list of queries, each containing the business keywords and the target region.

  Configure the Google Sheets Node:
  Open the Google Sheets node and select a document and specific sheet where the scraped results will be saved.

  Run the workflow:
  Click on "Test workflow" and watch your Google Sheets document gradually receive business email addresses. 

  Customize as Needed:

  You can adjust the regular expressions in the Code Node to refine the email extraction logic or add logic to extract other kinds of information.

workflow_json:
  {"name":"Google Maps Email Scraper Template","tags":[],"nodes":[{"id":"79df5316-c210-478d-a4de-35b5d31924ee","name":"Remove Duplicate URLs","type":"n8n-nodes-base.removeDuplicates","position":[-780,380],"parameters":{},"typeVersion":1.1},{"id":"985ac7e3-b501-4079-a043-780677c94b52","name":"Loop over queries","type":"n8n-nodes-base.splitInBatches","position":[-1080,-100],"parameters":{"options":{}},"typeVersion":3},{"id":"3a478935-781b-4fb1-bdc7-fcf8be1334bc","name":"Search Google Maps with query","type":"n8n-nodes-base.httpRequest","position":[-1380,380],"parameters":{"url":"=https://www.google.com/maps/search/{{ $json.query }}","options":{"allowUnauthorizedCerts":false}},"executeOnce":false,"typeVersion":4.2,"alwaysOutputData":false},{"id":"477e7d55-b7d6-4b20-ac44-dd1f443e270a","name":"Scrape URLs from results","type":"n8n-nodes-base.code","position":[-1180,380],"parameters":{"jsCode":"const data = $input.first().json.data\n\nconst regex = /https?:\\/\\/[^\\/]+/g\n\nconst urls = data.match(regex)\n\nreturn urls.map(url => ({json: {url: url}}))"},"typeVersion":2},{"id":"a5b67e45-a3f6-41d2-aa58-c26a441c41b2","name":"Filter irrelevant URLs","type":"n8n-nodes-base.filter","position":[-980,380],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"041797f2-2fe2-41dc-902a-d34050b9b304","operator":{"type":"string","operation":"notRegex"},"leftValue":"={{ $json.url }}","rightValue":"=(google|gstatic|ggpht|schema\\.org|example\\.com|sentry-next\\.wixpress\\.com|imli\\.com|sentry\\.wixpress\\.com|ingest\\.sentry\\.io)"},{"id":"eb499a7e-17bc-453c-be08-a47286f726dd","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"","rightValue":""}]}},"typeVersion":2.2},{"id":"40ec6d1f-1c98-4c9f-8499-c5893c3df7b9","name":"Request web page for URL","type":"n8n-nodes-base.httpRequest","onError":"continueRegularOutput","position":[-380,460],"parameters":{"url":"={{ $json.url }}","options":{}},"typeVersion":4.2,"alwaysOutputData":false},{"id":"12f662a8-c55f-409a-b381-f37ab6dd3794","name":"Loop over URLs","type":"n8n-nodes-base.splitInBatches","onError":"continueErrorOutput","position":[-580,380],"parameters":{"options":{"reset":false}},"typeVersion":3},{"id":"e6957d05-3533-48ae-9cc1-ee4ac026a2a6","name":"Loop over pages","type":"n8n-nodes-base.splitInBatches","onError":"continueErrorOutput","position":[-360,120],"parameters":{"options":{}},"typeVersion":3,"alwaysOutputData":false},{"id":"018621c0-0ea9-4865-b110-b6d0727f0588","name":"Scrape emails from page","type":"n8n-nodes-base.code","onError":"continueRegularOutput","position":[-200,220],"parameters":{"mode":"runOnceForEachItem","jsCode":"const data = $json.data\n\nconst emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.(?!png|jpg|gif|jpeg)[a-zA-Z]{2,}/g\n\nconst emails = data.match(emailRegex)\n\nreturn {json: {emails: emails}}"},"typeVersion":2},{"id":"5509b8e2-a6fc-4fbe-bbc5-1bc1d5de1c98","name":"Aggregate arrays of emails","type":"n8n-nodes-base.aggregate","position":[-40,100],"parameters":{"options":{"mergeLists":true},"fieldsToAggregate":{"fieldToAggregate":[{"fieldToAggregate":"emails"}]}},"typeVersion":1},{"id":"f1f01f03-b62e-453f-b938-ffe4f9b3f4de","name":"Split out into default data structure","type":"n8n-nodes-base.splitOut","position":[180,100],"parameters":{"options":{},"fieldToSplitOut":"emails"},"typeVersion":1},{"id":"ec27d665-d9c1-4f10-9c52-0d5ea89cbf77","name":"Remove duplicate emails","type":"n8n-nodes-base.removeDuplicates","position":[400,100],"parameters":{"compare":"selectedFields","options":{},"fieldsToCompare":"emails"},"typeVersion":1.1},{"id":"4a071bf0-23ad-455b-b231-bafd3b32e4f8","name":"Filter irrelevant emails","type":"n8n-nodes-base.filter","position":[600,100],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"041797f2-2fe2-41dc-902a-d34050b9b304","operator":{"type":"string","operation":"notRegex"},"leftValue":"={{ $json.emails }}","rightValue":"=(google|gstatic|ggpht|schema\\.org|example\\.com|sentry\\.wixpress\\.com|sentry-next\\.wixpress\\.com|ingest\\.sentry\\.io|sentry\\.io|imli\\.com)"}]}},"typeVersion":2.2},{"id":"59675faa-2b0d-4ba5-82c7-dc5dedcad31e","name":"Save emails to Google Sheet","type":"n8n-nodes-base.googleSheets","position":[800,100],"parameters":{"columns":{"value":{"Emails":"={{ $json.emails }}"},"schema":[{"id":"Emails","type":"string","display":true,"removed":false,"required":false,"displayName":"Emails","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["Emails"]},"options":{},"operation":"append"},"typeVersion":4.5},{"id":"93437e8b-4f8d-40a1-9585-cab1b556164a","name":"Starts scraper workflow","type":"n8n-nodes-base.executeWorkflowTrigger","position":[-1600,380],"parameters":{},"typeVersion":1},{"id":"eed77477-777d-450d-a975-4d2848b1cf55","name":"Run workflow","type":"n8n-nodes-base.manualTrigger","position":[-1320,-100],"parameters":{},"typeVersion":1},{"id":"dffaf04e-d1d2-4002-9a69-f0904b61fc2d","name":"Wait between executions","type":"n8n-nodes-base.wait","position":[-700,0],"webhookId":"40eb11a9-0f7d-4932-993e-0052b69dbf9b","parameters":{"amount":2},"typeVersion":1.1},{"id":"18787007-1d11-41b9-89c3-d5f69756eda7","name":"Execute scraper for query","type":"n8n-nodes-base.executeWorkflow","position":[-880,0],"parameters":{"mode":"each","options":{"waitForSubWorkflow":false},"workflowId":{"__rl":true,"mode":"id","value":"={{ $workflow.id }}"}},"typeVersion":1.1},{"id":"67fcde25-05e4-437c-b799-4448baea7891","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-2280,-140],"parameters":{"color":5,"width":740,"height":180,"content":"## 🛠 Setup\n1. Setup your list of queries in the \"Run workflow\" manual trigger node. Watch  this [video](https://youtu.be/HaiO-UeiKBA) on how to generate the queries with ChatGPT.\n3. Choose a sheet to populate with data in the **Google Sheets node**\n4. Run the workflow and start getting leads into your Google Sheets document"},"typeVersion":1},{"id":"ac880457-44b4-4ff7-8440-b4107f8468bb","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-700,-120],"parameters":{"color":6,"height":100,"content":"**Optional** 👇\nSet wait time between each query workflow execution. Default is 2 seconds."},"typeVersion":1},{"id":"d83afb3d-7b71-4b47-9b50-28837aac408c","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-1600,260],"parameters":{"width":480,"height":100,"content":"### Scraper 👇\nThis workflow will be executed in the background for each query. Click the **All executions** tab in the left sidebar to see the executions running."},"typeVersion":1},{"id":"007b621a-3d41-4358-aa45-560a3c8e3414","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[820,300],"parameters":{"color":4,"height":180,"content":"👆 \n1. Setup your **credentials**. Here's a [video tutorial](https://youtu.be/O5RnWDM27M8) on how to do that.\n\n2. Choose which document and sheet to save the scraped emails to. "},"typeVersion":1},{"id":"fc0b837f-624c-4d25-8ed7-f787f76c785b","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-1760,-360],"parameters":{"color":3,"content":" ## ⚠️ Note\n\nA [video tutorial](https://youtu.be/HaiO-UeiKBA) for this workflow guide is available on my [Youtube channel](https://www.youtube.com/channel/UCn8xmUBunez1SsDVRfZDUGA)"},"typeVersion":1},{"id":"2f8665d5-2890-4f7d-908b-9c09a66b6c93","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-2280,-360],"parameters":{"color":7,"width":480,"height":140,"content":"## Google Maps Automatic Email Scraper\n\nThis workflow automatically scrapes emails from businesses on Google Maps based on a list of queries that you provide."},"typeVersion":1},{"id":"7414b2ed-259d-47da-bbd1-d9ce0d64d43c","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-1000,540],"parameters":{"color":6,"width":160,"height":100,"content":"**Optional** 👆\nAdd or change the regex for filtering irrelevant URLs."},"typeVersion":1},{"id":"789c9a02-e6e7-4ea6-a7a2-acc7715b377a","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[580,260],"parameters":{"color":6,"width":200,"height":100,"content":"**Optional** 👆\nAdd or change the regex for filtering irrelevant/incorrect email addresses."},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"connections":{"Run workflow":{"main":[[{"node":"Loop over queries","type":"main","index":0}]]},"Loop over URLs":{"main":[[{"node":"Loop over pages","type":"main","index":0}],[{"node":"Request web page for URL","type":"main","index":0}]]},"Loop over pages":{"main":[[{"node":"Aggregate arrays of emails","type":"main","index":0}],[{"node":"Scrape emails from page","type":"main","index":0}]]},"Loop over queries":{"main":[[],[{"node":"Execute scraper for query","type":"main","index":0}]]},"Remove Duplicate URLs":{"main":[[{"node":"Loop over URLs","type":"main","index":0}]]},"Filter irrelevant URLs":{"main":[[{"node":"Remove Duplicate URLs","type":"main","index":0}]]},"Remove duplicate emails":{"main":[[{"node":"Filter irrelevant emails","type":"main","index":0}]]},"Scrape emails from page":{"main":[[{"node":"Loop over pages","type":"main","index":0}]]},"Starts scraper workflow":{"main":[[{"node":"Search Google Maps with query","type":"main","index":0}]]},"Wait between executions":{"main":[[{"node":"Loop over queries","type":"main","index":0}]]},"Filter irrelevant emails":{"main":[[{"node":"Save emails to Google Sheet","type":"main","index":0}]]},"Request web page for URL":{"main":[[{"node":"Loop over URLs","type":"main","index":0}]]},"Scrape URLs from results":{"main":[[{"node":"Filter irrelevant URLs","type":"main","index":0}]]},"Execute scraper for query":{"main":[[{"node":"Wait between executions","type":"main","index":0}]]},"Aggregate arrays of emails":{"main":[[{"node":"Split out into default data structure","type":"main","index":0}]]},"Search Google Maps with query":{"main":[[{"node":"Scrape URLs from results","type":"main","index":0}]]},"Split out into default data structure":{"main":[[{"node":"Remove duplicate emails","type":"main","index":0}]]}}}


name: AI Agent To Chat With Files In Supabase Storage
author_name: Mark Shcherbakov
author_username: lowcodingdev
categories: []
created_at: 2024-12-10T19:04:24.160Z
updated_at: 2024-12-10T19:04:24.160Z
url: https://n8n.io/workflows/2621
scraped_at: 2025-07-06 21:16:30
description:
  Video Guide

  I prepared a detailed guide explaining how to set up and implement this scenario, enabling you to chat with your documents stored in Supabase using n8n.



  Youtube Link

  Who is this for?
  This workflow is ideal for researchers, analysts, business owners, or anyone managing a large collection of documents. It's particularly beneficial for those who need quick contextual information retrieval from text-heavy files stored in Supabase, without needing additional services like Google Drive.

  What problem does this workflow solve?
  Manually retrieving and analyzing specific information from large document repositories is time-consuming and inefficient. This workflow automates the process by vectorizing documents and enabling AI-powered interactions, making it easy to query and retrieve context-based information from uploaded files.

  What this workflow does
  The workflow integrates Supabase with an AI-powered chatbot to process, store, and query text and PDF files. The steps include:
  Fetching and comparing files to avoid duplicate processing.
  Handling file downloads and extracting content based on the file type.
  Converting documents into vectorized data for contextual information retrieval.
  Storing and querying vectorized data from a Supabase vector store.

  File Extraction and Processing: Automates handling of multiple file formats (e.g., PDFs, text files), and extracts document content.
  Vectorized Embeddings Creation: Generates embeddings for processed data to enable AI-driven interactions.
  Dynamic Data Querying: Allows users to query their document repository conversationally using a chatbot.

  Setup

  N8N Workflow
  Fetch File List from Supabase:
     Use Supabase to retrieve the stored file list from a specified bucket.
     Add logic to manage empty folder placeholders returned by Supabase, avoiding incorrect processing.

  Compare and Filter Files:
     Aggregate the files retrieved from storage and compare them to the existing list in the Supabase files table.
     Exclude duplicates and skip placeholder files to ensure only unprocessed files are handled.

  Handle File Downloads:
     Download new files using detailed storage configurations for public/private access.
     Adjust the storage settings and GET requests to match your Supabase setup.

  File Type Processing:
     Use a Switch node to target specific file types (e.g., PDFs or text files).
     Employ relevant tools to process the content:
       For PDFs, extract embedded content.
       For text files, directly process the text data.

  Content Chunking:
     Break large text data into smaller chunks using the Text Splitter node.
     Define chunk size (default: 500 tokens) and overlap to retain necessary context across chunks.

  Vector Embedding Creation:
     Generate vectorized embeddings for the processed content using OpenAI's embedding tools.
     Ensure metadata, such as file ID, is included for easy data retrieval.

  Store Vectorized Data:
     Save the vectorized information into a dedicated Supabase vector store.
     Use the default schema and table provided by Supabase for seamless setup.

  AI Chatbot Integration:
     Add a chatbot node to handle user input and retrieve relevant document chunks.
     Use metadata like file ID for targeted queries, especially when multiple documents are involved.

  Testing
  Upload sample files to your Supabase bucket.
  Verify if files are processed and stored successfully in the vector store.
  Ask simple conversational questions about your documents using the chatbot (e.g., "What does Chapter 1 say about the Roman Empire?").
  Test for accuracy and contextual relevance of retrieved results.

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.supabase","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.embeddingsOpenAi","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","@n8n/n8n-nodes-langchain.vectorStoreSupabase","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.toolVectorStore"]

workflow_json:
  {"meta":{"instanceId":"6a2a7715680b8313f7cb4676321c5baa46680adfb913072f089f2766f42e43bd"},"nodes":[{"id":"f577f6bd-b1a4-48ec-9329-7bccc3fc1463","name":"Get All files","type":"n8n-nodes-base.httpRequest","position":[400,-100],"parameters":{"url":"=https://yqtvdcvjboenlblgcivl.supabase.co/storage/v1/object/list/private","method":"POST","options":{},"jsonBody":"={\n  \"prefix\": \"\",\n  \"limit\": 100,\n  \"offset\": 0,\n  \"sortBy\": {\n    \"column\": \"name\",\n    \"order\": \"asc\"\n  }\n}","sendBody":true,"specifyBody":"json","authentication":"predefinedCredentialType","nodeCredentialType":"supabaseApi"},"credentials":{"supabaseApi":{"id":"t8AQJzvZvrOMDLec","name":"Supabase account My Airtable Gen"}},"typeVersion":4.2},{"id":"10693bc8-560d-4cf6-8bd0-2fe3f4d863d1","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[1780,100],"parameters":{"options":{"metadata":{"metadataValues":[{"name":"=file_id","value":"={{ $json.id }}"}]}},"jsonData":"={{ $('Merge').item.json.data ?? $('Merge').item.json.text }}","jsonMode":"expressionData"},"typeVersion":1},{"id":"49428060-e707-4269-8344-77b301f56f7c","name":"Recursive Character Text Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","position":[1780,280],"parameters":{"options":{},"chunkSize":500,"chunkOverlap":200},"typeVersion":1},{"id":"08742063-e235-4874-a128-b352786b19ce","name":"Extract Document PDF","type":"n8n-nodes-base.extractFromFile","position":[1240,0],"parameters":{"options":{},"operation":"pdf"},"typeVersion":1,"alwaysOutputData":false},{"id":"21f19360-d7ce-4106-ae5a-aa0f15b7c4aa","name":"Embeddings OpenAI","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[1600,80],"parameters":{"model":"text-embedding-3-small","options":{}},"credentials":{"openAiApi":{"id":"fLfRtaXbR0EVD0pl","name":"OpenAi account"}},"typeVersion":1},{"id":"4147409f-8686-418f-b979-04f8c8e7fe42","name":"Create File record2","type":"n8n-nodes-base.supabase","position":[1540,-100],"parameters":{"tableId":"files","fieldsUi":{"fieldValues":[{"fieldId":"name","fieldValue":"={{ $('Loop Over Items').item.json.name }}"},{"fieldId":"storage_id","fieldValue":"={{ $('Loop Over Items').item.json.id }}"}]}},"credentials":{"supabaseApi":{"id":"t8AQJzvZvrOMDLec","name":"Supabase account My Airtable Gen"}},"typeVersion":1},{"id":"016f1afe-172b-4609-b451-8d67609214d3","name":"If","type":"n8n-nodes-base.if","position":[720,-100],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"9b14e306-a04d-40f7-bc5b-b8eda8d8f7f2","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ \n    !$('Aggregate').item.json.data || \n    !Array.isArray($('Aggregate').item.json.data) || \n    !$('Aggregate').item.json.data.some(item => \n        item.storage_id === $('Loop Over Items').item.json.id \n    ) \n}}","rightValue":""},{"id":"c3c0af88-9aea-4539-8948-1b69e601c27c","operator":{"type":"string","operation":"notEquals"},"leftValue":"={{ $json.name }}","rightValue":".emptyFolderPlaceholder"}]}},"typeVersion":2.2},{"id":"75e8a7db-8c4a-4ad8-b902-062cbc93e1eb","name":"Get All Files","type":"n8n-nodes-base.supabase","position":[20,-100],"parameters":{"tableId":"files","operation":"getAll"},"credentials":{"supabaseApi":{"id":"t8AQJzvZvrOMDLec","name":"Supabase account My Airtable Gen"}},"typeVersion":1,"alwaysOutputData":true},{"id":"b22a3bab-f615-4d8a-8832-ce25b1a385fe","name":"Download","type":"n8n-nodes-base.httpRequest","position":[900,-100],"parameters":{"url":"=https://yqtvdcvjboenlblgcivl.supabase.co/storage/v1/object/private/{{ $json.name }}","options":{},"authentication":"predefinedCredentialType","nodeCredentialType":"supabaseApi"},"credentials":{"supabaseApi":{"id":"t8AQJzvZvrOMDLec","name":"Supabase account My Airtable Gen"}},"typeVersion":4.2},{"id":"50d1fede-4bd0-4cd4-b74a-7d689fe211cc","name":"Loop Over Items","type":"n8n-nodes-base.splitInBatches","position":[560,-100],"parameters":{"options":{},"batchSize":"=1"},"typeVersion":3},{"id":"f9c23b5e-0b40-4886-b54f-59fb46132d3f","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-160,-100],"parameters":{},"typeVersion":1},{"id":"0a0ec290-2c3d-40ba-8d03-6abf75202e73","name":"Aggregate","type":"n8n-nodes-base.aggregate","position":[220,-100],"parameters":{"options":{},"aggregate":"aggregateAllItemData"},"typeVersion":1,"alwaysOutputData":true},{"id":"32b3e2e1-2d25-4dd1-93e8-3f693beb7b6f","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[800,-1020],"webhookId":"3c40d311-7996-4ed4-b2fa-c73bea5f4cf5","parameters":{"options":{}},"typeVersion":1.1},{"id":"79073b5c-a4ad-45a6-bbfa-e900a05bfde3","name":"OpenAI Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[940,-820],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"zJhr5piyEwVnWtaI","name":"OpenAi club"}},"typeVersion":1},{"id":"f8663483-76d5-4fc8-ad07-7eec815ff7a6","name":"Embeddings OpenAI2","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[1020,-540],"parameters":{"model":"text-embedding-3-small","options":{}},"credentials":{"openAiApi":{"id":"SphXAX7rlwRLkiox","name":"Test club key"}},"typeVersion":1},{"id":"a1458799-d379-46de-93e6-a5ba0c665163","name":"OpenAI Chat Model2","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1300,-680],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"SphXAX7rlwRLkiox","name":"Test club key"}},"typeVersion":1},{"id":"d6eeda2f-c984-406d-a625-726840308413","name":"Vector Store Tool1","type":"@n8n/n8n-nodes-langchain.toolVectorStore","position":[1100,-820],"parameters":{"name":"knowledge_base","topK":8,"description":"Retrieve data about user request"},"typeVersion":1},{"id":"e1d9a348-7d44-4ad1-adbd-2c9a31e06876","name":"Switch","type":"n8n-nodes-base.switch","position":[1060,-100],"parameters":{"rules":{"values":[{"outputKey":"txt","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{$binary.data?.fileExtension == undefined }}","rightValue":"txt"}]},"renameOutput":true},{"outputKey":"pdf","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"bf04cbec-dd86-4607-988f-4c96b6fd4b58","operator":{"type":"string","operation":"equals"},"leftValue":"={{$binary.data.fileExtension  }}","rightValue":"pdf"}]},"renameOutput":true}]},"options":{}},"typeVersion":3.1},{"id":"d38afb92-87ae-4e2a-a712-ec24b1efd105","name":"Insert into Supabase Vectorstore","type":"@n8n/n8n-nodes-langchain.vectorStoreSupabase","position":[1700,-100],"parameters":{"mode":"insert","options":{"queryName":"match_documents"},"tableName":{"__rl":true,"mode":"list","value":"documents","cachedResultName":"documents"}},"credentials":{"supabaseApi":{"id":"t8AQJzvZvrOMDLec","name":"Supabase account My Airtable Gen"}},"typeVersion":1},{"id":"1a903b2e-cab0-4798-b820-ec08d6a71ddd","name":"Merge","type":"n8n-nodes-base.merge","position":[1380,-100],"parameters":{},"typeVersion":3},{"id":"3afd552e-4995-493e-9cd5-ef496dfe359f","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[1020,-1020],"parameters":{"options":{}},"typeVersion":1.7},{"id":"d9688acc-311b-42fd-afa8-2c0e493be34b","name":"Supabase Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStoreSupabase","position":[1020,-660],"parameters":{"options":{"metadata":{"metadataValues":[{"name":"file_id","value":"300b0128-0955-4058-b0d3-a9aefe728432"}]}},"tableName":{"__rl":true,"mode":"list","value":"documents","cachedResultName":"documents"}},"credentials":{"supabaseApi":{"id":"t8AQJzvZvrOMDLec","name":"Supabase account My Airtable Gen"}},"typeVersion":1},{"id":"66df007c-0418-4551-950e-32e7d79840bd","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[340,-220],"parameters":{"height":89.3775420487804,"content":"### Replace Storage name, database ID and credentials."},"typeVersion":1},{"id":"b164b520-20dd-44a4-aa3b-647391786b20","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-20,-220],"parameters":{"height":80,"content":"### Replace credentials."},"typeVersion":1},{"id":"8688c219-5af4-4e54-9fd1-91851829445b","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[1540,-220],"parameters":{"height":80,"content":"### Replace credentials."},"typeVersion":1},{"id":"45c6ece4-f849-4496-8149-31385f5e36a4","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[840,-220],"parameters":{"height":89.3775420487804,"content":"### Replace Storage name, database ID and credentials."},"typeVersion":1},{"id":"2ca07cb0-b5f4-4761-b954-faf2131872d9","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1500,220],"parameters":{"height":80,"content":"### Replace credentials."},"typeVersion":1},{"id":"8d682dae-6f88-42f0-a717-affffd37d882","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1140,-520],"parameters":{"height":80,"content":"### Replace credentials."},"typeVersion":1},{"id":"796b5dca-d60e-43a9-afe8-194244643557","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[-520,-940],"parameters":{"color":7,"width":330.5152611046425,"height":239.5888196628349,"content":"### ... or watch set up video [10 min]\n[![Youtube Thumbnail](https://res.cloudinary.com/de9jgixzm/image/upload/v1739773273/Youtube%20Thumbs/Chat%20With%20FIles.png)](https://www.youtube.com/watch?v=glWUkdZe_3w)\n"},"typeVersion":1},{"id":"eba121de-a3f7-4ba5-8396-f7d64e648322","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-820,-1460],"parameters":{"color":7,"width":636.2128494576581,"height":497.1532689930921,"content":"![5min Logo](https://res.cloudinary.com/de9jgixzm/image/upload/v1739773200/Skool%20Assets/ejm3hqnvhgwpnu2fv92s.png)\n## AI Agent To Chat With Files In Supabase Storage\n**Made by [Mark Shcherbakov](https://www.linkedin.com/in/marklowcoding/) from community [5minAI](https://www.skool.com/5minai-2861)**\n\nManually retrieving and analyzing specific information from large document repositories is time-consuming and inefficient. This workflow automates the process by vectorizing documents and enabling AI-powered interactions, making it easy to query and retrieve context-based information from uploaded files.\n\nThe workflow integrates Supabase with an AI-powered chatbot to process, store, and query text and PDF files. The steps include:\n- Fetching and comparing files to avoid duplicate processing.\n- Handling file downloads and extracting content based on the file type.\n- Converting documents into vectorized data for contextual information retrieval.\n- Storing and querying vectorized data from a Supabase vector store.\n\n"},"typeVersion":1},{"id":"df054036-d6b9-4f53-86cb-85ad96f07d0e","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-820,-940],"parameters":{"color":7,"width":280.2462120317618,"height":545.9087885077763,"content":"### Set up steps\n\n1. **Fetch File List from Supabase**:\n   - Use Supabase to retrieve the stored file list from a specified bucket.\n   - Add logic to manage empty folder placeholders returned by Supabase, avoiding incorrect processing.\n\n2. **Compare and Filter Files**:\n   - Aggregate the files retrieved from storage and compare them to the existing list in the Supabase `files` table.\n   - Exclude duplicates and skip placeholder files to ensure only unprocessed files are handled.\n\n3. **Handle File Downloads**:\n   - Download new files using detailed storage configurations for public/private access.\n   - Adjust the storage settings and GET requests to match your Supabase setup.\n\n4. **File Type Processing**:\n   - Use a Switch node to target specific file types (e.g., PDFs or text files).\n   - Employ relevant tools to process the content:\n     - For PDFs, extract embedded content.\n     - For text files, directly process the text data.\n\n5. **Content Chunking**:\n   - Break large text data into smaller chunks using the Text Splitter node.\n   - Define chunk size (default: 500 tokens) and overlap to retain necessary context across chunks.\n\n6. **Vector Embedding Creation**:\n   - Generate vectorized embeddings for the processed content using OpenAI's embedding tools.\n   - Ensure metadata, such as file ID, is included for easy data retrieval.\n\n7. **Store Vectorized Data**:\n   - Save the vectorized information into a dedicated Supabase vector store.\n   - Use the default schema and table provided by Supabase for seamless setup.\n\n8. **AI Chatbot Integration**:\n   - Add a chatbot node to handle user input and retrieve relevant document chunks.\n   - Use metadata like file ID for targeted queries, especially when multiple documents are involved."},"typeVersion":1},{"id":"450a1e49-4be9-451a-9d05-2860e29c3695","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[540,-1160],"parameters":{"color":5,"width":951.7421645394404,"height":809.7437181509877,"content":"## Scenario 2 - AI agent"},"typeVersion":1},{"id":"c3814c5d-8881-4598-897e-268019bee1bc","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[-260,-280],"parameters":{"color":5,"width":2304.723519246249,"height":739.2522526116408,"content":"## Scenario 1 - Flow for adding new files from Supabase storage"},"typeVersion":1}],"connections":{"If":{"main":[[{"node":"Download","type":"main","index":0}],[{"node":"Loop Over Items","type":"main","index":0}]]},"Merge":{"main":[[{"node":"Create File record2","type":"main","index":0}]]},"Switch":{"main":[[{"node":"Merge","type":"main","index":0}],[{"node":"Extract Document PDF","type":"main","index":0}]]},"Download":{"main":[[{"node":"Switch","type":"main","index":0}]]},"Aggregate":{"main":[[{"node":"Get All files","type":"main","index":0}]]},"Get All Files":{"main":[[{"node":"Aggregate","type":"main","index":0}]]},"Get All files":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Loop Over Items":{"main":[null,[{"node":"If","type":"main","index":0}]]},"Embeddings OpenAI":{"ai_embedding":[[{"node":"Insert into Supabase Vectorstore","type":"ai_embedding","index":0}]]},"Embeddings OpenAI2":{"ai_embedding":[[{"node":"Supabase Vector Store","type":"ai_embedding","index":0}]]},"OpenAI Chat Model1":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"OpenAI Chat Model2":{"ai_languageModel":[[{"node":"Vector Store Tool1","type":"ai_languageModel","index":0}]]},"Vector Store Tool1":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"Create File record2":{"main":[[{"node":"Insert into Supabase Vectorstore","type":"main","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"Insert into Supabase Vectorstore","type":"ai_document","index":0}]]},"Extract Document PDF":{"main":[[{"node":"Merge","type":"main","index":1}]]},"Supabase Vector Store":{"ai_vectorStore":[[{"node":"Vector Store Tool1","type":"ai_vectorStore","index":0}]]},"When chat message received":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Insert into Supabase Vectorstore":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Recursive Character Text Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader","type":"ai_textSplitter","index":0}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"Get All Files","type":"main","index":0}]]}}}


name: ⚡AI-Powered YouTube Video Summarization & Analysis
author_name: Joseph LePage
author_username: joe
categories: []
created_at: 2024-12-29T03:01:45.635Z
updated_at: 2024-12-29T03:01:45.635Z
url: https://n8n.io/workflows/2679
scraped_at: 2025-07-06 21:16:30
description:
  -- Disclaimer: This workflow uses a community node and therefore only works for self-hosted n8n users --



  Transform YouTube videos into comprehensive summaries and structured analysis instantly. This n8n workflow automatically extracts, processes, and analyzes video transcripts to deliver clear, organized insights without watching the entire video.

  Time-Saving Features
  🚀 Instant Processing
  Simply provide a YouTube URL and receive a structured summary within seconds, eliminating the need to watch lengthy videos. Perfect for research, learning, or content analysis.

  🤖 AI-Powered Analysis
  Leverages GPT-4o-mini to analyze video transcripts, organizing key concepts and insights into a clear, hierarchical structure with main topics and essential points.

  Smart Processing Pipeline
  📝 Automated Transcript Extraction
  Supports public YouTube video
  Handles multiple URL formats
  Extracts complete video transcripts automatically

  🧠 Intelligent Content Organization
  Breaks down content into main topics
  Highlights key concepts and terminology
  Maintains technical accuracy while improving clarity
  Structures information logically with markdown formatting

  Perfect For
  📚 Researchers & Students
  Quick comprehension of educational content and lectures without watching entire videos.

  💼 Business Professionals
  Efficient analysis of industry talks, presentations, and training materials.

  🎯 Content Creators
  Rapid research and competitive analysis of video content in your niche.

  Technical Implementation
  🔄 Workflow Components
  Webhook endpoint for URL submission
  YouTube API integration for video details
  Transcript extraction system
  GPT-4 powered analysis engine
  Telegram notification system (optional)

  Transform your video content consumption with an intelligent system that delivers structured, comprehensive summaries while saving hours of viewing time.

nodes_used:
  ["n8n-nodes-base.telegram","n8n-nodes-base.youTube","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.lmChatOpenAi"]

workflow_json:
  {"nodes":[{"id":"9320d08a-4868-4103-abdf-3f8f54a7a0a0","name":"Webhook","type":"n8n-nodes-base.webhook","position":[0,0],"webhookId":"9024e29e-9080-4cf5-9a6b-0d918468f195","parameters":{"path":"ytube","options":{},"httpMethod":"POST","responseMode":"responseNode"},"typeVersion":2},{"id":"a5cc8922-8124-4269-9cfd-e891b29cc2b7","name":"YouTube Transcript","type":"n8n-nodes-youtube-transcription.youtubeTranscripter","position":[800,0],"parameters":{},"typeVersion":1},{"id":"ff3c0fd1-36d8-4d64-b405-0600efd4d93b","name":"Split Out","type":"n8n-nodes-base.splitOut","position":[200,260],"parameters":{"options":{},"fieldToSplitOut":"transcript"},"typeVersion":1},{"id":"423276e0-81bf-487a-bbdd-26e9b84fa755","name":"Respond to Webhook","type":"n8n-nodes-base.respondToWebhook","position":[1200,140],"parameters":{"options":{}},"typeVersion":1.1},{"id":"27344649-8029-48ae-867b-7363d904fc59","name":"Telegram","type":"n8n-nodes-base.telegram","position":[1200,380],"parameters":{"text":"={{ $json.title }}\n{{ $json.youtubeUrl }}","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"typeVersion":1.2},{"id":"230c0325-d22a-4070-9460-748a6fef48d5","name":"Get YouTube URL","type":"n8n-nodes-base.set","position":[200,0],"parameters":{"options":{},"assignments":{"assignments":[{"id":"3ee42e4c-3cee-4934-97e7-64c96b5691ed","name":"youtubeUrl","type":"string","value":"={{ $json.body.youtubeUrl }}"}]}},"typeVersion":3.4},{"id":"420e90c3-9dfa-4f41-825a-9874b5ebe43a","name":"YouTube Video ID","type":"n8n-nodes-base.code","position":[400,0],"parameters":{"jsCode":"const extractYoutubeId = (url) => {\n  // Regex pattern that matches both youtu.be and youtube.com URLs\n  const pattern = /(?:youtube\\.com\\/(?:[^\\/]+\\/.+\\/|(?:v|e(?:mbed)?)\\/|.*[?&]v=)|youtu\\.be\\/)([^\"&?\\/\\s]{11})/;\n  const match = url.match(pattern);\n  return match ? match[1] : null;\n};\n\n// Input URL from previous node\nconst youtubeUrl = items[0].json.youtubeUrl; // Adjust this based on your workflow\n\n// Process the URL and return the video ID\nreturn [{\n  json: {\n    videoId: extractYoutubeId(youtubeUrl)\n  }\n}];\n"},"typeVersion":2},{"id":"a4171c3e-1ff2-40de-af7f-b3971a1ebe79","name":"Get YouTube Video","type":"n8n-nodes-base.youTube","position":[600,0],"parameters":{"options":{},"videoId":"={{ $json.videoId }}","resource":"video","operation":"get"},"typeVersion":1},{"id":"73e6bfc5-8b62-4880-acd4-292f2f692540","name":"gpt-4o-mini","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[620,440],"parameters":{"options":{}},"typeVersion":1},{"id":"ea14e296-b30c-46f7-b283-746822ae1af4","name":"Summarize & Analyze Transcript","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[600,260],"parameters":{"text":"=Please analyze the given text and create a structured summary following these guidelines:\n\n1. Break down the content into main topics using Level 2 headers (##)\n2. Under each header:\n   - List only the most essential concepts and key points\n   - Use bullet points for clarity\n   - Keep explanations concise\n   - Preserve technical accuracy\n   - Highlight key terms in bold\n3. Organize the information in this sequence:\n   - Definition/Background\n   - Main characteristics\n   - Implementation details\n   - Advantages/Disadvantages\n4. Format requirements:\n   - Use markdown formatting\n   - Keep bullet points simple (no nesting)\n   - Bold important terms using **term**\n   - Use tables for comparisons\n   - Include relevant technical details\n\nPlease provide a clear, structured summary that captures the core concepts while maintaining technical accuracy.\n\nHere is the text: {{ $json.concatenated_text\n }}","promptType":"define"},"typeVersion":1.4},{"id":"90e3488f-f854-483e-9106-a5760d0c0457","name":"Concatenate","type":"n8n-nodes-base.summarize","position":[400,260],"parameters":{"options":{},"fieldsToSummarize":{"values":[{"field":"text","separateBy":" ","aggregation":"concatenate"}]}},"typeVersion":1},{"id":"9c5c249c-5eeb-4433-ba93-ace4611f4858","name":"Response Object","type":"n8n-nodes-base.set","position":[960,260],"parameters":{"options":{},"assignments":{"assignments":[{"id":"bf132004-6636-411f-9d85-0c696fda84c4","name":"summary","type":"string","value":"={{ $json.text }}"},{"id":"63c8d0e3-685c-488a-9b45-363cf52479ea","name":"topics","type":"array","value":"=[]"},{"id":"171f30cf-34e9-42f3-8735-814024bfde0b","name":"title","type":"string","value":"={{ $('Get YouTube Video').item.json.snippet.title }}"},{"id":"7f26f5a3-e695-49d1-b1e8-9260c31f1b3d","name":"description","type":"string","value":"={{ $('Get YouTube Video').item.json.snippet.description }}"},{"id":"d0594232-cb39-453c-b015-3b039c098e1f","name":"id","type":"string","value":"={{ $('Get YouTube Video').item.json.id }}"},{"id":"17b6ca08-ce89-4467-bd25-0d2d182f7a8b","name":"youtubeUrl","type":"string","value":"={{ $('Webhook').item.json.body.youtubeUrl }}"}]}},"typeVersion":3.4}],"connections":{"Webhook":{"main":[[{"node":"Get YouTube URL","type":"main","index":0}]]},"Split Out":{"main":[[{"node":"Concatenate","type":"main","index":0}]]},"Concatenate":{"main":[[{"node":"Summarize & Analyze Transcript","type":"main","index":0}]]},"gpt-4o-mini":{"ai_languageModel":[[{"node":"Summarize & Analyze Transcript","type":"ai_languageModel","index":0}]]},"Get YouTube URL":{"main":[[{"node":"YouTube Video ID","type":"main","index":0}]]},"Response Object":{"main":[[{"node":"Respond to Webhook","type":"main","index":0},{"node":"Telegram","type":"main","index":0}]]},"YouTube Video ID":{"main":[[{"node":"Get YouTube Video","type":"main","index":0}]]},"Summarize & Analyze Transcript":{"main":[[{"node":"Response Object","type":"main","index":0}]]}}}


name: AI Agent : Google calendar assistant using OpenAI
author_name: Dataki
author_username: dataki
categories: []
created_at: 2025-01-07T15:09:52.723Z
updated_at: 2025-01-07T15:09:52.723Z
url: https://n8n.io/workflows/2703
scraped_at: 2025-07-06 21:16:30
description:
  This template is a simple AI Agent that acts as a Google Calendar Assistant. 
  It is designed for beginners to have their "first AI Agent" performing common tasks and to help them understand how it works.

  For new users of n8n, AI Agents, and OpenAI:
  This template involves using an OpenAI API Key. If you are new to AI Agents, make sure to research and understand key concepts such as:
  "Tokens"** (used for API requests),
  "Tool calling"** (how the AI interacts with external tools),
  OpenAI's usage costs** (how you will be billed for API usage).

  Functionality

  It has two main functionalities:
  Create events** in a calendar
  Retrieve events** from a calendar

  How you can use it
  Everything is explained with sticky notes in the workflow. 
  It is ready-to-use: all you need to do is connect your OpenAI credentials, and you can start using the workflow.

nodes_used:
  ["@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.memoryBufferWindow"]

workflow_json:
  {"id":"ITH6r6UYtlCyUcpj","meta":{"instanceId":"b9faf72fe0d7c3be94b3ebff0778790b50b135c336412d28fd4fca2cbbf8d1f5"},"name":"AI Agent : Google calendar assistant using OpenAI","tags":[],"nodes":[{"id":"2e670a54-f789-4c8b-abba-ae35c458f5ed","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-280,0],"webhookId":"5308edc9-738b-4aae-a789-214e2392579a","parameters":{"options":{}},"typeVersion":1.1},{"id":"96bf895f-a18c-4a4c-bc26-3ec5d2372de5","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[160,820],"parameters":{"model":"gpt-4o","options":{}},"credentials":{"openAiApi":{"id":"","name":"OpenAi"}},"typeVersion":1},{"id":"270176df-9c2d-4f1a-b017-9349cb249341","name":"Window Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[580,820],"parameters":{},"typeVersion":1.3},{"id":"5cdece35-bd69-4c77-b240-963df8781d64","name":"Google Calendar - Get Events","type":"n8n-nodes-base.googleCalendarTool","position":[960,800],"parameters":{"options":{"timeMax":"={{ $fromAI('end_date') }}","timeMin":"={{ $fromAI('start_date') }}"},"calendar":{"__rl":true,"mode":"list","value":"","cachedResultName":""},"operation":"getAll","descriptionType":"manual","toolDescription":"Use this tool when you’re asked to retrieve events data."},"credentials":{"googleCalendarOAuth2Api":{"id":"","name":"Google Calendar account"}},"typeVersion":1.2},{"id":"634e6472-099c-4f0e-b9eb-67956c4881b8","name":"Google Calendar - Create events","type":"n8n-nodes-base.googleCalendarTool","position":[1380,800],"parameters":{"end":"={{ $fromAI('end_date') }} ","start":"={{ $fromAI('start_date') }} ","calendar":{"__rl":true,"mode":"list","value":"","cachedResultName":""},"descriptionType":"manual","toolDescription":"Use this Google Calendar tool when you are asked to create an event.","additionalFields":{"summary":"={{ $fromAI('event_title') }} ","attendees":[],"description":"={{ $fromAI('event_description') }} "},"useDefaultReminders":false},"credentials":{"googleCalendarOAuth2Api":{"id":"","name":"Google Calendar account"}},"typeVersion":1.2},{"id":"5c93e130-29d5-489b-84ea-3e31f5849b3a","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-380,-380],"parameters":{"color":7,"width":320,"height":560,"content":"## Chat trigger - When a message is received\n\nThis node is the **entry point of the workflow**.  \nIt triggers the workflow whenever a message is sent to the **chat interface**.\n\nOptions with n8n:\n- **Embed the chat interface** anywhere you want.\n- Use a **webhook node** instead of this node to connect with interfaces like **[Streamlit](https://docs.streamlit.io/develop/tutorials/llms/build-conversational-apps)** or **[OpenWebUI](https://docs.openwebui.com/)**.\n- Use nodes for communication platforms (**Slack**, **Teams**, **Discord**, etc.) if you know how to configure them.\n"},"typeVersion":1},{"id":"a1e850b4-d0fe-417c-8e1e-13fb4cdbb0a8","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[60,-380],"parameters":{"color":7,"width":1520,"height":560,"content":"## Tools Agent - Calendar AI Agent\n\nThis **node** configures the **AI agent** for interaction with Google Calendar.  \nIt includes the following features:\n\n- A **prompt source**: This is the user message derived from the chat input of the preceding node (`When chat message is received`).\n- A **system message**: This defines the system prompt to guide the AI agent's behavior. It incorporates the variable `{{ DateTime.local().toFormat('cccc d LLLL yyyy') }`, allowing the AI agent to determine the current date and interact with Google Calendar accordingly. For example, the agent can understand a request like \"Create an event called 'n8n workflow review' for next Tuesday.\"\n\n\nn8n nodes come with built-in **guardrails**, ensuring that if the user requests tasks outside the AI agent's setup, it may not function as intended. (Feel free to test it!)\n"},"typeVersion":1},{"id":"9b259245-5fd5-4798-973e-bc6aa15da20f","name":"Calendar AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[580,0],"parameters":{"text":"={{ $json.chatInput }}","options":{"systemMessage":"=You are a Google Calendar assistant.\nYour primary goal is to assist the user in managing their calendar effectively using two tools: Event Creation and Event Retrieval. Always base your responses on the current date: \n{{ DateTime.local().toFormat('cccc d LLLL yyyy') }}.\nGeneral Guidelines:\nIf the user's initial message is vague (e.g., \"hello\" or a generic greeting) or does not specify a request, explain your capabilities clearly:\nExample: \"Hello! I can help you manage your Google Calendar. You can ask me to create an event or retrieve event data. What would you like me to do?\"\nIf the user specifies a request in their first message, begin preparing to use the appropriate tool:\nFor event creation, gather necessary details like start date, end date, title, and description.\nFor event retrieval, ask for the date range or time period they want to query.\nTool: Event Creation\nWhen asked to create an event:\n\nRequest the start and end dates/times from the user.\nDate format: YYYY-MM-DD HH:mm:ss\nCollect the following information:\nstart_date: Exact start date and time of the event.\nend_date: Exact end date and time of the event.\nevent_title: Event title in uppercase. Suggest one if not provided.\nevent_description: Generate a brief description and present it for confirmation.\nTool: Event Retrieval\nWhen asked to retrieve events:\n\nAsk for the date range or period they are interested in. Examples:\nFor \"last week,\" retrieve events from Monday of the previous week to Friday of the same week.\nFor \"today,\" use the current date.\nFormat the date range:\nstart_date: Start date and time in YYYY-MM-DD HH:mm:ss.\nend_date: End date and time in YYYY-MM-DD HH:mm:ss.\nKey Behaviors:\nClarity: Provide a clear and helpful introduction when the user's request is unclear.\nValidation: Confirm details with the user before finalizing actions.\nAdaptation: Handle varying levels of detail in requests (e.g., \"Add a meeting for next Monday morning\" or \"Retrieve my events for this weekend\").\nProactivity: Offer suggestions to fill in missing details or clarify ambiguous inputs.\nLanguage Matching: Ensure all interactions, including event titles, descriptions, and messages, are in the user's language to provide a seamless experience."},"promptType":"define"},"typeVersion":1.7},{"id":"b902a7d0-c2ca-4ab9-9f2a-047b9ccb1678","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[60,240],"parameters":{"color":5,"width":320,"height":720,"content":"## OpenAI chat model\n\nThis node specifies the chat model used by the agent.  \nIn the template, the **default LLM is gpt-4o** for its high relevance.\n\nOther options:\n- You can **try gpt-4o-mini**, which is more cost-effective.\n- You can also choose **other LLM providers besides OpenAI**, but make sure the LLM you select **supports tool-calling**.\n"},"typeVersion":1},{"id":"c67e1e1b-ef9a-4fec-a860-4ec6b7439df6","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[460,240],"parameters":{"color":5,"width":320,"height":720,"content":"## Window buffer memory\n\nThis node manages the **memory** of the agent, specifically the **context window length** for chat history.  \nThe default is set to 5 messages.\n\nNote:  \nThe **memory** is **temporary**. If you want to **store conversations with the agent**, you should use other nodes like **Postgres chat memory**.  \nThis can be easily set up with services like **[Supabase](https://supabase.com/)**.\n"},"typeVersion":1},{"id":"bf719d53-e21b-4bd5-9443-c24d008f732b","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[860,240],"parameters":{"color":5,"width":320,"height":720,"content":"## Google Calendar - Get Events\n\nThis sub-node is a tool used by the AI agent.  \nIts purpose is to **retrieve events based on the user input**.  \nFor example: *\"Can you give me the events from last week about internal process ?\"*\n\nThe AI agent is designed to **use this tool only** when it has a **date range**.  \nIf the user hasn’t provided a date range, the **AI agent will ask the user** for it.\n\nThe **variables** `{{ $fromAI('start_date') }}` and `{{ $fromAI('end_date') }}` are **dynamically filled by the AI**.\n"},"typeVersion":1},{"id":"e94eb1f8-df42-414b-9bec-9e6991a5a832","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1260,240],"parameters":{"color":5,"width":320,"height":720,"content":"## Google Calendar - Create Events\n\nThis sub-node is a tool used by the AI agent.  \nIts purpose is to **create events based on the user input**.  \nFor example: \"Can you create an event 'Quarter revenue meeting' on [date] from [hour] to [hour] ?\"\n\nThe AI agent is designed to **use this tool only** when it has a **date range**.  \nIf the user hasn’t provided a **date range**, the AI agent will **ask the user** for it.  \nThe variables `{{ $fromAI('start_date') }}` and `{{ $fromAI('end_date') }}` are dynamically filled by the AI.\n\nBefore creating the event, the AI agent will **confirm with the user** if the **title** and **description** of the event are correct.  \nThe variables used for this are:\n- `{{ $fromAI('event_title') }}`\n- `{{ $fromAI('event_description') }}`\n"},"typeVersion":1},{"id":"707c011c-c822-4922-8ef7-c4368947d179","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[860,1000],"parameters":{"color":4,"width":720,"height":380,"content":"## Having fun with it ? Here’s how to level up this AI agent !  \n\nThis workflow demonstrates **how easily you can set up an AI agent to call tools** for you using **n8n**.  \nThe tasks here are **useful but very basic**.  \n\nIf you want to **enhance the tool-calling capabilities**, consider the following:\n\n- Explore the **\"options\"** in the Google Calendar nodes to see additional features you can use.  \n  For example, let the AI agent add attendees to events it creates.\n\n- Implement the AI agent with your **teammates and link it to each calendar**.  \n  Use a `{{ $fromAI('') }}` variable for the calendar field and refine the prompts to suit your needs.\n\n- Add **more actions** for the AI agent to perform with the **Google Calendar API**, expanding its functionality.\n"},"typeVersion":1}],"active":false,"settings":{"timezone":"Europe/Paris","callerPolicy":"workflowsFromSameOwner","executionOrder":"v1"},"versionId":"25b51038-e103-4be6-bcd1-64df4b90d4c6","connections":{"Calendar AI Agent":{"main":[[]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"Calendar AI Agent","type":"ai_languageModel","index":0}]]},"Window Buffer Memory":{"ai_memory":[[{"node":"Calendar AI Agent","type":"ai_memory","index":0}]]},"When chat message received":{"main":[[{"node":"Calendar AI Agent","type":"main","index":0}]]},"Google Calendar - Get Events":{"ai_tool":[[{"node":"Calendar AI Agent","type":"ai_tool","index":0}]]},"Google Calendar - Create events":{"ai_tool":[[{"node":"Calendar AI Agent","type":"ai_tool","index":0}]]}}}


name: 🔐🦙🤖 Private & Local Ollama Self-Hosted AI Assistant
author_name: Joseph LePage
author_username: joe
nodes_used: ["@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.lmOllama"]
categories: []
created_at: 2025-01-15T05:39:06.856Z
updated_at: 2025-01-15T05:39:06.856Z
url: https://n8n.io/workflows/2729
scraped_at: 2025-07-06 21:16:30
description:
  Transform your local N8N instance into a powerful chat interface using any local & private Ollama model, with zero cloud dependencies ☁️. This workflow creates a structured chat experience that processes messages locally through a language model chain and returns formatted responses 💬.

  How it works 🔄
  💭 Chat messages trigger the workflow
  🧠 Messages are processed through Llama 3.2 via Ollama (or any other Ollama compatible model)
  📊 Responses are formatted as structured JSON
  ⚡ Error handling ensures robust operation

  Set up steps 🛠️
  📥 Install N8N and Ollama
  ⚙️ Download Ollama 3.2 model (or other model)
  🔑 Configure Ollama API credentials
  ✨ Import and activate workflow

  This template provides a foundation for building AI-powered chat applications while maintaining full control over your data and infrastructure 🚀.

workflow_json:
  {"id":"Telr6HU0ltH7s9f7","meta":{"instanceId":"31e69f7f4a77bf465b805824e303232f0227212ae922d12133a0f96ffeab4fef"},"name":"🗨️Ollama Chat","tags":[],"nodes":[{"id":"9560e89b-ea08-49dc-924e-ec8b83477340","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[280,60],"webhookId":"4d06a912-2920-489c-a33c-0e3ea0b66745","parameters":{"options":{}},"typeVersion":1.1},{"id":"c7919677-233f-4c48-ba01-ae923aef511e","name":"Basic LLM Chain","type":"@n8n/n8n-nodes-langchain.chainLlm","onError":"continueErrorOutput","position":[640,60],"parameters":{"text":"=Provide the users prompt and response as a JSON object with two fields:\n- Prompt\n- Response\n\nAvoid any preample or further explanation.\n\nThis is the question: {{ $json.chatInput }}","promptType":"define"},"typeVersion":1.5},{"id":"b9676a8b-f790-4661-b8b9-3056c969bdf5","name":"Ollama Model","type":"@n8n/n8n-nodes-langchain.lmOllama","position":[740,340],"parameters":{"model":"llama3.2:latest","options":{}},"credentials":{"ollamaApi":{"id":"IsSBWGtcJbjRiKqD","name":"Ollama account"}},"typeVersion":1},{"id":"61dfcda5-083c-43ff-8451-b2417f1e4be4","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-380,-380],"parameters":{"color":4,"width":520,"height":860,"content":"# 🦙 Ollama Chat Workflow\n\nA simple N8N workflow that integrates Ollama LLM for chat message processing and returns a structured JSON object.\n\n## Overview\nThis workflow creates a chat interface that processes messages using the Llama 3.2 model through Ollama. When a chat message is received, it gets processed through a basic LLM chain and returns a response.\n\n## Components\n- **Trigger Node**\n- **Processing Node**\n- **Model Node**\n- **JSON to Object Node**\n- **Structured Response Node**\n- **Error Response Node**\n\n## Workflow Structure\n1. The chat trigger node receives incoming messages\n2. Messages are passed to the Basic LLM Chain\n3. The Ollama Model processes the input using Llama 3.2\n4. Responses are returned through the chain\n\n## Prerequisites\n- N8N installation\n- Ollama setup with Llama 3.2 model\n- Valid Ollama API credentials\n\n## Configuration\n1. Set up the Ollama API credentials in N8N\n2. Ensure the Llama 3.2 model is available in your Ollama installation\n\n"},"typeVersion":1},{"id":"64f60ee1-7870-461e-8fac-994c9c08b3f9","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[340,280],"parameters":{"width":560,"height":200,"content":"## Model Node\n- Name: Ollama Model\n- Type: LangChain Ollama Integration\n- Model: llama3.2:latest\n- Purpose: Provides the language model capabilities"},"typeVersion":1},{"id":"bb46210d-450c-405b-a451-42458b3af4ae","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[200,-160],"parameters":{"color":6,"width":280,"height":400,"content":"## Trigger Node\n- Name: When chat message received\n- Type: Chat Trigger\n- Purpose: Initiates the workflow when a new chat message arrives"},"typeVersion":1},{"id":"7f21b9e6-6831-4117-a2e2-9c9fb6edc492","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[520,-380],"parameters":{"color":3,"width":500,"height":620,"content":"## Processing Node\n- Name: Basic LLM Chain\n- Type: LangChain LLM Chain\n- Purpose: Handles the processing of messages through the language model and returns a structured JSON object.\n\n"},"typeVersion":1},{"id":"871bac4e-002f-4a1d-b3f9-0b7d309db709","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[560,-200],"parameters":{"color":7,"width":420,"height":200,"content":"### Prompt (Change this for your use case)\nProvide the users prompt and response as a JSON object with two fields:\n- Prompt\n- Response\n\n\nAvoid any preample or further explanation.\nThis is the question: {{ $json.chatInput }}"},"typeVersion":1},{"id":"c9e1b2af-059b-4330-a194-45ae0161aa1c","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1060,-280],"parameters":{"color":5,"width":420,"height":520,"content":"## JSON to Object Node\n- Type: Set Node\n- Purpose: A node designed to transform and structure response data in a specific format before sending it through the workflow. It operates in manual mapping mode to allow precise control over the response format.\n\n**Key Features**\n- Manual field mapping capabilities\n- Object transformation and restructuring\n- Support for JSON data formatting\n- Field-to-field value mapping\n- Includes option to add additional input fields\n"},"typeVersion":1},{"id":"3fb912b8-86ac-42f7-a19c-45e59898a62e","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[1520,-180],"parameters":{"color":6,"width":460,"height":420,"content":"## Structured Response Node\n- Type: Set Node\n- Purpose: Controls how the workflow responds to users chat prompt.\n\n**Response Mode**\n- Manual Mapping: Allows custom formatting of response data\n- Fields to Set: Specify which data fields to include in response\n\n"},"typeVersion":1},{"id":"fdfd1a5c-e1a6-4390-9807-ce665b96b9ae","name":"Structured Response","type":"n8n-nodes-base.set","position":[1700,60],"parameters":{"options":{},"assignments":{"assignments":[{"id":"13c4058d-2d50-46b7-a5a6-c788828a1764","name":"text","type":"string","value":"=Your prompt was: {{ $json.response.Prompt }}\n\nMy response is: {{ $json.response.Response }}\n\nThis is the JSON object:\n\n{{ $('Basic LLM Chain').item.json.text }}"}]}},"typeVersion":3.4},{"id":"76baa6fc-72dd-41f9-aef9-4fd718b526df","name":"Error Response","type":"n8n-nodes-base.set","position":[1460,660],"parameters":{"options":{},"assignments":{"assignments":[{"id":"13c4058d-2d50-46b7-a5a6-c788828a1764","name":"text","type":"string","value":"=There was an error."}]}},"typeVersion":3.4},{"id":"bde3b9df-af55-451b-b287-1b5038f9936c","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[1240,280],"parameters":{"color":2,"width":540,"height":560,"content":"## Error Response Node\n- Type: Set Node\n- Purpose: Handles error cases when the Basic LLM Chain fails to process the chat message properly. It provides a fallback response mechanism to ensure the workflow remains robust.\n\n**Key Features**\n- Provides default error messaging\n- Maintains consistent response structure\n- Connects to the error output branch of the LLM Chain\n- Ensures graceful failure handling\n\nThe Error Response node activates when the main processing chain encounters issues, ensuring users always receive feedback even when errors occur in the language model processing.\n"},"typeVersion":1},{"id":"b9b2ab8d-9bea-457a-b7bf-51c8ef0de69f","name":"JSON to Object","type":"n8n-nodes-base.set","position":[1220,60],"parameters":{"options":{},"assignments":{"assignments":[{"id":"12af1a54-62a2-44c3-9001-95bb0d7c769d","name":"response","type":"object","value":"={{ $json.text }}"}]}},"typeVersion":3.4}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"5175454a-91b7-4c57-890d-629bd4e8d2fd","connections":{"Ollama Model":{"ai_languageModel":[[{"node":"Basic LLM Chain","type":"ai_languageModel","index":0}]]},"JSON to Object":{"main":[[{"node":"Structured Response","type":"main","index":0}]]},"Basic LLM Chain":{"main":[[{"node":"JSON to Object","type":"main","index":0}],[{"node":"Error Response","type":"main","index":0}]]},"When chat message received":{"main":[[{"node":"Basic LLM Chain","type":"main","index":0}]]}}}


name: 🤖 Telegram Messaging Agent for Text/Audio/Images
author_name: Joseph LePage
author_username: joe
categories: []
created_at: 2025-01-18T18:10:46.426Z
updated_at: 2025-01-18T18:10:46.426Z
url: https://n8n.io/workflows/2751
scraped_at: 2025-07-06 21:16:30
description:
  🤖 This n8n workflow creates an intelligent Telegram bot that processes multiple types of messages and provides automated responses using AI capabilities. The bot serves as a personal assistant that can handle text, voice messages, and images through a sophisticated processing pipeline.

  Core Components

  Message Reception and Validation 📥
  🔄 Implements webhook-based message reception for real-time processing
  🔐 Features a robust user validation system that verifies sender credentials
  🔀 Supports both testing and production webhook endpoints for development flexibility

  Message Processing Pipeline ⚡
  🔄 Uses a smart router to detect and categorize incoming message types
  📝 Processes three main message formats:
    💬 Text messages
    🎤 Voice recordings
    📸 Images with captions

  AI Integration 🧠
  🤖 Leverages OpenAI's GPT-4 for message classification and processing
  🗣️ Incorporates voice transcription capabilities for audio messages
  👁️ Features image analysis using GPT-4 Vision API for processing visual content

  Technical Architecture

  Webhook Management 🔌
  🌐 Maintains separate endpoints for testing and production environments
  📊 Implements automatic webhook status monitoring
  ⚡ Provides real-time webhook configuration updates

  Error Handling ⚠️
  🔍 Features comprehensive error detection and reporting
  🔄 Implements fallback mechanisms for unprocessable messages
  💬 Provides user feedback for failed operations

  Message Classification System 📋
  🏷️ Categorizes incoming messages into tasks and general conversation
  🔀 Implements separate processing paths for different message types
  🧩 Maintains context awareness across message processing

  Security Features

  User Authentication 🔒
  ✅ Validates user credentials against predefined parameters
  👤 Implements first name, last name, and user ID verification
  🚫 Restricts access to authorized users only

  Response System

  Intelligent Responses 💡
  🤖 Generates contextual responses based on message classification

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.telegram","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.openAi","@n8n/n8n-nodes-langchain.textClassifier"]

workflow_json:
  {"id":"8jDt77Y4FaV6ARYG","meta":{"instanceId":"31e69f7f4a77bf465b805824e303232f0227212ae922d12133a0f96ffeab4fef"},"name":"🤖 Telegram Messaging Agent for Text/Audio/Images","tags":[],"nodes":[{"id":"1656be7a-7a27-47f3-b511-3634a65a97a2","name":"Check User & Chat ID","type":"n8n-nodes-base.if","position":[100,160],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"5fe3c0d8-bd61-4943-b152-9e6315134520","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $('Listen for Telegram Events').item.json.body.message.from.first_name }}","rightValue":"={{ $json.first_name }}"},{"id":"98a0ea91-0567-459c-bbce-06abc14a49ce","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $('Listen for Telegram Events').item.json.body.message.from.last_name }}","rightValue":"={{ $json.last_name }}"},{"id":"18a96c1f-f2a0-4a2a-b789-606763df4423","operator":{"type":"number","operation":"equals"},"leftValue":"={{ $('Listen for Telegram Events').item.json.body.message.from.id }}","rightValue":"={{ $json.id }}"}]},"looseTypeValidation":"="},"typeVersion":2.2},{"id":"73b0fedb-eb82-4464-a08f-397a3fe69480","name":"Error message","type":"n8n-nodes-base.telegram","position":[320,440],"parameters":{"text":"=Unable to process your message.","chatId":"={{ $json.body.message.chat.id }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"a3dc143b-cf3c-4416-bf43-0ca75cbde6c9","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-380,-20],"parameters":{"width":929,"height":652,"content":"# Receive Telegram Message with Webhook"},"typeVersion":1},{"id":"c80dae1e-dd20-4632-a00c-9c6290540f22","name":"Listen for Telegram Events","type":"n8n-nodes-base.webhook","position":[-320,160],"webhookId":"b4ed4c80-a655-4ff2-87d6-febd5280d343","parameters":{"path":"your-endpoint","options":{"binaryPropertyName":"data"},"httpMethod":"POST"},"typeVersion":2},{"id":"6010dacf-1ed6-413c-adf9-146397e16b09","name":"Set Webhook Test URL","type":"n8n-nodes-base.httpRequest","position":[260,-260],"parameters":{"url":"=https://api.telegram.org/{{ $json.token }}/setWebhook","options":{},"sendQuery":true,"queryParameters":{"parameters":[{"name":"url","value":"={{ $json.test_url }}"}]}},"typeVersion":4.2},{"id":"65f8d945-12bb-4ae3-bd83-3b892a36afb9","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-380,-580],"parameters":{"color":3,"width":1638,"height":532,"content":"# Telegram Webhook Tools\n\n## Setting your Telegram Bot WebHook the Easy Way\n"},"typeVersion":1},{"id":"8e3268e9-dc7c-4edd-b5e8-716de5d2ffb3","name":"Get Telegram Webhook Info","type":"n8n-nodes-base.httpRequest","position":[-240,-260],"parameters":{"url":"=https://api.telegram.org/{{ $json.token }}/getWebhookInfo","options":{}},"typeVersion":4.2},{"id":"e31e176f-2ebd-4cd1-a160-2cc5f254ca6d","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[580,-20],"parameters":{"color":4,"width":1113,"height":429,"content":"# Process Audio"},"typeVersion":1},{"id":"b8b10cd9-7a41-4b21-853c-b2123918ab8d","name":"Image Schema","type":"n8n-nodes-base.set","position":[660,1060],"parameters":{"options":{},"assignments":{"assignments":[{"id":"17989eb0-feca-4631-b5c8-34b1d4a6c72b","name":"image_file_id","type":"string","value":"={{ $json.body.message.photo.last().file_id }}"},{"id":"9317d7ae-dffd-4b1f-9a9c-b3cc4f1e0dd3","name":"caption","type":"string","value":"={{ $json.body.message.caption }}"}]}},"typeVersion":3.4},{"id":"9a7b9e4c-7a81-451a-887a-b7b3f658ae6e","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[580,900],"parameters":{"color":6,"width":1289,"height":432,"content":"# Process Image"},"typeVersion":1},{"id":"800da6c7-8d03-4932-a081-f35ce01c8dd7","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-1200,-580],"parameters":{"color":7,"width":800,"height":860,"content":"# How to set up a Telegram Bot WebHook\n\n## WebHook Setup Process\n\n**Basic Concept**\nA WebHook allows your Telegram bot to automatically receive updates instead of manually polling the Bot API.\n\n**Setup Method**\nTo set a WebHook, make a GET request using this URL format:\n```\nhttps://api.telegram.org/bot{my_bot_token}/setWebhook?url={url_to_send_updates_to}\n```\nWhere:\n- `my_bot_token`: Your bot token from BotFather\n- `url_to_send_updates_to`: Your HTTPS endpoint that handles bot updates\n\n\n**Verification**\nTo verify the WebHook setup, use:\n```\nhttps://api.telegram.org/bot{my_bot_token}/getWebhookInfo\n```\n\nA successful response looks like:\n```json\n{\n \"ok\": true,\n \"result\": {\n   \"url\": \"https://www.example.com/my-telegram-bot/\",\n   \"has_custom_certificate\": false,\n   \"pending_update_count\": 0,\n   \"max_connections\": 40\n }\n}\n```\n\n\nThis method provides a simple and efficient way to handle Telegram bot updates automatically through webhooks rather than manual polling."},"typeVersion":1},{"id":"cd09daf9-ac74-4e86-9d74-875d78f466f0","name":"gpt-4o-mini","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1080,260],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"jEMSvKmtYfzAkhe6","name":"OpenAi account"}},"typeVersion":1},{"id":"4c69533c-e4e7-4667-baf8-7ca1ed36b150","name":"Get Audio File","type":"n8n-nodes-base.telegram","position":[660,100],"parameters":{"fileId":"={{ $json.body.message.voice.file_id }}","resource":"file"},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"0b15b158-88ec-45ba-ae70-fd55a9a72ea3","name":"Get Image","type":"n8n-nodes-base.telegram","position":[860,1060],"parameters":{"fileId":"={{ $json.image_file_id }}","resource":"file"},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"081ec871-6cac-4945-9c1b-97bb87489688","name":"Analyze Image","type":"@n8n/n8n-nodes-langchain.openAi","position":[1460,1060],"parameters":{"modelId":{"__rl":true,"mode":"list","value":"gpt-4o-mini","cachedResultName":"GPT-4O-MINI"},"options":{},"resource":"image","inputType":"base64","operation":"analyze"},"credentials":{"openAiApi":{"id":"jEMSvKmtYfzAkhe6","name":"OpenAi account"}},"typeVersion":1.6},{"id":"072c21fc-d125-4078-b151-9c2fd5a4802c","name":"Transcribe Recording","type":"@n8n/n8n-nodes-langchain.openAi","position":[860,100],"parameters":{"options":{},"resource":"audio","operation":"transcribe","binaryPropertyName":"=data"},"credentials":{"openAiApi":{"id":"jEMSvKmtYfzAkhe6","name":"OpenAi account"}},"typeVersion":1.6},{"id":"b74e2181-8bf2-43a5-b4d4-d24112989b81","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[580,440],"parameters":{"color":5,"width":1113,"height":429,"content":"# Process Text"},"typeVersion":1},{"id":"8f44b159-07ff-4805-82ad-d8aeed1f9f68","name":"gpt-4o-mini1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1080,720],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"jEMSvKmtYfzAkhe6","name":"OpenAi account"}},"typeVersion":1},{"id":"666ed1b9-475e-44bf-a884-1ddf58c6c6af","name":"Test Webhook Status","type":"n8n-nodes-base.telegram","position":[460,-260],"parameters":{"text":"={{ $json.description }} for Testing","chatId":"=1234567891","additionalFields":{}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"2a1174a2-2eae-4cf5-ba48-a58a479956bf","name":"Production Webhook Status","type":"n8n-nodes-base.telegram","position":[980,-260],"parameters":{"text":"={{ $json.description }} for Production","chatId":"=1234567891","additionalFields":{}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"210b6df9-e799-409f-b78f-953bffbb37db","name":"Set Webhook Production URL","type":"n8n-nodes-base.httpRequest","position":[780,-260],"parameters":{"url":"=https://api.telegram.org/{{ $json.token }}/setWebhook","options":{},"sendQuery":true,"queryParameters":{"parameters":[{"name":"url","value":"={{ $json.production_url }}"}]}},"typeVersion":4.2},{"id":"5dc6642c-3557-47bb-b012-b353a0d10ca0","name":"Edit Fields","type":"n8n-nodes-base.set","position":[860,560],"parameters":{"options":{},"assignments":{"assignments":[{"id":"b37b48ba-8fef-4e6c-bbca-73e6c2e1e0a8","name":"text","type":"string","value":"={{ $json.body.message.text }}"}]}},"typeVersion":3.4},{"id":"cd715b79-765e-4605-84d6-963d9889c922","name":"Audio Task Message","type":"n8n-nodes-base.telegram","position":[1460,40],"parameters":{"text":"=Task message: <i>{{ $json.text }}</i>","chatId":"={{ $('Listen for Telegram Events').item.json.body.message.chat.id }}","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"9845b3e6-8c0f-4194-8442-5648147f905e","name":"Audio Other Message","type":"n8n-nodes-base.telegram","position":[1460,220],"parameters":{"text":"=Other message: <i>{{ $json.text }}</i>","chatId":"={{ $('Listen for Telegram Events').item.json.body.message.chat.id }}","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"0184b872-27a1-48dd-8e37-4fdaae7241cd","name":"Text Task Message","type":"n8n-nodes-base.telegram","position":[1460,500],"parameters":{"text":"=Task message: <i>{{ $json.text }}</i>","chatId":"={{ $('Listen for Telegram Events').item.json.body.message.chat.id }}","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"7d90fb9b-b2b5-48eb-a6f2-7f953fe6ee52","name":"Text Other Message","type":"n8n-nodes-base.telegram","position":[1460,680],"parameters":{"text":"=Other message: <i>{{ $json.text }}</i>","chatId":"={{ $('Listen for Telegram Events').item.json.body.message.chat.id }}","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"c9b9f6d2-c4c4-44b9-a929-9bc0552e8e45","name":"Image Message","type":"n8n-nodes-base.telegram","position":[1660,1060],"parameters":{"text":"={{ $json.content }}","chatId":"={{ $('Listen for Telegram Events').item.json.body.message.chat.id }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"bfc69b30-4bab-459d-bbe1-42e540275582","name":"Convert to Image File","type":"n8n-nodes-base.convertToFile","position":[1260,1060],"parameters":{"options":{"fileName":"={{ $json.result.file_path }}"},"operation":"toBinary","sourceProperty":"data"},"typeVersion":1.1},{"id":"f78d54c3-aa00-4e82-bfb1-f3131182940c","name":"Extract from File to Base64","type":"n8n-nodes-base.extractFromFile","position":[1060,1060],"parameters":{"options":{},"operation":"binaryToPropery"},"typeVersion":1},{"id":"735bb735-6b24-4bbd-8d3f-aec6cd383383","name":"Text Classifier Audio","type":"@n8n/n8n-nodes-langchain.textClassifier","position":[1060,100],"parameters":{"options":{},"inputText":"={{ $json.text }}","categories":{"categories":[{"category":"task","description":"If the message is about about creating a task/todo"},{"category":"other","description":"If the message is not about creating a task/todo "}]}},"typeVersion":1},{"id":"be7f49da-f88e-4803-95ef-fb7e2ff2d2ed","name":"Text Classifier","type":"@n8n/n8n-nodes-langchain.textClassifier","position":[1060,560],"parameters":{"options":{},"inputText":"={{ $json.text }}","categories":{"categories":[{"category":"task","description":"If the message is about about creating a task/todo"},{"category":"other","description":"If the message is not about creating a task/todo "}]}},"typeVersion":1},{"id":"33eab7d8-5b90-4533-8799-fb4ae32fc6c5","name":"Telegram Token & Webhooks","type":"n8n-nodes-base.set","position":[380,-540],"parameters":{"options":{},"assignments":{"assignments":[{"id":"87811892-85f5-4578-a149-3edd94d3815a","name":"token","type":"string","value":"bot[your-telegram-bot-token]"},{"id":"d2b9ab83-44ad-4741-aac9-1feed974c015","name":"test_url","type":"string","value":"https://[your-url]/webhook-test/[your-endpoint]"},{"id":"0c671fbf-aa2c-42ef-9e8b-398ac38358d0","name":"production_url","type":"string","value":"https://[your-url]/webhook/[your-endpoint]"}]}},"typeVersion":3.4},{"id":"65d9568e-0504-4c7d-ac05-0b7b4c52a6b2","name":"Get Webhook Status","type":"n8n-nodes-base.telegram","position":[-40,-260],"parameters":{"text":"={{ JSON.stringify($json.result, null, 2)  }}","chatId":"=1234567891","additionalFields":{}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"04669db1-3a74-4404-9b5f-9b8554b1059e","name":"Validation","type":"n8n-nodes-base.set","position":[-100,160],"parameters":{"options":{},"assignments":{"assignments":[{"id":"0cea6da1-652a-4c1e-94c3-30608ced90f8","name":"first_name","type":"string","value":"First Name"},{"id":"b90280c6-3e36-49ca-9e7e-e15c42d256cc","name":"last_name","type":"string","value":"Last Name"},{"id":"f6d86283-16ca-447e-8427-7d3d190babc0","name":"id","type":"number","value":12345678999}]}},"typeVersion":3.4},{"id":"7f9935cb-4ca6-40cf-99c5-96c5a1f4ca91","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-160,100],"parameters":{"color":7,"width":420,"height":260,"content":"## Validate Telegram User\n"},"typeVersion":1},{"id":"fa6c87eb-5f96-4e26-a1bb-60dae902186c","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-320,-320],"parameters":{"color":7,"width":460,"height":240,"content":"## Webhook Status"},"typeVersion":1},{"id":"96536ad2-e607-448e-a368-e4e8c7578b57","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[200,-320],"parameters":{"color":7,"width":460,"height":240,"content":"## Set Webhook for Testing"},"typeVersion":1},{"id":"a58c16d5-0c08-4ee6-a3fe-b9fdbd62eb8b","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[720,-320],"parameters":{"color":7,"width":480,"height":240,"content":"## Set Webhook for Production"},"typeVersion":1},{"id":"158bf4d2-aac9-4a1a-b319-1a4766cdeaca","name":"Message Router","type":"n8n-nodes-base.switch","position":[320,160],"parameters":{"rules":{"values":[{"outputKey":"audio","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"operator":{"type":"object","operation":"exists","singleValue":true},"leftValue":"={{ $json.body.message.voice }}","rightValue":""}]},"renameOutput":true},{"outputKey":"text","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"342f0883-d959-44a2-b80d-379e39c76218","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $json.body.message.text }}","rightValue":""}]},"renameOutput":true},{"outputKey":"image","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"ded3a600-f861-413a-8892-3fc5ea935ecb","operator":{"type":"array","operation":"exists","singleValue":true},"leftValue":"={{ $json.body.message.photo }}","rightValue":""}]},"renameOutput":true}]},"options":{"fallbackOutput":"extra"}},"typeVersion":3.2}],"active":true,"settings":{"executionOrder":"v1"},"versionId":"91b5de12-0ada-4125-b5ce-3ffb4dc9fa9b","connections":{"Get Image":{"main":[[{"node":"Extract from File to Base64","type":"main","index":0}]]},"Validation":{"main":[[{"node":"Check User & Chat ID","type":"main","index":0}]]},"Edit Fields":{"main":[[{"node":"Text Classifier","type":"main","index":0}]]},"gpt-4o-mini":{"ai_languageModel":[[{"node":"Text Classifier Audio","type":"ai_languageModel","index":0}]]},"Image Schema":{"main":[[{"node":"Get Image","type":"main","index":0}]]},"gpt-4o-mini1":{"ai_languageModel":[[{"node":"Text Classifier","type":"ai_languageModel","index":0}]]},"Analyze Image":{"main":[[{"node":"Image Message","type":"main","index":0}]]},"Image Message":{"main":[[]]},"Get Audio File":{"main":[[{"node":"Transcribe Recording","type":"main","index":0}]]},"Message Router":{"main":[[{"node":"Get Audio File","type":"main","index":0}],[{"node":"Edit Fields","type":"main","index":0}],[{"node":"Image Schema","type":"main","index":0}],[{"node":"Error message","type":"main","index":0}]]},"Text Classifier":{"main":[[{"node":"Text Task Message","type":"main","index":0}],[{"node":"Text Other Message","type":"main","index":0}]]},"Check User & Chat ID":{"main":[[{"node":"Message Router","type":"main","index":0}],[{"node":"Error message","type":"main","index":0}]]},"Set Webhook Test URL":{"main":[[{"node":"Test Webhook Status","type":"main","index":0}]]},"Transcribe Recording":{"main":[[{"node":"Text Classifier Audio","type":"main","index":0}]]},"Convert to Image File":{"main":[[{"node":"Analyze Image","type":"main","index":0}]]},"Text Classifier Audio":{"main":[[{"node":"Audio Task Message","type":"main","index":0}],[{"node":"Audio Other Message","type":"main","index":0}]]},"Get Telegram Webhook Info":{"main":[[{"node":"Get Webhook Status","type":"main","index":0}]]},"Telegram Token & Webhooks":{"main":[[{"node":"Set Webhook Production URL","type":"main","index":0},{"node":"Set Webhook Test URL","type":"main","index":0},{"node":"Get Telegram Webhook Info","type":"main","index":0}]]},"Listen for Telegram Events":{"main":[[{"node":"Validation","type":"main","index":0}]]},"Set Webhook Production URL":{"main":[[{"node":"Production Webhook Status","type":"main","index":0}]]},"Extract from File to Base64":{"main":[[{"node":"Convert to Image File","type":"main","index":0}]]}}}


name: RAG Chatbot for Company Documents using Google Drive and Gemini
author_name: Mihai Farcas
author_username: mihailtd
categories: []
created_at: 2025-01-20T00:06:27.623Z
updated_at: 2025-01-20T00:06:27.623Z
url: https://n8n.io/workflows/2753
scraped_at: 2025-07-06 21:16:30
description:
  This workflow implements a Retrieval Augmented Generation (RAG) chatbot that answers employee questions based on company documents stored in Google Drive. It automatically indexes new or updated documents in a Pinecone vector database, allowing the chatbot to provide accurate and up-to-date information. The workflow uses Google's Gemini AI for both embeddings and response generation.

  How it works
  The workflow uses two Google Drive Trigger nodes: one for detecting new files added to a specified Google Drive folder, and another for detecting file updates in that same folder.
  Automated Indexing: When a new or updated document is detected
  The Google Drive node downloads the file.
  The Default Data Loader node loads the document content.
  The Recursive Character Text Splitter node breaks the document into smaller text chunks.
  The Embeddings Google Gemini node generates embeddings for each text chunk using the text-embedding-004 model.
  The Pinecone Vector Store node indexes the text chunks and their embeddings in a specified Pinecone index.
  7.The Chat Trigger node receives user questions through a chat interface. The user's question is passed to an AI Agent node.
  The AI Agent node uses a Vector Store Tool node, linked to a Pinecone Vector Store node in query mode, to retrieve relevant text chunks from Pinecone based on the user's question.
  The AI Agent sends the retrieved information and the user's question to the Google Gemini Chat Model (gemini-pro).
  The Google Gemini Chat Model generates a comprehensive and informative answer based on the retrieved documents.
  A Window Buffer Memory node connected to the AI Agent provides short-term memory, allowing for more natural and context-aware conversations.

  Set up steps

  Google Cloud Project and Vertex AI API:
  Create a Google Cloud project.
  Enable the Vertex AI API for your project.
  Google AI API Key:
  Obtain a Google AI API key from Google AI Studio.
  Pinecone Account:
  Create a free account on the Pinecone website.
  Obtain your API key from your Pinecone dashboard.
  Create an index named company-files in your Pinecone project.
  Google Drive:
  Create a dedicated folder in your Google Drive where company documents will be stored.
  Credentials in n8n: Configure credentials in your n8n environment for:
  Google Drive OAuth2
  Google Gemini(PaLM) Api (using your Google AI API key)
  Pinecone API (using your Pinecone API key)
  Import the Workflow:
  Import this workflow into your n8n instance.
  Configure the Workflow:
  Update both Google Drive Trigger nodes to watch the specific folder you created in your Google Drive.
  Configure the Pinecone Vector Store nodes to use your company-files index.

nodes_used:
  ["n8n-nodes-base.googleDrive","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.memoryBufferWindow","@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","@n8n/n8n-nodes-langchain.vectorStorePinecone","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.embeddingsGoogleGemini","@n8n/n8n-nodes-langchain.lmChatGoogleGemini","@n8n/n8n-nodes-langchain.toolVectorStore"]

workflow_json:
  {"id":"7cXvgkl9170QXzT2","meta":{"instanceId":"69133932b9ba8e1ef14816d0b63297bb44feb97c19f759b5d153ff6b0c59e18d","templateCredsSetupCompleted":true},"name":"RAG Workflow For Company Documents stored in Google Drive","tags":[],"nodes":[{"id":"753455a3-ddc8-4a74-b043-70a0af38ff9e","name":"Pinecone Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStorePinecone","position":[680,0],"parameters":{"mode":"insert","options":{},"pineconeIndex":{"__rl":true,"mode":"list","value":"company-files","cachedResultName":"company-files"}},"credentials":{"pineconeApi":{"id":"bQTNry52ypGLqt47","name":"PineconeApi account"}},"typeVersion":1},{"id":"a7c8fa7f-cad2-4497-a295-30aa2e98cacc","name":"Embeddings Google Gemini","type":"@n8n/n8n-nodes-langchain.embeddingsGoogleGemini","position":[640,280],"parameters":{"modelName":"models/text-embedding-004"},"credentials":{"googlePalmApi":{"id":"jLOqyTR4yTT1nYKi","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"215f0519-4359-4e4b-a90c-7e54b1cc52b5","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[840,220],"parameters":{"options":{},"dataType":"binary","binaryMode":"specificField"},"typeVersion":1},{"id":"863d3d1d-1621-406e-8320-688f64b07b09","name":"Recursive Character Text Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","position":[820,420],"parameters":{"options":{},"chunkOverlap":100},"typeVersion":1},{"id":"5af1efb1-ea69-466e-bb3b-2b7e6b1ceef7","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[420,840],"parameters":{"options":{"systemMessage":"You are a helpful HR assistant designed to answer employee questions based on company policies.\n\nRetrieve relevant information from the provided internal documents and provide a concise, accurate, and informative answer to the employee's question.\n\nUse the tool called \"company_documents_tool\" to retrieve any information from the company's documents.\n\nIf the answer cannot be found in the provided documents, respond with \"I cannot find the answer in the available resources.\""}},"typeVersion":1.7},{"id":"825632ac-1edf-4e63-948d-b1a498b2b962","name":"Vector Store Tool","type":"@n8n/n8n-nodes-langchain.toolVectorStore","position":[820,1060],"parameters":{"name":"company_documents_tool","description":"Retrieve information from any company documents"},"typeVersion":1},{"id":"72d2f685-bcc3-4e62-a5e3-72c0fe65f8e8","name":"Pinecone Vector Store (Retrieval)","type":"@n8n/n8n-nodes-langchain.vectorStorePinecone","position":[720,1240],"parameters":{"options":{},"pineconeIndex":{"__rl":true,"mode":"list","value":"company-files","cachedResultName":"company-files"}},"credentials":{"pineconeApi":{"id":"bQTNry52ypGLqt47","name":"PineconeApi account"}},"typeVersion":1},{"id":"eeff81cb-6aec-4e7f-afe0-432d87085fb2","name":"Embeddings Google Gemini (retrieval)","type":"@n8n/n8n-nodes-langchain.embeddingsGoogleGemini","position":[700,1400],"parameters":{"modelName":"models/text-embedding-004"},"credentials":{"googlePalmApi":{"id":"jLOqyTR4yTT1nYKi","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"8bb6ebb1-1deb-498b-8da4-b809a736e097","name":"Download File From Google Drive","type":"n8n-nodes-base.googleDrive","position":[460,0],"parameters":{"fileId":{"__rl":true,"mode":"id","value":"={{ $json.id }}"},"options":{"fileName":"={{ $json.name }}"},"operation":"download"},"credentials":{"googleDriveOAuth2Api":{"id":"uixLsi5TmrfwXPeB","name":"Google Drive account"}},"typeVersion":3},{"id":"bd83bacf-dff1-4b7c-af5c-b249fb16c113","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[420,660],"parameters":{"content":"## Chat with company documents"},"typeVersion":1},{"id":"7b90daab-0fb2-4c8a-93e6-b138bb04f282","name":"Google Drive File Updated","type":"n8n-nodes-base.googleDriveTrigger","position":[140,140],"parameters":{"event":"fileUpdated","options":{},"pollTimes":{"item":[{"mode":"everyMinute"}]},"triggerOn":"specificFolder","folderToWatch":{"__rl":true,"mode":"list","value":"1evDIoHePhjw_LgVFZXSZyK1sZm2GHp9W","cachedResultUrl":"https://drive.google.com/drive/folders/1evDIoHePhjw_LgVFZXSZyK1sZm2GHp9W","cachedResultName":"INNOVI PRO"}},"credentials":{"googleDriveOAuth2Api":{"id":"uixLsi5TmrfwXPeB","name":"Google Drive account"}},"typeVersion":1},{"id":"3a6c6cef-7a19-42ef-8092-eaf57dae4cdd","name":"Google Drive File Created","type":"n8n-nodes-base.googleDriveTrigger","position":[140,-120],"parameters":{"event":"fileCreated","options":{"fileType":"all"},"pollTimes":{"item":[{"mode":"everyMinute"}]},"triggerOn":"specificFolder","folderToWatch":{"__rl":true,"mode":"list","value":"1evDIoHePhjw_LgVFZXSZyK1sZm2GHp9W","cachedResultUrl":"https://drive.google.com/drive/folders/1evDIoHePhjw_LgVFZXSZyK1sZm2GHp9W","cachedResultName":"INNOVI PRO"}},"credentials":{"googleDriveOAuth2Api":{"id":"uixLsi5TmrfwXPeB","name":"Google Drive account"}},"typeVersion":1},{"id":"1e38f1c8-7bd0-4eeb-addc-62339582d350","name":"Window Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[500,1140],"parameters":{},"typeVersion":1.3},{"id":"4b0ab858-99b1-4337-8c5c-a223519e3662","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[80,840],"webhookId":"5f1c0c82-0ff9-40c7-9e2e-b1a96ffe24cd","parameters":{"options":{}},"typeVersion":1.1},{"id":"bfb684d1-e5c1-41da-8305-b2606a2eade6","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[440,-240],"parameters":{"width":320,"content":"## Add docuemnts to vector store when updating or creating new documents in Google Drive"},"typeVersion":1},{"id":"8f627ec6-4b3f-43ad-a4a3-e2b199a7fe58","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[320,1140],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash-exp"},"credentials":{"googlePalmApi":{"id":"jLOqyTR4yTT1nYKi","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"f2133a06-0088-46de-9f74-a3f9fe478f98","name":"Google Gemini Chat Model (retrieval)","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[1080,1240],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash-exp"},"credentials":{"googlePalmApi":{"id":"jLOqyTR4yTT1nYKi","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"578deb96-8393-4850-9757-fa97b2bc9992","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-540,220],"parameters":{"width":420,"height":720,"content":"## Set up steps\n\n1. Google Cloud Project and Vertex AI API:\n* Create a Google Cloud project.\n* Enable the Vertex AI API for your project.\n2. Google AI API Key:\n* Obtain a Google AI API key from Google AI Studio.\n3. Pinecone Account:\n* Create a free account on the Pinecone website.\nObtain your API key from your Pinecone dashboard.\n* Create an index named company-files in your Pinecone project.\n4. Google Drive:\n* Create a dedicated folder in your Google Drive where company documents will be stored.\n5. Credentials in n8n: Configure credentials in your n8n environment for:\n* Google Drive OAuth2\n* Google Gemini(PaLM) Api (using your Google AI API key)\n* Pinecone API (using your Pinecone API key)\n5. Import the Workflow:\n* Import this workflow into your n8n instance.\n6. Configure the Workflow:\n* Update both Google Drive Trigger nodes to watch the specific folder you created in your Google Drive.\n* Configure the Pinecone Vector Store nodes to use your company-files index."},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"33b252fb-5d87-4a29-a0a7-97308140699c","connections":{"AI Agent":{"main":[[]]},"Vector Store Tool":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"Pinecone Vector Store","type":"ai_document","index":0}]]},"Window Buffer Memory":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"Pinecone Vector Store":{"main":[[]]},"Embeddings Google Gemini":{"ai_embedding":[[{"node":"Pinecone Vector Store","type":"ai_embedding","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Google Drive File Created":{"main":[[{"node":"Download File From Google Drive","type":"main","index":0}]]},"Google Drive File Updated":{"main":[[{"node":"Download File From Google Drive","type":"main","index":0}]]},"When chat message received":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Download File From Google Drive":{"main":[[{"node":"Pinecone Vector Store","type":"main","index":0}]]},"Pinecone Vector Store (Retrieval)":{"ai_vectorStore":[[{"node":"Vector Store Tool","type":"ai_vectorStore","index":0}]]},"Recursive Character Text Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader","type":"ai_textSplitter","index":0}]]},"Embeddings Google Gemini (retrieval)":{"ai_embedding":[[{"node":"Pinecone Vector Store (Retrieval)","type":"ai_embedding","index":0}]]},"Google Gemini Chat Model (retrieval)":{"ai_languageModel":[[{"node":"Vector Store Tool","type":"ai_languageModel","index":0}]]}}}


name: Create a Branded AI-Powered Website Chatbot
author_name: Wayne Simpson
author_username: nocodecreative
categories: []
created_at: 2025-01-23T17:44:16.860Z
updated_at: 2025-01-23T17:44:16.860Z
url: https://n8n.io/workflows/2786
scraped_at: 2025-07-06 21:16:30
description:
  Create a Branded AI Website Chatbot

  Engage website visitors with an intelligent chat widget powered by OpenAI. This template includes:

  💬 Natural conversation handling
  📅 Microsoft Outlook calendar integration
  📝 Lead capture and information gathering
  🔄 Human handoff capabilities

  Simply add a JavaScript snippet to your website and configure the workflow to match your needs. Follow our detailed setup guide to get started in minutes.



  &gt; Note: Widget includes a "Powered By" affiliate link

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.microsoftOutlook","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.memoryBufferWindow","@n8n/n8n-nodes-langchain.toolWorkflow","@n8n/n8n-nodes-langchain.toolHttpRequest"]

workflow_json:
  {"meta":{"instanceId":"67d4d33d8b0ad4e5e12f051d8ad92fc35893d7f48d7f801bc6da4f39967b3592","templateCredsSetupCompleted":true},"nodes":[{"id":"22c8d63b-ce3c-4aab-b3f6-4bae8c1b9ec5","name":"Window Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[1460,880],"parameters":{"sessionKey":"={{ $json.sessionId }}","sessionIdType":"customKey","contextWindowLength":20},"typeVersion":1.2},{"id":"45403d5c-6e85-424f-b40b-c6214b57457b","name":"Respond to Webhook","type":"n8n-nodes-base.respondToWebhook","position":[1880,580],"parameters":{"options":{}},"typeVersion":1.1},{"id":"1111262a-1743-4bae-abf1-f69d2e1a580c","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1360,760],"parameters":{"model":"gpt-4o-2024-08-06","options":{"temperature":0.4}},"credentials":{"openAiApi":{"id":"XWFTuTtx9oWglhNn","name":"OpenAi account"}},"typeVersion":1},{"id":"df891547-c715-4dc6-bfcc-c0ac5cfcaf02","name":"Make Appointment","type":"@n8n/n8n-nodes-langchain.toolHttpRequest","position":[1820,840],"parameters":{"url":"https://graph.microsoft.com/v1.0/me/events","method":"POST","jsonBody":"{\n  \"subject\": \"Meetings with <name> at <company>\",\n  \"start\": {\n    \"dateTime\": \"{dateStartTime}\",\n    \"timeZone\": \"Europe/London\"\n  },\n  \"end\": {\n    \"dateTime\": \"{dateEndTime}\",\n    \"timeZone\": \"Europe/London\"\n  },\n  \"body\": {\n    \"contentType\": \"HTML\",\n    \"content\": \"{reason}\"\n  },\n  \"attendees\": [\n    {\n      \"emailAddress\": {\n        \"address\": \"{email}\",\n        \"name\": \"{name}\"\n      },\n      \"type\": \"required\"\n    }\n  ],\n  \"location\": {\n    \"displayName\": \"Online Meeting\"\n  },\n  \"isOnlineMeeting\": true,\n  \"onlineMeetingProvider\": \"teamsForBusiness\",\n  \"showAs\": \"busy\",\n  \"categories\": [\n    \"Meeting\"\n  ]\n}","sendBody":true,"sendQuery":true,"specifyBody":"json","authentication":"predefinedCredentialType","parametersQuery":{"values":[{"name":"Content-Type","value":"application/json","valueProvider":"fieldValue"}]},"toolDescription":"Call this tool to make the appointment, ensure you send the user email, name, company, reason for the meeting and the appointment start time and the date in ISO String format with timezone for <timezone>. When creating an appointment, always send JSON.","nodeCredentialType":"microsoftOutlookOAuth2Api","placeholderDefinitions":{"values":[{"name":"dateStartTime","type":"string","description":"The date and start time of the appointment in toISOString format with timezone for Europe/London"},{"name":"dateEndTime","type":"string","description":"The date and end time of the appointment in toISOString format, always 30 minutes after the dateStartTime,  format with timezone for Europe/London"},{"name":"reason","type":"string","description":"Detailed description of the meeting, will be sent to us and the customer"},{"name":"email","type":"string","description":"The customers email address."},{"name":"name","type":"string","description":"The customers full name, must be second and last name"}]}},"credentials":{"microsoftOutlookOAuth2Api":{"id":"E0WY3yUNKgrxIwLU","name":"Microsoft Outlook Business"}},"typeVersion":1.1},{"id":"44141c44-de49-4707-b287-24007c84ca21","name":"Execute Workflow Trigger","type":"n8n-nodes-base.executeWorkflowTrigger","position":[2160,580],"parameters":{},"typeVersion":1},{"id":"795e1451-57d8-4563-8b86-5a75df2427b6","name":"varResponse","type":"n8n-nodes-base.set","position":[3120,460],"parameters":{"options":{},"assignments":{"assignments":[{"id":"c0b6e779-0f7b-41f0-81f8-457f2b31ccfe","name":"response","type":"array","value":"={{ $json.freeTimeSlots.toJsonString() }}"}]}},"typeVersion":3.4},{"id":"4283635f-649c-4cc7-84b9-37524ddb6ce0","name":"freeTimeSlots","type":"n8n-nodes-base.code","position":[2900,460],"parameters":{"jsCode":"// Input: An array with objects containing a 'value' array of events.\nconst businessHoursStart = \"08:00:00Z\";  // Business hours start time\nconst businessHoursEnd = \"17:30:00Z\";    // Business hours end time\n\nconst inputData = items[0].json.value;  // Assuming the input data is in the 'value' array of the first item\n\n// Function to convert ISO datetime string to a Date object with specified time\nfunction getDateWithTime(dateString, time) {\n  const datePart = new Date(dateString).toISOString().split(\"T\")[0];  // Extract the date part (YYYY-MM-DD)\n  return new Date(`${datePart}T${time}`);\n}\n\n// Function to get day of the week from a date string\nfunction getDayOfWeek(dateString) {\n  const daysOfWeek = [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"];\n  return daysOfWeek[new Date(dateString).getUTCDay()];\n}\n\n// Function to add days to a date\nfunction addDays(date, days) {\n  const result = new Date(date);\n  result.setDate(result.getDate() + days);\n  return result;\n}\n\n// Function to format date as YYYY-MM-DD\nfunction formatDate(date) {\n  return date.toISOString().split('T')[0];\n}\n\n// Determine the default timezone from input data\nconst defaultTimeZone = inputData.length > 0 && inputData[0].start && inputData[0].start.timeZone \n  ? inputData[0].start.timeZone \n  : \"UTC\";\n\n// Find min and max dates in the input\nlet minDate = null;\nlet maxDate = null;\n\ninputData.forEach(event => {\n  if (event.start && event.start.dateTime) {\n    const eventDate = new Date(event.start.dateTime);\n    if (!minDate || eventDate < minDate) {\n      minDate = eventDate;\n    }\n    if (!maxDate || eventDate > maxDate) {\n      maxDate = eventDate;\n    }\n  }\n});\n\n// If we have valid dates, ensure they're at the start of the day\nif (minDate && maxDate) {\n  minDate = new Date(minDate.toISOString().split('T')[0]);\n  maxDate = new Date(maxDate.toISOString().split('T')[0]);\n}\n\n// Organise events by date\nconst eventsByDate = {};\ninputData.forEach(event => {\n  if (event.start && event.start.dateTime) {\n    const eventDate = new Date(event.start.dateTime).toISOString().split(\"T\")[0];  // Extract the date\n    if (!eventsByDate[eventDate]) {\n      eventsByDate[eventDate] = [];\n    }\n    if (event.showAs === \"busy\") {\n      eventsByDate[eventDate].push({\n        start: new Date(event.start.dateTime),\n        end: new Date(event.end.dateTime),\n        timeZone: event.start.timeZone || defaultTimeZone\n      });\n    }\n  }\n});\n\n// Find free slots within business hours for each date\nconst freeTimeSlots = [];\n\n// Process all dates in the range\nif (minDate && maxDate) {\n  for (let currentDate = new Date(minDate); currentDate <= maxDate; currentDate = addDays(currentDate, 1)) {\n    const dateStr = formatDate(currentDate);\n    const busyEvents = eventsByDate[dateStr] || [];\n    \n    // Define business start and end times for the current date\n    const businessStart = getDateWithTime(dateStr, businessHoursStart);\n    const businessEnd = getDateWithTime(dateStr, businessHoursEnd);\n    \n    // If there are no busy events for this date, add the entire business day as free\n    if (busyEvents.length === 0) {\n      freeTimeSlots.push({\n        date: dateStr,\n        dayOfWeek: getDayOfWeek(dateStr),\n        freeStart: businessStart.toISOString(),\n        freeEnd: businessEnd.toISOString(),\n        timeZone: defaultTimeZone\n      });\n      continue; // Skip to the next date\n    }\n    \n    // Sort events by their start time\n    busyEvents.sort((a, b) => a.start - b.start);\n    \n    // Check if there's free time before the first busy event\n    if (busyEvents[0].start > businessStart) {\n      freeTimeSlots.push({\n        date: dateStr,\n        dayOfWeek: getDayOfWeek(dateStr),\n        freeStart: businessStart.toISOString(),\n        freeEnd: busyEvents[0].start.toISOString(),\n        timeZone: busyEvents[0].timeZone\n      });\n    }\n    \n    // Check for gaps between busy events\n    for (let i = 0; i < busyEvents.length - 1; i++) {\n      if (busyEvents[i].end < busyEvents[i+1].start) {\n        freeTimeSlots.push({\n          date: dateStr,\n          dayOfWeek: getDayOfWeek(dateStr),\n          freeStart: busyEvents[i].end.toISOString(),\n          freeEnd: busyEvents[i+1].start.toISOString(),\n          timeZone: busyEvents[i].timeZone\n        });\n      }\n    }\n    \n    // Check if there's free time after the last busy event\n    if (busyEvents[busyEvents.length - 1].end < businessEnd) {\n      freeTimeSlots.push({\n        date: dateStr,\n        dayOfWeek: getDayOfWeek(dateStr),\n        freeStart: busyEvents[busyEvents.length - 1].end.toISOString(),\n        freeEnd: businessEnd.toISOString(),\n        timeZone: busyEvents[busyEvents.length - 1].timeZone\n      });\n    }\n  }\n}\n\n// Output the free time slots\nreturn [{ json: { freeTimeSlots } }];\n"},"typeVersion":2},{"id":"0786b561-449e-4c8f-bddb-c2bbd95dc197","name":"Get Events","type":"n8n-nodes-base.httpRequest","position":[2680,460],"parameters":{"url":"=https://graph.microsoft.com/v1.0/me/calendarView","options":{},"sendQuery":true,"sendHeaders":true,"authentication":"predefinedCredentialType","queryParameters":{"parameters":[{"name":"startDateTime","value":"={{ new Date(new Date().setDate(new Date().getDate() + 2)).toISOString() }}"},{"name":"endDateTime","value":"={{ new Date(new Date().setDate(new Date().getDate() + 16)).toISOString() }}"},{"name":"$top","value":"50"},{"name":"select","value":"start,end,categories,importance,isAllDay,recurrence,showAs,subject,type"},{"name":"orderby","value":"start/dateTime asc"}]},"headerParameters":{"parameters":[{"name":"Prefer","value":"outlook.timezone=\"Europe/London\""}]},"nodeCredentialType":"microsoftOutlookOAuth2Api"},"credentials":{"microsoftOutlookOAuth2Api":{"id":"E0WY3yUNKgrxIwLU","name":"Microsoft Outlook Business"}},"typeVersion":4.2},{"id":"55c4233e-d395-4193-9a1d-1884faed6f1e","name":"Get Availability","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[1760,1080],"parameters":{"name":"Get_availability","fields":{"values":[{"name":"route","stringValue":"availability"}]},"workflowId":{"__rl":true,"mode":"list","value":"KD21RG8VeXYDS2Vf","cachedResultName":"Website Chatbot"},"description":"Call this tool to check my calendar for availability before booking an appointment. This will result in all events for the next 2 weeks. Review all events and do not double book."},"typeVersion":1.2},{"id":"096d1962-31e6-4b3b-ba75-7956f70a6a32","name":"Send Message","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[1620,1080],"parameters":{"name":"Send_email","fields":{"values":[{"name":"route","stringValue":"message"}]},"workflowId":{"__rl":true,"mode":"list","value":"KD21RG8VeXYDS2Vf","cachedResultName":"Website Chatbot"},"description":"Call this tool when the customer wants to speak to a human, or is not ready to make an appointment or if the customer has questions outside of your remit. The tool will send an email to our founder, <insert name>. Always send the customer's full name, company and email address along with a detailed message about the enquiry. You must always gather project details.","jsonSchemaExample":"{\n\t\"email\": \"the customer's email\",\n    \"subject\": \"the subject of the email\",\n    \"message\": \"The customer's enquiry, must be a detailed description of their enquiry\",\n    \"name\": \"the customer's full name\",\n    \"company\": \"the customer company name\"\n}","specifyInputSchema":true},"typeVersion":1.2},{"id":"285ddd31-5412-4d1c-ab80-d9960ec902bb","name":"Chat Trigger","type":"@n8n/n8n-nodes-langchain.chatTrigger","disabled":true,"position":[620,600],"webhookId":"f406671e-c954-4691-b39a-66c90aa2f103","parameters":{"mode":"webhook","public":true,"options":{"responseMode":"responseNode","allowedOrigins":"*"}},"typeVersion":1},{"id":"032a26e9-6853-490d-991b-b2af2d845f58","name":"Switch","type":"n8n-nodes-base.switch","position":[2380,580],"parameters":{"rules":{"values":[{"outputKey":"availability","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.route }}","rightValue":"availability"}]},"renameOutput":true},{"outputKey":"message","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"52fd844b-cc8d-471f-a56a-40e119b66194","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.route }}","rightValue":"message"}]},"renameOutput":true}]},"options":{}},"typeVersion":3.2},{"id":"c74905ce-4fd9-486c-abc4-b0b1d57d71a8","name":"varMessageResponse","type":"n8n-nodes-base.set","position":[2900,700],"parameters":{"options":{"ignoreConversionErrors":false},"assignments":{"assignments":[{"id":"0d2ad084-9707-4979-84e4-297d1c21f725","name":"response","type":"string","value":"={{ $json }}"}]}},"typeVersion":3.4},{"id":"04c5d43c-1629-4e11-a6bb-ae73369d7002","name":"Send Message1","type":"n8n-nodes-base.microsoftOutlook","position":[2680,700],"webhookId":"d8acc2cb-fcba-4312-a743-e74abe76d071","parameters":{"subject":"={{ $('Execute Workflow Trigger').item.json.query.subject }}","bodyContent":"=<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>New Webchat Customer Enquiry</title>\n    <style type=\"text/css\">\n        /* Client-specific styles */\n        body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }\n        table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }\n        img { -ms-interpolation-mode: bicubic; }\n\n        /* Reset styles */\n        body { margin: 0; padding: 0; }\n        img { border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; }\n        table { border-collapse: collapse !important; }\n        body { height: 100% !important; margin: 0; padding: 0; width: 100% !important; }\n\n        /* iOS BLUE LINKS */\n        a[x-apple-data-detectors] {\n            color: inherit !important;\n            text-decoration: none !important;\n            font-size: inherit !important;\n            font-family: inherit !important;\n            font-weight: inherit !important;\n            line-height: inherit !important;\n        }\n\n        /* Styles for Outlook and other email clients */\n        .ExternalClass { width: 100%; }\n        .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div { line-height: 100%; }\n        \n        /* Responsive styles */\n        @media screen and (max-width: 600px) {\n            .container { width: 100% !important; }\n            .content { padding: 15px !important; }\n            .field { padding: 10px !important; }\n            .header h1 { font-size: 20px !important; }\n            .header p { font-size: 12px !important; }\n        }\n    </style>\n</head>\n<body style=\"margin: 0; padding: 0; background-color: #f4f4f4;\">\n    <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n        <tr>\n            <td>\n                <table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"600\" style=\"border-collapse: collapse; background-color: #ffffff;\">\n                    <tr>\n                        <td align=\"center\" bgcolor=\"#1a1a1a\" style=\"padding: 30px 0; background: linear-gradient(135deg, #1a1a1a 0%, #2d1f3d 100%);\">\n                            <h1 style=\"color: #ffffff; font-family: Arial, sans-serif; font-size: 24px; font-weight: 700; margin: 0; text-transform: uppercase; letter-spacing: 1px;\">New Customer Enquiry</h1>\n                            <p style=\"color: #ffffff; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin: 10px 0 0; opacity: 0.8;\">A potential client has reached out through our webchat</p>\n                        </td>\n                    </tr>\n                    <tr>\n                        <td style=\"padding: 20px;\">\n                            <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n                                <tr>\n                                    <td style=\"padding: 15px; background-color: #f9f9f9; border: 1px solid #e0e0e0; border-radius: 8px;\">\n                                        <p style=\"font-family: Arial, sans-serif; font-size: 14px; line-height: 1.6; color: #6a1b9a; font-weight: bold; margin: 0 0 5px 0;\">FROM</p>\n                                        <p style=\"font-family: Arial, sans-serif; font-size: 16px; line-height: 1.6; color: #333333; margin: 0;\">{{ $('Execute Workflow Trigger').item.json.query.name }}</p>\n                                    </td>\n                                </tr>\n                                <tr><td height=\"20\"></td></tr>\n                                <tr>\n                                    <td style=\"padding: 15px; background-color: #f9f9f9; border: 1px solid #e0e0e0; border-radius: 8px;\">\n                                        <p style=\"font-family: Arial, sans-serif; font-size: 14px; line-height: 1.6; color: #6a1b9a; font-weight: bold; margin: 0 0 5px 0;\">EMAIL</p>\n                                        <p style=\"font-family: Arial, sans-serif; font-size: 16px; line-height: 1.6; color: #333333; margin: 0;\">{{ $('Execute Workflow Trigger').item.json.query.email }}</p>\n                                    </td>\n                                </tr>\n                                <tr><td height=\"20\"></td></tr>\n                                <tr>\n                                    <td style=\"padding: 15px; background-color: #f9f9f9; border: 1px solid #e0e0e0; border-radius: 8px;\">\n                                        <p style=\"font-family: Arial, sans-serif; font-size: 14px; line-height: 1.6; color: #6a1b9a; font-weight: bold; margin: 0 0 5px 0;\">COMPANY</p>\n                                        <p style=\"font-family: Arial, sans-serif; font-size: 16px; line-height: 1.6; color: #333333; margin: 0;\">{{ $('Execute Workflow Trigger').item.json.query.company }}</p>\n                                    </td>\n                                </tr>\n                                <tr><td height=\"20\"></td></tr>\n                                <tr>\n                                    <td style=\"padding: 15px; background-color: #f9f9f9; border: 1px solid #e0e0e0; border-radius: 8px;\">\n                                        <p style=\"font-family: Arial, sans-serif; font-size: 14px; line-height: 1.6; color: #6a1b9a; font-weight: bold; margin: 0 0 5px 0;\">MESSAGE</p>\n                                        <p style=\"font-family: Arial, sans-serif; font-size: 16px; line-height: 1.6; color: #333333; margin: 0;\">{{ $('Execute Workflow Trigger').item.json.query.message }}</p>\n                                    </td>\n                                </tr>\n                            </table>\n                        </td>\n                    </tr>\n                    <tr>\n                        <td align=\"center\" bgcolor=\"#e90ebb\" style=\"padding: 20px; background: linear-gradient(135deg, #e90ebb 0%, #6a1b9a 100%);\">\n                            <p style=\"font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; color: #ffffff; margin: 0;\">This enquiry was automatically generated from our website's chat interface.</p>\n                        </td>\n                    </tr>\n                </table>\n            </td>\n        </tr>\n    </table>\n</body>\n</html>","toRecipients":"you@yourdomain.com","additionalFields":{"importance":"High","bodyContentType":"html"}},"credentials":{"microsoftOutlookOAuth2Api":{"id":"E0WY3yUNKgrxIwLU","name":"Microsoft Outlook Business"}},"typeVersion":2},{"id":"5a2636f1-47d3-4421-840b-56553bf14d82","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[1580,1000],"parameters":{"width":311.6936390497898,"height":205.34013605442183,"content":"Ensure these referance this workflow, replace placeholders"},"typeVersion":1},{"id":"a9fe05d4-6b86-4313-9f11-b20e3ce7db89","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[2600,380],"parameters":{"width":468,"height":238,"content":"modify business hours\nmodify timezones"},"typeVersion":1},{"id":"5dfda5c9-eeeb-421a-a80d-f42c94602080","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[1460,580],"parameters":{"text":"={{ $json.chatInput }}","options":{"systemMessage":"=You are an intelligent personal assistant to Wayne, Founder at nocodecreative.io (ai consultancy and software development agency) responsible for coordinating appointments and gathering relevant information from customers. Your tasks are to:\n\n- Understand when the customer is available by asking for suitable days and times (ensuring they are aware we are in a UK timezone)\n- Check the calendar to identify available slots that match their preferences. Pay attention to each event's start and end time and do not double book, you will be given all events for the next 14 days\n- Ask the customer what they would like to discuss during the appointment to ensure proper preparation.\n- Get the customer's name, company name and email address to book the appointment\n- Make the conversation friendly and natural. Confirm the appointment details with the customer and let them know I’ll be ready to discuss what they’d like.\n- After you have checked the calendar, book the appointment accordingly, without double booking. Confirm the customer's timezone and adjust the appointment for EU/London.\n- If the customer isn't ready to book, you can send an email for a human to respond to, ensure you gather a detailed enquiry from the customer including contact details and project information.Ensure the message contains enough information for a human to respond, always include project details, if the customer hasn't provided project details, ask.\n- Alwways suggest an appointment before sending a message, appointment are you primary goal, message are a fall back\n\nExample questions:\n\n\"Hi there! we'd love to help arrange a time that works for us to meet. Could you let us know which days and times are best for you? We’ll check the calendar and book in a suitable slot.\"\n\n\"Could you please let us know what you’d like to discuss during the appointment? This helps us prepare in advance and make our time together as productive as possible.\"\n\n\"Before we put you in touch with a human, please can you provide more information about the project you have in mind?\" //You must gather project info at all times, even if the enquiry is about pricing/costs.\n\nIf the time the customer suggests is not available, suggest the nearest alternative appointment based on existing events, do not book an appointment outside of freeTimeSlots\n\nImportant information:\n- All appointments need 48 hours' notice from {{ \n  new Date().toLocaleString(\"en-GB\", { timeZone: \"Europe/London\", hour12: false })\n  .split(\", \")[0].split(\"/\").reverse().join(\"-\") \n  + \"T\" + new Date().toLocaleTimeString(\"en-GB\", { timeZone: \"Europe/London\", hour12: false }) + \":00.000Z\" \n}} (current date and time in the UK) // this is non-negotiable, but discuss with care and be friendly, only let the customer know this if required\n- Business hours are 8am - 6pm Monday to Friday only Europe/London timezone, ensure the customer is aware of this and help them book during UK hours, you must confirm their timezone to do this!\n- Do not book appointments on a Saturday or sunday\n- Do not book appointments outside of freeTimeSlots\n- Always check the next 14 days, and review all events before providing availability \n- All appointments are for a max of 30 minutes\n- You must never offer an appointment without checking the calendar, if you cannot check the calendar, you cannot book and must let the customer know you can not book an appointment right now.\n- Always offer the soonest appointment available if the customer's preferred time is unavailable\n- When confirming an appointment, be thankful and excited!\n- Initial 30 minute consultation are free of charge\n\n\nMessages and description:\n- When creating descriptions or sending messages, always ensure enough detail is provided for preparation, meaning you can ask follow-up questions to extract further information as required. For example, if a customer asks about pricing, gather some information about the project so our team can provide accurate pricing, and apply this logic throughout\n\nComments:\n//!IMPORTANT! Do not offer any times without checking the calendar, do not make availability up\n//**Do not discuss anything other than appointment booking, if the query does not relate to an appointment, advise them you cannot help at this time.** be friendly and always offer to book an appointment to discuss their query\n//When the appointment is confirmed, let the customer know, by name, that they will be meeting our founder, Wayne for a 30 minute consultation, and that they will receive a calendar invite by email, ensure they accept the invite to confirm the appointment.\n//Always respond as a highly professional executive PA, remember this is the customer's first engagement, they do not know us or Wayne at this stage\n//Do not refer to yourself as me or I, instead communicate like an organisation, using terms like 'us'\n//Always gather project for descriptions and messages"},"promptType":"define"},"typeVersion":1.6},{"id":"6156ab7e-d411-46b9-ac44-52ad56ee563d","name":"If","type":"n8n-nodes-base.if","position":[840,600],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"158a0b91-534d-4745-b10e-8a7c97050861","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $json.chatInput }}","rightValue":""}]}},"typeVersion":2.2},{"id":"c94171a9-a71d-4f63-bef6-e90361c57abd","name":"Respond With Initial Message","type":"n8n-nodes-base.respondToWebhook","position":[1140,720],"parameters":{"options":{},"respondWith":"json","responseBody":"{\n  \"output\": \"Hi, how can I help you today?\"\n}"},"typeVersion":1.1},{"id":"43129771-e976-41af-8adb-88cb5465628d","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[1340,-240],"parameters":{"color":6,"width":668,"height":111,"content":"# Custom Branded n8n Chatbot\nBuilt by [Wayne Simpson](https://www.linkedin.com/in/simpsonwayne/) at [nocodecreative.io](https://nocodecreative.io)\n☕ If you find this useful, feel free to [buy me a coffee](https://ko-fi.com/waynesimpson)"},"typeVersion":1},{"id":"bb890f44-caf0-4b7d-b95e-0c05c70e8f45","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[1000,-80],"parameters":{"color":7,"width":667,"height":497,"content":"# Watch the Setup Video 📺\n### Watch Set Up Video 👇\n[![Auto Categorise Outlook Emails with AI](https://cdn.jsdelivr.net/gh/WayneSimpson/n8n-chatbot-template/custom-branded-chatbot.png)](https://youtu.be/xQ1tCQZhLaI)\n\n"},"typeVersion":1},{"id":"f0b054cc-f961-4c48-846c-a80ea5e49924","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[1700,-80],"parameters":{"color":7,"width":600,"height":500,"content":"## Read to blog post to get started 📝\n**Follow along to add a custom branded chat widget to your webiste**\n\n[![Custom Branded n8n Chatbot](https://cdn.jsdelivr.net/gh/WayneSimpson/n8n-chatbot-template/chat%20widget.png)](https://blog.nocodecreative.io/create-a-branded-ai-powered-website-chatbot-with-n8n/)"},"typeVersion":1},{"id":"210cef85-6fbe-413e-88b6-b0fed76212ac","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[2600,640],"parameters":{"color":4,"width":260,"height":240,"content":"Customise the email template"},"typeVersion":1},{"id":"17abc6bd-06c3-48e7-8380-e10024daa9f5","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1760,740],"parameters":{"color":6,"width":208,"height":238,"content":"modify timezones"},"typeVersion":1}],"connections":{"If":{"main":[[{"node":"AI Agent","type":"main","index":0}],[{"node":"Respond With Initial Message","type":"main","index":0}]]},"Switch":{"main":[[{"node":"Get Events","type":"main","index":0}],[{"node":"Send Message1","type":"main","index":0}]]},"AI Agent":{"main":[[{"node":"Respond to Webhook","type":"main","index":0}]]},"Get Events":{"main":[[{"node":"freeTimeSlots","type":"main","index":0}]]},"Chat Trigger":{"main":[[{"node":"If","type":"main","index":0}]]},"Send Message":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"Send Message1":{"main":[[{"node":"varMessageResponse","type":"main","index":0}]]},"freeTimeSlots":{"main":[[{"node":"varResponse","type":"main","index":0}]]},"Get Availability":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"Make Appointment":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Window Buffer Memory":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"Execute Workflow Trigger":{"main":[[{"node":"Switch","type":"main","index":0}]]}}}


name: Generate Instagram Content from Top Trends with AI Image Generation
author_name: mustafa kendigüzel
author_username: mustafakendiguzel
categories: []
created_at: 2025-01-26T14:36:11.785Z
updated_at: 2025-01-26T14:36:11.785Z
url: https://n8n.io/workflows/2803
scraped_at: 2025-07-06 21:16:30
description:
  How it works

  This automated workflow discovers trending Instagram posts and creates similar AI-generated content. Here's the high-level process:

  1. Content Discovery & Analysis
  Scrapes trending posts from specific hashtags
  Analyzes visual elements using AI
  Filters out videos and duplicates

  2. AI Content Generation
  Creates unique images based on trending content
  Generates engaging captions with relevant hashtags
  Maintains brand consistency while being original

  3. Automated Publishing
  Posts content directly to Instagram
  Monitors publication status
  Sends notifications via Telegram

  Set up steps

  Setting up this workflow takes approximately 15-20 minutes:

  1. API Configuration (7-10 minutes)
  Instagram Business Account setup
  Telegram Bot creation
  API key generation (OpenAI, Replicate, Rapid Api)

  2. Database Setup (3-5 minutes)
  Create required database table
  Configure PostgreSQL credentials

  3. Workflow Configuration (5-7 minutes)
  Set scheduling preferences
  Configure notification settings
  Test connection and permissions

  Detailed technical specifications and configurations are available in sticky notes within the workflow.

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.postgres","n8n-nodes-base.telegram","n8n-nodes-base.facebookGraphApi","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.openAi"]

workflow_json:
  {"id":"H7porcmXYj7StO23","meta":{"instanceId":"35409808e3cc9dd8ecfa6f7b93ae931f074920a2f681e667da8974c0ecf81c52","templateId":"2537","templateCredsSetupCompleted":true},"name":"Generate Instagram Content from Top Trends with AI Image Generation","tags":[],"nodes":[{"id":"8c49be2b-6320-4eb0-8303-6448ced34636","name":"If media status is finished","type":"n8n-nodes-base.if","position":[1420,260],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"0304efee-33b2-499e-bad1-9238c1fc2999","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.status_code }}","rightValue":"FINISHED"}]}},"typeVersion":2.2},{"id":"f0cc0be5-6d35-4334-a124-139fa8676d07","name":"If media status is finished1","type":"n8n-nodes-base.if","position":[2000,260],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"0304efee-33b2-499e-bad1-9238c1fc2999","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.status_code }}","rightValue":"PUBLISHED"}]}},"typeVersion":2.2},{"id":"c8d8d8cd-8501-4d1b-ac28-8cb3fa74d9d7","name":"Telegram","type":"n8n-nodes-base.telegram","position":[1580,440],"parameters":{"text":"Video upload edilmeden önce bir problem oldu","chatId":"={{ $('Telegram Params').item.json.telegram_chat_id }}","additionalFields":{}},"credentials":{"telegramApi":{"id":"GcIVVl98RcazYBaB","name":"Telegram account"}},"typeVersion":1.2},{"id":"ae91a5e0-4f70-4a1c-afa5-41f5449facab","name":"Telegram1","type":"n8n-nodes-base.telegram","position":[2160,100],"parameters":{"text":"Instagram Content is shared","chatId":"={{ $('Telegram Params').item.json.telegram_chat_id }}","additionalFields":{}},"credentials":{"telegramApi":{"id":"GcIVVl98RcazYBaB","name":"Telegram account"}},"typeVersion":1.2},{"id":"b8b38440-14a7-43f6-ac49-6ca9502ff54d","name":"Telegram2","type":"n8n-nodes-base.telegram","position":[2160,440],"parameters":{"text":"There was a problem when execution a upload content to instagram","chatId":"={{ $('Telegram Params').item.json.telegram_chat_id }}","additionalFields":{}},"credentials":{"telegramApi":{"id":"GcIVVl98RcazYBaB","name":"Telegram account"}},"typeVersion":1.2},{"id":"82e0e5d0-bf50-4b2e-8693-2612dffe53e2","name":"Loop Over Items","type":"n8n-nodes-base.splitInBatches","position":[-1000,220],"parameters":{"options":{}},"typeVersion":3},{"id":"fb72beb1-1a6a-4148-9ee4-cdc564c4dc5c","name":"Schedule Trigger1","type":"n8n-nodes-base.scheduleTrigger","position":[-3080,300],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"5 13,19 * * *"}]}},"typeVersion":1.2},{"id":"470f3406-19d2-420c-8f33-7031237d882c","name":"Telegram Params","type":"n8n-nodes-base.set","position":[-2320,300],"parameters":{"options":{},"assignments":{"assignments":[{"id":"d18cdca7-d301-4c70-a4d0-8d6e7ecfc2d1","name":"telegram_chat_id","type":"string","value":""}]}},"typeVersion":3.4},{"id":"12971505-7061-4d32-8921-d2e731eae9db","name":"Instagram params","type":"n8n-nodes-base.set","position":[-2560,300],"parameters":{"options":{},"assignments":{"assignments":[{"id":"1e380c14-e908-4eeb-90e0-957a422829d0","name":"instagram_business_account_id","type":"string","value":""}]}},"typeVersion":3.4},{"id":"3cb5f27d-eb3b-4fdc-bb55-1b54f85298e5","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-2860,20],"parameters":{"color":4,"width":1000,"height":600,"content":"## All Credentials You Need\n**  Instagram Business Account Id\n** Telegram Chat Id\n**  Rapid Api Key\n** Replicate Token"},"typeVersion":1},{"id":"2bc617b8-835c-48ba-8de6-341a6c87b853","name":"Rapid Api params","type":"n8n-nodes-base.set","notes":"test","position":[-2080,300],"parameters":{"options":{},"assignments":{"assignments":[{"id":"48a33ec7-2b4f-496a-ad77-e4d5f1907ee4","name":"x-rapid-api-key","type":"string","value":""}]}},"notesInFlow":false,"typeVersion":3.4},{"id":"23bad41e-40ac-4488-8b2f-0d54d22a927a","name":"filter the image content","type":"n8n-nodes-base.code","position":[-1480,380],"parameters":{"jsCode":"const filteredData = $input.first().json.data.items.filter(item=> !item.is_video)\nreturn filteredData.map((item)=>{\n  return {\n    id: item.id,\n    prompt: item.caption.text,\n    content_code: item.code,\n    thumbnail_url: item.thumbnail_url,\n    tag: $input.first().json.data.additional_data.name\n  }\n})                                                                    \n\n"},"typeVersion":2},{"id":"a65690cd-4d30-4541-b80d-aae872326a77","name":"get  top trends on instagram #blender3d","type":"n8n-nodes-base.httpRequest","position":[-1720,180],"parameters":{"url":"https://instagram-scraper-api2.p.rapidapi.com/v1/hashtag","options":{},"sendQuery":true,"sendHeaders":true,"queryParameters":{"parameters":[{"name":"hashtag","value":"blender3d"},{"name":"feed_type","value":"top"}]},"headerParameters":{"parameters":[{"name":"x-rapidapi-host","value":"instagram-scraper-api2.p.rapidapi.com"},{"name":"x-rapidapi-key","value":"={{ $json['x-rapid-api-key'] }}"}]}},"typeVersion":4.2},{"id":"8707c475-7e28-4d80-92b8-ba24033c4632","name":"get top trends on instagram #isometric","type":"n8n-nodes-base.httpRequest","position":[-1720,380],"parameters":{"url":"https://instagram-scraper-api2.p.rapidapi.com/v1/hashtag","options":{},"sendQuery":true,"sendHeaders":true,"queryParameters":{"parameters":[{"name":"hashtag","value":"isometric"},{"name":"feed_type","value":"top"}]},"headerParameters":{"parameters":[{"name":"x-rapidapi-host","value":"instagram-scraper-api2.p.rapidapi.com"},{"name":"x-rapidapi-key","value":"={{ $json['x-rapid-api-key'] }}"}]}},"typeVersion":4.2},{"id":"1c1bfd8f-b086-4147-ba08-578877f2a315","name":"merge the array content","type":"n8n-nodes-base.merge","position":[-1280,280],"parameters":{},"typeVersion":3},{"id":"dcc2b6b6-9880-4676-8a1a-a3c21e583bba","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-3180,20],"parameters":{"color":3,"width":280,"height":600,"content":"## Schedule Your Time To  Post\n"},"typeVersion":1},{"id":"c1e0ac33-c4b7-47d8-bd2b-0b74b02afe38","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-2600,160],"parameters":{"color":5,"width":180,"height":300,"content":"## Guide \n** [Guide](https://docs.matillion.com/metl/docs/6957316//) of getting  of Instagram Business Account Id "},"typeVersion":1},{"id":"321680da-ca7a-4c6f-98d4-a0d8f8d0347f","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-2360,160],"parameters":{"color":5,"width":180,"height":300,"content":"## Guide \n** [Guide](https://rapidapi.com/i-yqerddkq0t/api/telegram92/tutorials/how-to-get-the-id-of-a-telegram-channel,-chat,-user-or-bot%3F) of Getting  of Telegram Chat Id "},"typeVersion":1},{"id":"b3d07cf7-8d03-4644-88f7-2e94de0c43c2","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-2120,160],"parameters":{"color":5,"width":180,"height":300,"content":"## Guide \n** [Guide](https://docs.rapidapi.com/docs/keys-and-key-rotation) of Getting  of Rapid Api Key "},"typeVersion":1},{"id":"b6dbdfaa-fc71-4def-a723-bf6c0facd372","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-2360,480],"parameters":{"color":7,"width":180,"height":120,"content":"## Warning\n**Don't forgot the create bot and send a message to bot first"},"typeVersion":1},{"id":"81d598e2-8993-4315-9894-2e78dc26ad10","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[-1820,20],"parameters":{"width":660,"height":600,"content":"## Getting Top Trend Posts On Instagram\n** Change the topic you want to get on http request"},"typeVersion":1},{"id":"6beb79ef-8205-4882-9bb0-6a2e1a33f1d4","name":"Check Data on Database Is Exist","type":"n8n-nodes-base.postgres","onError":"continueErrorOutput","position":[-760,220],"parameters":{"table":{"__rl":true,"mode":"list","value":"top_trends","cachedResultName":"top_trends"},"where":{"values":[{"value":"={{$json.content_code}}","column":"code"}]},"schema":{"__rl":true,"mode":"list","value":"public","cachedResultName":"public"},"options":{},"operation":"select"},"credentials":{"postgres":{"id":"sBHQ2psBsfnHkFrZ","name":"Postgres account"}},"typeVersion":2.5,"alwaysOutputData":true},{"id":"5b0c05a8-3eb7-4ad8-88e8-ceef81fe7a61","name":"If Data is Exist","type":"n8n-nodes-base.if","position":[-540,240],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"9dc20983-ae4d-40db-b969-7d43fa8b0c3e","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ !$json.isEmpty() }}","rightValue":"we"},{"id":"0e1b9264-be56-4d0c-a83e-d9ca0b05b265","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"","rightValue":""}]},"looseTypeValidation":true},"executeOnce":false,"typeVersion":2.2,"alwaysOutputData":false},{"id":"557aa2c3-8d0b-42c4-b444-953a538d7ff4","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[-1120,20],"parameters":{"width":1060,"height":600,"content":"## Looping Data And Checking For Is Exist On Database\n**We are checking until find a data we did not insert because we don't want to create content about in same content"},"typeVersion":1},{"id":"9b510f11-9a44-4d54-b162-3ffb55d66677","name":"send error message to telegram","type":"n8n-nodes-base.telegram","position":[-1000,440],"parameters":{"text":"There was a problem execution a postgresql content","chatId":"={{ $('Telegram Params').item.json.telegram_chat_id}}","additionalFields":{}},"credentials":{"telegramApi":{"id":"GcIVVl98RcazYBaB","name":"Telegram account"}},"typeVersion":1.2},{"id":"48bc61de-d416-4673-9e9b-8331ea841891","name":"insert data on db","type":"n8n-nodes-base.postgres","position":[-260,240],"parameters":{"table":{"__rl":true,"mode":"list","value":"top_trends","cachedResultName":"top_trends"},"schema":{"__rl":true,"mode":"list","value":"public"},"columns":{"value":{"tag":"={{$('Loop Over Items').item.json.tag}}","code":"={{$('Loop Over Items').item.json.content_code}}","prompt":"={{$('Loop Over Items').item.json.prompt}}","isposted":false,"thumbnail_url":"={{$('Loop Over Items').item.json.thumbnail_url}}"},"schema":[{"id":"id","type":"number","display":true,"removed":true,"required":false,"displayName":"id","defaultMatch":true,"canBeUsedToMatch":true},{"id":"prompt","type":"string","display":true,"required":true,"displayName":"prompt","defaultMatch":false,"canBeUsedToMatch":true},{"id":"isposted","type":"boolean","display":true,"required":false,"displayName":"isposted","defaultMatch":false,"canBeUsedToMatch":true},{"id":"createdat","type":"dateTime","display":true,"removed":true,"required":false,"displayName":"createdat","defaultMatch":false,"canBeUsedToMatch":true},{"id":"updatedat","type":"dateTime","display":true,"removed":true,"required":false,"displayName":"updatedat","defaultMatch":false,"canBeUsedToMatch":true},{"id":"deletedat","type":"dateTime","display":true,"removed":true,"required":false,"displayName":"deletedat","defaultMatch":false,"canBeUsedToMatch":true},{"id":"code","type":"string","display":true,"required":false,"displayName":"code","defaultMatch":false,"canBeUsedToMatch":true},{"id":"tag","type":"string","display":true,"required":false,"displayName":"tag","defaultMatch":false,"canBeUsedToMatch":true},{"id":"thumbnail_url","type":"string","display":true,"required":false,"displayName":"thumbnail_url","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":["id"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{}},"credentials":{"postgres":{"id":"sBHQ2psBsfnHkFrZ","name":"Postgres account"}},"typeVersion":2.5},{"id":"15e7d69d-a10f-48a1-b240-046e9950d077","name":"Analyze Image and give the content","type":"@n8n/n8n-nodes-langchain.openAi","position":[80,240],"parameters":{"text":"Create a clear and concise description of the object in the image, focusing on its physical and general features. Avoid detailed environmental aspects like background, lighting, or colors. Describe the shape, texture, size, and any unique characteristics of the object. Mention any notable features that make the object stand out, such as its surface details, materials, and design. The description should be focused on the object itself, not its surroundings.\n\nFor example, describe the following image:\n","modelId":{"__rl":true,"mode":"list","value":"gpt-4o-mini","cachedResultName":"GPT-4O-MINI"},"options":{},"resource":"image","imageUrls":"={{ $('Loop Over Items').item.json.thumbnail_url }}","operation":"analyze"},"credentials":{"openAiApi":{"id":"1TwEayhZUT90fq8N","name":"OpenAi account"}},"typeVersion":1.8},{"id":"93e253b1-da7d-4193-b899-a38e6fd9f4e4","name":"Analyze Content And Generate Instagram Caption","type":"@n8n/n8n-nodes-langchain.openAi","position":[280,240],"parameters":{"modelId":{"__rl":true,"mode":"list","value":"gpt-4o-mini","cachedResultName":"GPT-4O-MINI"},"options":{},"messages":{"values":[{"content":"=\nSummarize the following content description into a short, engaging Instagram caption under 150 words. The caption should focus on the content of the image, not the app. Keep it appealing to social media users, and highlight the visual details of the image. Include hashtags relevant to 3D modeling and design, such as #Blender3D, #3DArt, #DigitalArt, #3DModeling, and #ArtCommunity. Ensure the tone is friendly and inviting.\n\n\nContent description to summarize:\n{{ $json.content }}\n\nMake sure to craft the caption around the content's features, such as the color contrast, reflective surface, and artistic nature of the image.\n\n"}]}},"credentials":{"openAiApi":{"id":"1TwEayhZUT90fq8N","name":"OpenAi account"}},"typeVersion":1.8},{"id":"9af1dc59-1d9e-4900-8f80-1eba946c4057","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-20,20],"parameters":{"color":4,"width":860,"height":600,"content":"## Analyze Post Content\n** We are analyzing the image\n** We are generating a instagram caption by content\n** Then we are generating the image"},"typeVersion":1},{"id":"2259f6df-dca9-4a7e-babb-e63375f7207f","name":"Prepare data on Instagram","type":"n8n-nodes-base.facebookGraphApi","position":[980,260],"parameters":{"edge":"media","node":"={{ $('Instagram params').item.json.instagram_business_account_id }}","options":{"queryParameters":{"parameter":[{"name":"image_url","value":"={{ $json.output[0] }}"},{"name":"caption","value":"={{ $('Analyze Content And Generate Instagram Caption').item.json.message.content }}"}]}},"graphApiVersion":"v20.0","httpRequestMethod":"POST"},"credentials":{"facebookGraphApi":{"id":"ZFxxxLfZ25M7Va6r","name":"Facebook Graph account"}},"typeVersion":1},{"id":"bcbb6058-1966-4bb5-915a-1e65b9131117","name":"Check Status Of Media Before Uploaded","type":"n8n-nodes-base.facebookGraphApi","position":[1200,260],"parameters":{"node":"={{ $json.id }}","options":{"fields":{"field":[{"name":"id"},{"name":"status"},{"name":"status_code"}]}},"graphApiVersion":"v20.0"},"credentials":{"facebookGraphApi":{"id":"ZFxxxLfZ25M7Va6r","name":"Facebook Graph account"}},"typeVersion":1},{"id":"518d87ff-7808-4c06-b137-4e97d8f2ca28","name":"Publish Media on Instagram","type":"n8n-nodes-base.facebookGraphApi","position":[1600,100],"parameters":{"edge":"media_publish","node":"={{ $('Instagram params').item.json.instagram_business_account_id }}","options":{"queryParameters":{"parameter":[{"name":"creation_id","value":"={{ $json.id }}"}]}},"graphApiVersion":"v20.0","httpRequestMethod":"POST"},"credentials":{"facebookGraphApi":{"id":"ZFxxxLfZ25M7Va6r","name":"Facebook Graph account"}},"typeVersion":1},{"id":"a033d12b-524f-40e8-9208-5300bbc823d3","name":"Check status of post ","type":"n8n-nodes-base.facebookGraphApi","position":[1800,260],"parameters":{"node":"={{ $('Check Status Of Media Before Uploaded').item.json.id }}","options":{"fields":{"field":[{"name":"id"},{"name":"status"},{"name":"status_code"}]}},"graphApiVersion":"v20.0"},"credentials":{"facebookGraphApi":{"id":"ZFxxxLfZ25M7Va6r","name":"Facebook Graph account"}},"typeVersion":1},{"id":"f136e907-2938-4175-b51f-4201fbe3477d","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[880,20],"parameters":{"color":5,"width":1580,"height":600,"content":"## Publish On Instagram And Send Message When Published via Telegram\n"},"typeVersion":1},{"id":"8145986c-5453-43ac-8d5c-c50a84a62136","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[-1800,100],"parameters":{"color":5,"width":260,"height":500,"content":"## For More About Api\n** [Facebook Scraper Api Guide](https://rapidapi.com/social-api1-instagram/api/instagram-scraper-api2/playground/apiendpoint_a45552b2-9850-4da9-b5cb-bbdd3ac2199d)"},"typeVersion":1},{"id":"02416fbb-4250-4278-af23-1f9189787123","name":"filter the image content-2","type":"n8n-nodes-base.code","position":[-1480,180],"parameters":{"jsCode":"const filteredData = $input.first().json.data.items.filter(item=> !item.is_video)\nreturn filteredData.map((item)=>{\n  return {\n    id: item.id,\n    prompt: item.caption.text,\n    content_code: item.code,\n    thumbnail_url: item.thumbnail_url,\n    tag: $input.first().json.data.additional_data.name\n  }\n})                                                                    \n\n"},"typeVersion":2},{"id":"2d1ea53d-1d32-4b86-8944-ce2ad4a69847","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[-2820,160],"parameters":{"color":5,"width":180,"height":300,"content":"## Guide \n** [Guide](https://replicate.com) of getting  of Replicate Token "},"typeVersion":1},{"id":"c8b933af-356e-49ae-92d3-42eaf4ee3e9f","name":"Replicate params","type":"n8n-nodes-base.set","position":[-2780,300],"parameters":{"options":{},"assignments":{"assignments":[{"id":"1e380c14-e908-4eeb-90e0-957a422829d0","name":"replicate_token","type":"string","value":""}]}},"typeVersion":3.4},{"id":"2c73cc9c-d436-459b-9b3c-bd870810b9b4","name":"Generate image on flux","type":"n8n-nodes-base.httpRequest","position":[680,260],"parameters":{"url":"https://api.replicate.com/v1/models/black-forest-labs/flux-schnell/predictions","method":"POST","options":{},"jsonBody":"={\n  \"input\": {\n    \"prompt\": \"A highly detailed 3D isometric model of {{$('Analyze Image and give the content').item.json.content   .replace(/\\\\n/g, ' ') \n.replace(/\\\\t/g, ' ') \n.replace(/\\s+/g, ' ')\n.trim(); }} rendered in a stylized miniature toy aesthetic. Materials: Matte plastic/painted metal/weathered stone texture with no self-shadowing. Lighting: - Completely shadowless rendering - Ultra bright and perfectly even illumination from all angles - Pure ambient lighting without directional shadows - Flat, consistent lighting across all surfaces - No ambient occlusion. Style specifications: - Clean, defined edges and surfaces - Slightly exaggerated proportions - Miniature/toy-like scale - Subtle wear and texturing - Rich color palette with muted tones - Isometric 3/4 view angle - Crisp details and micro-elements. Technical details: - 4K resolution - PBR materials without shadows - No depth of field - High-quality anti-aliasing - Perfect uniform lighting. Environment: Pure white background with zero shadows or gradients. Post-processing: High key lighting, maximum brightness, shadow removal.\",\n    \"output_format\": \"jpg\",\n    \"output_quality\": 100,\n    \"go_fast\":false\n  }\n}\n","sendBody":true,"sendHeaders":true,"specifyBody":"=json","bodyParameters":{"parameters":[{}]},"headerParameters":{"parameters":[{"name":"Authorization","value":"=Bearer {{ $('Replicate params').item.json.replicate_token}}"},{"name":"Prefer","value":"wait"}]}},"typeVersion":4.2},{"id":"6f9e7dc6-1287-4235-8631-198d729f367f","name":"Sticky Note12","type":"n8n-nodes-base.stickyNote","position":[-1120,-340],"parameters":{"color":4,"width":1060,"height":320,"content":"## For top_trends Table\n```\nCREATE TABLE top_trends (\n    id SERIAL PRIMARY KEY,\n    isposted BOOLEAN DEFAULT false,\n    createdat TIMESTAMP WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP,\n    updatedat TIMESTAMP WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP,\n    deletedat TIMESTAMP WITHOUT TIME ZONE,\n    prompt TEXT NOT NULL,\n    thumbnail_url TEXT,\n    code TEXT,\n    tag TEXT\n);\n```"},"typeVersion":1},{"id":"b19951bb-6346-44a7-a4c8-1bd0806c6019","name":"Sticky Note13","type":"n8n-nodes-base.stickyNote","position":[-660,-120],"parameters":{"color":3,"width":160,"height":120,"content":"## Warning\n** Don't forgot the create top_trends table"},"typeVersion":1},{"id":"3de6b8e5-c5e0-4999-871a-c349cb9b3ac0","name":"Sticky Note14","type":"n8n-nodes-base.stickyNote","position":[-3180,-940],"parameters":{"width":620,"height":840,"content":"\n## Automated Instagram Content Creation from Trending Posts\n\nThis workflow automates the process of discovering and recreating trending content on Instagram:\n\n1. Content Discovery:\n   - Scrapes top trending posts from specific hashtags (#blender3d, #isometric)\n   - Filters for image-only content (excludes videos)\n   - Checks database to avoid duplicate content\n\n2. AI-Powered Content Generation:\n   - Analyzes trending images using GPT-4 Vision\n   - Generates detailed descriptions of visual elements\n   - Creates engaging Instagram captions with relevant hashtags\n   - Uses Flux AI to generate similar but unique images\n\n3. Publishing & Monitoring:\n   - Automatically posts content to Instagram Business Account\n   - Monitors post status and publishing process\n   - Sends status updates via Telegram\n\nPerfect for content creators and businesses looking to maintain an active Instagram presence with AI-generated content inspired by current trends. The workflow runs on schedule and handles everything from content discovery to publication automatically.\n\nNote: Requires Instagram Business Account, Telegram Bot, OpenAI, and Replicate API credentials."},"typeVersion":1},{"id":"dfd0d182-177c-4336-8950-4792ea739123","name":"Sticky Note15","type":"n8n-nodes-base.stickyNote","position":[-2120,480],"parameters":{"color":7,"width":180,"height":120,"content":"##Warning\n** Dont forgot the subscribe [Instagram Scraper Api](https://rapidapi.com/social-api1-instagram/api/instagram-scraper-api2/playground/apiendpoint_a45552b2-9850-4da9-b5cb-bbdd3ac2199d)"},"typeVersion":1},{"id":"03330941-3c6e-4152-8c51-f1d53f4424bc","name":"Sticky Note16","type":"n8n-nodes-base.stickyNote","position":[-2120,640],"parameters":{"width":180,"height":180,"content":"## Warning\n** You can check the  [rate limit](https://rapidapi.com/social-api1-instagram/api/instagram-scraper-api2) of the Instagram Scraper Api on Rapid Api\n** Free version is monthly 500 request\n"},"typeVersion":1}],"active":false,"settings":{"timezone":"Europe/Istanbul","callerPolicy":"workflowsFromSameOwner","executionOrder":"v1"},"versionId":"cc50f9e8-373b-433a-af43-824a264e762a","connections":{"Telegram":{"main":[[]]},"Loop Over Items":{"main":[[],[{"node":"Check Data on Database Is Exist","type":"main","index":0}]]},"Telegram Params":{"main":[[{"node":"Rapid Api params","type":"main","index":0}]]},"If Data is Exist":{"main":[[{"node":"Loop Over Items","type":"main","index":0}],[{"node":"insert data on db","type":"main","index":0}]]},"Instagram params":{"main":[[{"node":"Telegram Params","type":"main","index":0}]]},"Rapid Api params":{"main":[[{"node":"get top trends on instagram #isometric","type":"main","index":0},{"node":"get  top trends on instagram #blender3d","type":"main","index":0}]]},"Replicate params":{"main":[[{"node":"Instagram params","type":"main","index":0}]]},"Schedule Trigger1":{"main":[[{"node":"Replicate params","type":"main","index":0}]]},"insert data on db":{"main":[[{"node":"Analyze Image and give the content","type":"main","index":0}]]},"Check status of post ":{"main":[[{"node":"If media status is finished1","type":"main","index":0}]]},"Generate image on flux":{"main":[[{"node":"Prepare data on Instagram","type":"main","index":0}]]},"merge the array content":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"filter the image content":{"main":[[{"node":"merge the array content","type":"main","index":1}]]},"Prepare data on Instagram":{"main":[[{"node":"Check Status Of Media Before Uploaded","type":"main","index":0}]]},"Publish Media on Instagram":{"main":[[{"node":"Check status of post ","type":"main","index":0}]]},"filter the image content-2":{"main":[[{"node":"merge the array content","type":"main","index":0}]]},"If media status is finished":{"main":[[{"node":"Publish Media on Instagram","type":"main","index":0}],[{"node":"Telegram","type":"main","index":0}]]},"If media status is finished1":{"main":[[{"node":"Telegram1","type":"main","index":0}],[{"node":"Telegram2","type":"main","index":0}]]},"Check Data on Database Is Exist":{"main":[[{"node":"If Data is Exist","type":"main","index":0}],[{"node":"send error message to telegram","type":"main","index":0}]]},"Analyze Image and give the content":{"main":[[{"node":"Analyze Content And Generate Instagram Caption","type":"main","index":0}]]},"Check Status Of Media Before Uploaded":{"main":[[{"node":"If media status is finished","type":"main","index":0}]]},"get top trends on instagram #isometric":{"main":[[{"node":"filter the image content","type":"main","index":0}]]},"get  top trends on instagram #blender3d":{"main":[[{"node":"filter the image content-2","type":"main","index":0}]]},"Analyze Content And Generate Instagram Caption":{"main":[[{"node":"Generate image on flux","type":"main","index":0}]]}}}


name: Automate Content Generator for WordPress with DeepSeek R1
author_name: Davide
author_username: n3witalia
categories: []
created_at: 2025-01-28T11:15:09.521Z
updated_at: 2025-01-28T11:15:09.521Z
url: https://n8n.io/workflows/2813
scraped_at: 2025-07-06 21:16:30
description:
  This workflow is designed to generate SEO-friendly content with DeepSeek R1 (or V3), publish it on WordPress, and update a Google Sheets document with the details of the created post. Below is a detailed analysis of what each node in the workflow does:

  How It Works
  Triggering the Workflow:
     The workflow starts with a Manual Trigger node, which is activated when the user clicks "Test workflow" in the n8n interface.

  Fetching Data:
     The Get Ideas node retrieves data from a Google Sheets document. It reads a specific sheet and filters the data based on the "ID POST" column, returning the first matching row.

  Setting the Prompt:
     The Set your prompt node extracts the PROMPT field from the Google Sheets data and assigns it to a variable for use in subsequent steps.

  Generating Content:
     The Generate article node uses an AI model (DeepSeek) to create an SEO-friendly article based on the prompt. The article includes an introduction, 2-3 chapters, and a conclusion, formatted in HTML.
     The Generate title node uses the same AI model to generate a concise, SEO-optimized title for the article.

  Publishing on WordPress:
     The Create post on WordPress node creates a new draft post on WordPress using the generated title and article content.

  Generating and Uploading an Image:
     The Generate Image node creates a photorealistic image based on the article title using an AI model (OpenAI).
     The Upload image node uploads the generated image to WordPress as a media file.
     The Set Image node assigns the uploaded image as the featured image for the WordPress post.

  Updating Google Sheets:
     The Update Sheet node updates the original Google Sheets document with the post details, including the title, post ID, creation date, and row number.

  Set Up Steps
  Configure Google Sheets Integration:
     Set up the Google Sheets node to connect to your Google account and specify the document ID and sheet name to read from and update.

  Set Up AI Models:
     Configure the OpenAI nodes (for generating the article, title, and image) with the appropriate API credentials and model settings (e.g., deepseek-reasoner for text generation).

  Configure WordPress Integration:
     Set up the WordPress node with your WordPress site's API credentials to allow creating posts and uploading media.

  Define the Prompt and Content Structure:
     In the Set your prompt node, ensure the prompt variable is correctly mapped to the data from Google Sheets.
     In the Generate article and Generate title nodes, define the instructions for the AI model to generate the desired content.

  Set Up Image Generation:
     Configure the Generate Image node with the appropriate prompt and image settings (e.g., size, quality, style).

  Configure HTTP Requests for Media Upload:
     Set up the Upload image and Set Image nodes to use the WordPress REST API for uploading and assigning the featured image.

  Map Data for Google Sheets Update:
     In the Update Sheet node, map the relevant fields (e.g., title, post ID, date) to the appropriate columns in the Google Sheets document.

  Test and Activate the Workflow:
     Run the workflow manually to ensure all steps execute correctly.
     Once verified, activate the workflow for automated execution.

  Overall purpose of the workflow
  This workflow automates the creation of SEO-friendly content for a WordPress blog. Starting from a prompt extracted from a Google Sheets document, it generates an article, a title, and an image, publishes the post on WordPress, and updates the Google Sheets document with the details of the created post. This process is useful for blog managers who want to automate content creation and publishing.

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

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

workflow_json:
  {"id":"p5bfwpcRy6LK33Io","meta":{"instanceId":"a4bfc93e975ca233ac45ed7c9227d84cf5a2329310525917adaf3312e10d5462","templateCredsSetupCompleted":true},"name":"Automate Content Generator for WordPress with DeepSeek R1","tags":[],"nodes":[{"id":"c4a6995f-7769-4b77-80ca-1e6bccef77c1","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-20,200],"parameters":{},"typeVersion":1},{"id":"c76b1458-5130-41e7-b2f2-1cfe22eab536","name":"Get Ideas","type":"n8n-nodes-base.googleSheets","position":[200,200],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"id","value":"=Sheet1"},"documentId":{"__rl":true,"mode":"id","value":"YOURDOCUMENT"}},"credentials":{"googleSheetsOAuth2Api":{"id":"JYR6a64Qecd6t8Hb","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"8d17a640-3e15-42e9-9481-e3291d395ccd","name":"Set your prompt","type":"n8n-nodes-base.set","position":[420,200],"parameters":{"options":{},"assignments":{"assignments":[{"id":"3e8d2523-66aa-46fe-adcc-39dc78b9161e","name":"prompt","type":"string","value":"={{ $json.PROMPT }}"}]}},"typeVersion":3.4},{"id":"4f0e9065-b331-49ed-acd9-77c7c43e89a5","name":"Create post on Wordpress","type":"n8n-nodes-base.wordpress","position":[0,500],"parameters":{"title":"={{ $json.message.content }}","additionalFields":{"status":"draft","content":"={{ $('Generate article with DeepSeek').item.json.message.content }}"}},"credentials":{"wordpressApi":{"id":"OE4AgquSkMWydRqn","name":"Wordpress (wp.test.7hype.com)"}},"typeVersion":1},{"id":"cb85d980-9d60-4c85-8574-b46e4cc14341","name":"Upload image","type":"n8n-nodes-base.httpRequest","position":[420,500],"parameters":{"url":"https://YOURSITE.com/wp-json/wp/v2/media","method":"POST","options":{},"sendBody":true,"contentType":"binaryData","sendHeaders":true,"authentication":"predefinedCredentialType","headerParameters":{"parameters":[{"name":"Content-Disposition","value":"=attachment; filename=\"copertina-{{ $('Create post on Wordpress').item.json.id }}.jpg\""}]},"inputDataFieldName":"data","nodeCredentialType":"wordpressApi"},"credentials":{"wordpressApi":{"id":"OE4AgquSkMWydRqn","name":"Wordpress (wp.test.7hype.com)"},"wooCommerceApi":{"id":"vYYrjB5kgHQ0XByZ","name":"WooCommerce (wp.test.7hype.com)"}},"typeVersion":4.2},{"id":"bc71ed8a-fe35-487a-b4cd-6b8c1b256763","name":"Set Image","type":"n8n-nodes-base.httpRequest","position":[640,500],"parameters":{"url":"=https://wp.test.7hype.com/wp-json/wp/v2/posts/{{ $('Create post on Wordpress').item.json.id }}","method":"POST","options":{},"sendQuery":true,"authentication":"predefinedCredentialType","queryParameters":{"parameters":[{"name":"featured_media","value":"={{ $json.id }}"}]},"nodeCredentialType":"wordpressApi"},"credentials":{"wordpressApi":{"id":"OE4AgquSkMWydRqn","name":"Wordpress (wp.test.7hype.com)"}},"typeVersion":4.2},{"id":"fbed2813-cc64-42a2-994f-3696e9d8d8fe","name":"Update Sheet","type":"n8n-nodes-base.googleSheets","position":[880,500],"parameters":{"columns":{"value":{"DATA":"={{ $now.format('dd/LL/yyyy') }}","TITOLO":"={{ $('Generate title with DeepSeek').item.json.message.content }}","ID POST":"={{ $('Create post on Wordpress').item.json.id }}","row_number":"={{ $('Get Ideas').item.json.row_number }}"},"schema":[{"id":"DATA","type":"string","display":true,"required":false,"displayName":"DATA","defaultMatch":false,"canBeUsedToMatch":true},{"id":"PROMPT","type":"string","display":true,"required":false,"displayName":"PROMPT","defaultMatch":false,"canBeUsedToMatch":true},{"id":"TITOLO","type":"string","display":true,"required":false,"displayName":"TITOLO","defaultMatch":false,"canBeUsedToMatch":true},{"id":"ID POST","type":"string","display":true,"required":false,"displayName":"ID POST","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":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/16VFeCrE5BkMBoA_S5HD-9v7C0sxcXAUiDbq5JvkDqnI/edit#gid=0","cachedResultName":"Foglio1"},"documentId":{"__rl":true,"mode":"list","value":"16VFeCrE5BkMBoA_S5HD-9v7C0sxcXAUiDbq5JvkDqnI","cachedResultUrl":"https://docs.google.com/spreadsheets/d/16VFeCrE5BkMBoA_S5HD-9v7C0sxcXAUiDbq5JvkDqnI/edit?usp=drivesdk","cachedResultName":"Plan Blog wp.test.7hype.com"}},"credentials":{"googleSheetsOAuth2Api":{"id":"JYR6a64Qecd6t8Hb","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"8db2b0cb-6d61-4e2d-bfac-e25a0385296d","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-60,-360],"parameters":{"color":3,"width":800,"height":380,"content":"## Target\nThis workflow is designed to automatically generate seo-friendly content for wordpress through DeepSeek R1 by giving input ideas on how to structure the article. A cover image is also generated and uploaded with OpenAI DALL-E 3. This flow is designed to be executed automatically (ad \"On a schedule\" node) and thus have a complete editorial plan.\n\nThis process is useful for blog managers who want to automate content creation and publishing.\n\n## Preliminary step\nCreate a google sheet with the following columns:\n- Date\n- Prompt\n- Title\n- Post ID\n\nFill in only the \"Prompt\" column with basic ideas that DeepSeek will work on to generate the content."},"typeVersion":1},{"id":"ab620659-558d-46f0-ab85-e061af99b743","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[140,100],"parameters":{"height":260,"content":"Connect with your Google Sheet. This node select only rows for which no content has been generated yet in WordPress"},"typeVersion":1},{"id":"73b0e640-8ccf-4e29-a0cd-6340db907bbd","name":"Generate article with DeepSeek","type":"@n8n/n8n-nodes-langchain.openAi","position":[640,200],"parameters":{"modelId":{"__rl":true,"mode":"id","value":"=deepseek-reasoner"},"options":{"maxTokens":2048},"messages":{"values":[{"content":"=You are an SEO expert, write an article based on this topic:\n{{ $json.prompt }}\n\nInstructions:\n- In the introduction, introduce the topic that will be explored in the rest of the text\n- The introduction should be about 120 words\n- The conclusions should be about 120 words\n- Use the conclusions to summarize everything said in the article and offer a conclusion to the reader\n- Write a maximum of 4-5 chapters and argue them.\n- The chapters should follow a logical flow and not repeat the same concepts.\n- The chapters should be related to each other and not isolated blocks of text. The text should flow and follow a linear logic.\n- Do not start chapters with \"Chapter 1\", \"Chapter 2\", \"Chapter 3\" ... write only the chapter title\n- For the text, use HTML for formatting, but limit yourself to bold, italics, paragraphs and lists.\n- Don't put the output in ```html but only text\n- Don't use markdown for formatting.\n- Go deeper into the topic you're talking about, don't just throw superficial information there\n- In output I want only the HTML format"}]}},"credentials":{"openAiApi":{"id":"97Cz4cqyiy1RdcQL","name":"DeepSeek"}},"typeVersion":1.8},{"id":"6ef4e0d1-6123-4f47-94fb-c06c785ddd92","name":"Generate title with DeepSeek","type":"@n8n/n8n-nodes-langchain.openAi","position":[880,200],"parameters":{"modelId":{"__rl":true,"mode":"id","value":"=deepseek-reasoner"},"options":{"maxTokens":2048},"messages":{"values":[{"content":"=You are an SEO Copywriter and you need to think of a title of maximum 60 characters for the following article:\n{{ $json.message.content }}\n\nInstructions:\n- Use keywords contained in the article\n- Do not use any HTML characters\n- Output only the string containing the title.\n- Do not use quotation marks. The only special characters allowed are \":\" and \",\""}]}},"credentials":{"openAiApi":{"id":"97Cz4cqyiy1RdcQL","name":"DeepSeek"}},"typeVersion":1.8},{"id":"2ecc8514-c04e-4f8b-9ab3-560f2cf910b0","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[580,100],"parameters":{"width":420,"height":260,"content":"Add your DeepSeek API credential. If you want you can change the model with \"deepseek-chat\""},"typeVersion":1},{"id":"196f7799-a6ab-429b-afd3-bcbcbd65da3b","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-20,420],"parameters":{"width":160,"height":260,"content":"Add your WordPress API credential\n"},"typeVersion":1},{"id":"93c2d359-531a-4cc9-8a18-870c2d6ec62c","name":"Generate Image with DALL-E","type":"@n8n/n8n-nodes-langchain.openAi","position":[200,500],"parameters":{"prompt":"=Generate a real photographic image used as a cover for a blog post:\n\nImage prompt:\n{{ $('Generate title with DeepSeek').item.json.message.content }}, photography, realistic, sigma 85mm f/1.4","options":{"size":"1792x1024","style":"natural","quality":"hd"},"resource":"image"},"credentials":{"openAiApi":{"id":"CDX6QM4gLYanh0P4","name":"OpenAi account"}},"typeVersion":1.8},{"id":"eec14cd7-fb2b-4f7d-ad94-bcffc1249353","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[180,420],"parameters":{"width":160,"height":260,"content":"Add your OpenAI API credential\n"},"typeVersion":1},{"id":"4f15679b-bc8f-45b8-b3c4-8b43d7f9bb6f","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[380,420],"parameters":{"width":180,"height":260,"content":"Upload the image on your WordPress via APIs\n"},"typeVersion":1},{"id":"abe32434-671a-4ac3-a788-fcf5fd0e9435","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[600,420],"parameters":{"width":180,"height":260,"content":"Set the uploaded image with the newly created article\n"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"315cc8df-bca2-4180-806e-a01407dccc79","connections":{"Get Ideas":{"main":[[{"node":"Set your prompt","type":"main","index":0}]]},"Set Image":{"main":[[{"node":"Update Sheet","type":"main","index":0}]]},"Upload image":{"main":[[{"node":"Set Image","type":"main","index":0}]]},"Set your prompt":{"main":[[{"node":"Generate article with DeepSeek","type":"main","index":0}]]},"Create post on Wordpress":{"main":[[{"node":"Generate Image with DALL-E","type":"main","index":0}]]},"Generate Image with DALL-E":{"main":[[{"node":"Upload image","type":"main","index":0}]]},"Generate title with DeepSeek":{"main":[[{"node":"Create post on Wordpress","type":"main","index":0}]]},"Generate article with DeepSeek":{"main":[[{"node":"Generate title with DeepSeek","type":"main","index":0}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"Get Ideas","type":"main","index":0}]]}}}


name: Complete business WhatsApp AI-Powered RAG Chatbot using OpenAI
author_name: Davide
author_username: n3witalia
categories: []
created_at: 2025-02-04T10:29:23.985Z
updated_at: 2025-02-04T10:29:23.985Z
url: https://n8n.io/workflows/2845
scraped_at: 2025-07-06 21:16:30
description:
  The provided workflow in n8n is designed to create a Business WhatsApp AI RAG (Retrieval-Augmented Generation) Chatbot.

  How it works:
  Webhook Setup: The workflow begins by setting up webhooks for verification and response. The Verify webhook receives GET requests and sends back a verification code, while the Respond webhook handles incoming POST requests from Meta regarding WhatsApp messages.
  Message Handling: Once a message is received, the workflow checks if the incoming JSON contains a user message. If it does, the message is processed further; otherwise, a generic response is sent.
  AI Agent Interaction: The user's message is passed to the AI Agent node, which uses a conversational agent with a predefined system message tailored for an electronics store. This ensures that the AI provides accurate and professional responses based on the knowledge base.
  Knowledge Base Utilization: The AI Agent references a knowledge base stored in Qdrant, a vector database. Documents from Google Drive are downloaded, vectorized using OpenAI embeddings, and stored in Qdrant for retrieval during conversations.
  Response Generation: The AI Agent generates a response using the OpenAI chat model (gpt-4o-mini) and sends it back to the user via WhatsApp.

  Set up steps:
  Create Qdrant Collection:
     Update the QDRANTURL and COLLECTION variables in the workflow.
     Use the Create collection HTTP request node to initialize the collection in Qdrant.

  Vectorize Documents:
     Configure the Get folder and Download Files nodes to fetch documents from a specified Google Drive folder.
     Use the Embeddings OpenAI node to generate embeddings for the downloaded files.
     Store the vectorized documents in Qdrant using the Qdrant Vector Store node.

  Configure Webhooks:
     Ensure both Verify and Respond webhooks have the same URL.
     Set the Verify webhook to use the GET HTTP method and the Respond webhook to use the POST HTTP method.

  Set Up AI Agent:
     Define the system prompt for the AI Agent, specifying guidelines for product information, technical support, customer service, and knowledge base usage.
     Link the AI Agent to the OpenAI chat model and configure any additional tools as needed.

  Test Workflow:
     Trigger the workflow manually using the When clicking ‘Test workflow’ node to ensure all components are functioning correctly.
     Monitor the flow of data through the nodes and verify that responses are being generated and sent accurately.

  By following these steps, the workflow will be fully operational, enabling a robust AI-powered chatbot capable of handling customer inquiries via WhatsApp.

  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.whatsApp","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.embeddingsOpenAi","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.memoryBufferWindow","@n8n/n8n-nodes-langchain.textSplitterTokenSplitter","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.vectorStoreQdrant","@n8n/n8n-nodes-langchain.toolVectorStore"]

workflow_json:
  {"id":"NLOITjwt4iZK16Qq","meta":{"instanceId":"a4bfc93e975ca233ac45ed7c9227d84cf5a2329310525917adaf3312e10d5462","templateCredsSetupCompleted":true},"name":"Business WhatsApp AI RAG Chatbot","tags":[],"nodes":[{"id":"5be03c5c-e02d-4770-b0db-795dff0bf84f","name":"Respond to Webhook","type":"n8n-nodes-base.respondToWebhook","position":[-60,1140],"parameters":{"options":{},"respondWith":"text","responseBody":"={{ $json.query['hub.challenge'] }}"},"typeVersion":1.1},{"id":"8e24d1bc-8e65-4562-8cc4-4ce9c917841b","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[480,1480],"parameters":{"text":"={{ $('Respond').item.json.body.entry[0].changes[0].value.messages[0].text.body }}","agent":"conversationalAgent","options":{"systemMessage":"You are an AI-powered assistant for an electronics store. Your primary goal is to assist customers by providing accurate and helpful information about products, troubleshooting tips, and general support. Use the provided knowledge base (retrieved documents) to answer questions with precision and professionalism.\n\n**Guidelines**:\n1. **Product Information**:\n   - Provide detailed descriptions of products, including specifications, features, and compatibility.\n   - Highlight key selling points and differences between similar products.\n   - Mention availability, pricing, and promotions if applicable.\n\n2. **Technical Support**:\n   - Offer step-by-step troubleshooting guides for common issues.\n   - Suggest solutions for setup, installation, or configuration problems.\n   - If the issue is complex, recommend contacting the store’s support team for further assistance.\n\n3. **Customer Service**:\n   - Respond politely and professionally to all inquiries.\n   - If a question is unclear, ask for clarification to provide the best possible answer.\n   - For order-related questions (e.g., status, returns, or cancellations), guide customers on how to proceed using the store’s systems.\n\n4. **Knowledge Base Usage**:\n   - Always reference the provided knowledge base (retrieved documents) to ensure accuracy.\n   - If the knowledge base does not contain relevant information, inform the customer and suggest alternative resources or actions.\n\n5. **Tone and Style**:\n   - Use a friendly, approachable, and professional tone.\n   - Avoid technical jargon unless the customer demonstrates familiarity with the topic.\n   - Keep responses concise but informative.\n\n**Example Interactions**:\n1. **Product Inquiry**:\n   - Customer: \"What’s the difference between the XYZ Smartwatch and the ABC Smartwatch?\"\n   - AI: \"The XYZ Smartwatch features a longer battery life (up to 7 days) and built-in GPS, while the ABC Smartwatch has a brighter AMOLED display and supports wireless charging. Both are compatible with iOS and Android devices. Would you like more details on either product?\"\n\n2. **Technical Support**:\n   - Customer: \"My wireless router isn’t connecting to the internet.\"\n   - AI: \"Please try the following steps: 1) Restart your router and modem. 2) Ensure all cables are securely connected. 3) Check if the router’s LED indicators show a stable connection. If the issue persists, you may need to reset the router to factory settings. Would you like a detailed guide for resetting your router?\"\n\n3. **Customer Service**:\n   - Customer: \"How do I return a defective product?\"\n   - AI: \"To return a defective product, please visit our Returns Portal on our website and enter your order number. You’ll receive a return label and instructions. If you need further assistance, our support team is available at support@electronicsstore.com.\"\n\n**Limitations**:\n- If the question is outside the scope of the knowledge base or requires human intervention, inform the customer and provide contact details for the appropriate department.\n- Do not provide speculative or unverified information. Always rely on the knowledge base or direct the customer to official resources."},"promptType":"define"},"typeVersion":1.7},{"id":"22fe09e5-053c-4f80-9e44-71f533492e31","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-340,1360],"parameters":{"width":459,"height":485,"content":"# STEP 4\n\n## RAG System\n\n\n\n\n\n\n\n\n\n\n\n\n\n* *Respond* webhook receives various POST Requests from Meta regarding WhatsApp messages (user messages + status notifications)\n* Check if the incoming JSON contains user message\n* Echo back the text message to the user. This is a custom message, not a WhatsApp Business template message\n"},"typeVersion":1},{"id":"cfed3c49-be8a-4d1a-aa3a-5e60a19c00ac","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[480,1680],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"CDX6QM4gLYanh0P4","name":"OpenAi account"}},"typeVersion":1.2},{"id":"55970db5-284d-40b9-ad6f-f43b513aac45","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-620,200],"parameters":{},"typeVersion":1},{"id":"99de11b0-ab4a-49fe-977b-b3102c9ff1cf","name":"Qdrant Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStoreQdrant","position":[360,320],"parameters":{"mode":"insert","options":{},"qdrantCollection":{"__rl":true,"mode":"list","value":""}},"credentials":{"qdrantApi":{"id":"iyQ6MQiVaF3VMBmt","name":"QdrantApi account"}},"typeVersion":1},{"id":"619d2d2f-7a1e-49ba-a3ae-24bf24287dd2","name":"Create collection","type":"n8n-nodes-base.httpRequest","position":[-320,60],"parameters":{"url":"https://QDRANTURL/collections/COLLECTION","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":"b61d5d74-14d2-4488-a0d6-3f7df9745329","name":"Refresh collection","type":"n8n-nodes-base.httpRequest","position":[-320,320],"parameters":{"url":"https://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":"71c8817f-f5be-4900-aecc-14d483993c4c","name":"Get folder","type":"n8n-nodes-base.googleDrive","position":[-100,320],"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":"id","value":"=test-whatsapp"}},"options":{},"resource":"fileFolder"},"credentials":{"googleDriveOAuth2Api":{"id":"HEy5EuZkgPZVEa9w","name":"Google Drive account (n3w.it)"}},"typeVersion":3},{"id":"c14e570d-527d-4cc2-b0c0-2406b814ffc6","name":"Download Files","type":"n8n-nodes-base.googleDrive","position":[120,320],"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":"7f1ffbd5-7aa0-49d3-aa11-9568ac704d6e","name":"Embeddings OpenAI","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[340,520],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"CDX6QM4gLYanh0P4","name":"OpenAi account"}},"typeVersion":1.1},{"id":"bdc58292-5880-41b9-bc55-d6437f037629","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[520,520],"parameters":{"options":{},"dataType":"binary"},"typeVersion":1},{"id":"7df52ba0-011e-44a5-b25d-a4610f903ed9","name":"Token Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterTokenSplitter","position":[480,680],"parameters":{"chunkSize":300,"chunkOverlap":30},"typeVersion":1},{"id":"b3306890-d527-44d9-bd42-2decd61b35a2","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-880,1240],"parameters":{"color":3,"width":405,"height":177,"content":"## Important!\n### Configure the webhook nodes this way:\n* Make sure that both *Verify* and *Respond* have the same URL\n* *Verify* should have GET HTTP Method\n* *Respond* should have POST HTTP Method"},"typeVersion":1},{"id":"2da39c54-1596-4674-99c5-8fdac7873ea3","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-340,900],"parameters":{"color":5,"width":618,"height":392,"content":"# STEP 3\n\n## Create Webhook\n* Go to your [Meta for Developers App page](https://developers.facebook.com/apps/), navigate to the App settings\n* Add a **production webhook URL** as a new Callback URL\n* *Verify* webhook receives a GET Request and sends back a verification code\n* After that you can delete this\n"},"typeVersion":1},{"id":"9c8a18df-d2a9-4d91-a799-a8ee6c5160ba","name":"Verify","type":"n8n-nodes-base.webhook","position":[-300,1140],"webhookId":"f0d2e6f6-8fda-424d-b377-0bd191343c20","parameters":{"path":"f0d2e6f6-8fda-424d-b377-0bd191343c20","options":{},"responseMode":"responseNode"},"typeVersion":2},{"id":"1ca39545-9ec1-489d-bcaf-f6289163d3e0","name":"Respond","type":"n8n-nodes-base.webhook","position":[-320,1520],"webhookId":"f0d2e6f6-8fda-424d-b377-0bd191343c20","parameters":{"path":"f0d2e6f6-8fda-424d-b377-0bd191343c20","options":{},"httpMethod":"POST"},"typeVersion":2},{"id":"02ae9009-b34b-49a5-86f2-50e681125d77","name":"is Message?","type":"n8n-nodes-base.if","position":[-100,1520],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"959fbffc-876a-4235-87be-2dedba4926cd","operator":{"type":"object","operation":"exists","singleValue":true},"leftValue":"={{ $json.body.entry[0].changes[0].value.messages[0] }}","rightValue":""}]},"looseTypeValidation":true},"typeVersion":2.2},{"id":"9f866e16-cedb-4c43-ab38-e0e53703402a","name":"Only message","type":"n8n-nodes-base.whatsApp","position":[200,1620],"parameters":{"textBody":"=You can only send text messages","operation":"send","phoneNumberId":"470271332838881","requestOptions":{},"additionalFields":{},"recipientPhoneNumber":"={{ $('Respond').item.json.body.entry[0].changes[0].value.contacts[0].wa_id }}"},"credentials":{"whatsAppApi":{"id":"HDUOWQXeRXMVjo0Z","name":"WhatsApp account"}},"typeVersion":1},{"id":"3867b8c8-db5f-40f6-b3ae-edf1ab732395","name":"Send","type":"n8n-nodes-base.whatsApp","position":[900,1480],"parameters":{"textBody":"={{ $json.output }}","operation":"send","phoneNumberId":"470271332838881","requestOptions":{},"additionalFields":{},"recipientPhoneNumber":"={{ $('Respond').item.json.body.entry[0].changes[0].value.contacts[0].wa_id }}"},"credentials":{"whatsAppApi":{"id":"HDUOWQXeRXMVjo0Z","name":"WhatsApp account"}},"typeVersion":1},{"id":"401a8204-4cea-4bd0-9ae7-8c5c6797c586","name":"Window Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[640,1720],"parameters":{},"typeVersion":1.3},{"id":"ff1ebe0d-b572-4b77-ad67-351c0ec17927","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-120,0],"parameters":{"color":6,"width":880,"height":220,"content":"# STEP 1\n\n## Create Qdrant Collection\nChange:\n- QDRANTURL\n- COLLECTION"},"typeVersion":1},{"id":"df7bc44c-fb7d-4bc4-bc79-245f53e17eca","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-340,260],"parameters":{"color":4,"width":620,"height":400,"content":"# STEP 2\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":"df4f90ab-1cbb-4335-893a-0f3e2a62be04","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[440,1360],"parameters":{"width":380,"height":260,"content":"## Configure AI Agent\nSet System prompt and chat model. If you want you can set any tools"},"typeVersion":1},{"id":"b0928ee4-2c6a-4bc0-a013-15504f157379","name":"OpenAI Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[980,1920],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"CDX6QM4gLYanh0P4","name":"OpenAi account"}},"typeVersion":1.2},{"id":"16ca729c-9492-4af1-a02f-9b3e5b4ebc43","name":"Retrive Qdrant Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStoreQdrant","position":[620,1940],"parameters":{"options":{},"qdrantCollection":{"__rl":true,"mode":"id","value":"COLLECTION"}},"credentials":{"qdrantApi":{"id":"iyQ6MQiVaF3VMBmt","name":"QdrantApi account"}},"typeVersion":1},{"id":"c950482d-23e3-4318-a878-f80f8cfee556","name":"Embeddings OpenAI2","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[500,2140],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"CDX6QM4gLYanh0P4","name":"OpenAi account"}},"typeVersion":1.2},{"id":"46347cfc-b4e7-4627-a991-3f30c12d7f42","name":"RAG","type":"@n8n/n8n-nodes-langchain.toolVectorStore","position":[840,1700],"parameters":{"name":"company_data","description":"Retrive data about company knowledge from vector store"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"b760b44b-24d8-41c6-8251-c7e6ddac82c1","connections":{"RAG":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"Verify":{"main":[[{"node":"Respond to Webhook","type":"main","index":0}]]},"Respond":{"main":[[{"node":"is Message?","type":"main","index":0}]]},"AI Agent":{"main":[[{"node":"Send","type":"main","index":0}]]},"Get folder":{"main":[[{"node":"Download Files","type":"main","index":0}]]},"is Message?":{"main":[[{"node":"AI Agent","type":"main","index":0}],[{"node":"Only message","type":"main","index":0}]]},"Download Files":{"main":[[{"node":"Qdrant Vector Store","type":"main","index":0}]]},"Token Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader","type":"ai_textSplitter","index":0}]]},"Embeddings OpenAI":{"ai_embedding":[[{"node":"Qdrant Vector Store","type":"ai_embedding","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Embeddings OpenAI2":{"ai_embedding":[[{"node":"Retrive Qdrant Vector Store","type":"ai_embedding","index":0}]]},"OpenAI Chat Model1":{"ai_languageModel":[[{"node":"RAG","type":"ai_languageModel","index":0}]]},"Refresh collection":{"main":[[{"node":"Get folder","type":"main","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"Qdrant Vector Store","type":"ai_document","index":0}]]},"Window Buffer Memory":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"Retrive Qdrant Vector Store":{"ai_vectorStore":[[{"node":"RAG","type":"ai_vectorStore","index":0}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"Create collection","type":"main","index":0},{"node":"Refresh collection","type":"main","index":0}]]}}}


name: AI Voice Chatbot with ElevenLabs & OpenAI for Customer Service and Restaurants
author_name: Davide
author_username: n3witalia
categories: []
created_at: 2025-02-04T13:13:55.888Z
updated_at: 2025-02-04T13:13:55.888Z
url: https://n8n.io/workflows/2846
scraped_at: 2025-07-06 21:16:30
description:
  The "Voice RAG Chatbot with ElevenLabs and OpenAI" workflow in n8n is designed to create an interactive voice-based chatbot system that leverages both text and voice inputs for providing information. Ideal for shops, commercial activities and restaurants

  How it works:

  Here's how it operates:

  Webhook Activation: The process begins when a user interacts with the voice agent set up on ElevenLabs, triggering a webhook in n8n. This webhook sends a question from the user to the AI Agent node.
  AI Agent Processing: Upon receiving the query, the AI Agent node processes the input using predefined prompts and tools. It extracts relevant information from the knowledge base stored within the Qdrant vector database.
  Knowledge Base Retrieval: The Vector Store Tool node interfaces with the Qdrant Vector Store to retrieve pertinent documents or data segments matching the user’s query.
  Text Generation: Using the retrieved information, the OpenAI Chat Model generates a coherent response tailored to the user’s question.
  Response Delivery: The generated response is sent back through another webhook to ElevenLabs, where it is converted into speech and delivered audibly to the user.
  Continuous Interaction: For ongoing conversations, the Window Buffer Memory ensures context retention by maintaining a history of interactions, enhancing the conversational flow.

  Set up steps:

  To configure this workflow effectively, follow these detailed setup instructions:

  ElevenLabs Agent Creation:
     Begin by creating an agent on ElevenLabs (e.g., named 'test_n8n').
     Customize the first message and define the system prompt specific to your use case, such as portraying a character like a waiter at "Pizzeria da Michele".
     Add a Webhook tool labeled 'test_chatbot_elevenlabs' configured to receive questions via POST requests.

  Qdrant Collection Initialization:
     Utilize the HTTP Request nodes ('Create collection' and 'Refresh collection') to initialize and clear existing collections in Qdrant. Ensure you update placeholders QDRANTURL and COLLECTION accordingly.

  Document Vectorization:
     Use Google Drive integration to fetch documents from a designated folder. These documents are then downloaded and processed for embedding.
     Employ the Embeddings OpenAI node to generate embeddings for the downloaded files before storing them into Qdrant via the Qdrant Vector Store node.

  AI Agent Configuration:
     Define the system prompt for the AI Agent node which guides its behavior and responses based on the nature of queries expected (e.g., product details, troubleshooting tips).
     Link necessary models and tools including OpenAI language models and memory buffers to enhance interaction quality.

  Testing Workflow:
     Execute test runs of the entire workflow by clicking 'Test workflow' in n8n alongside initiating tests on the ElevenLabs side to confirm all components interact seamlessly.
     Monitor logs and outputs closely during testing phases to ensure accurate data flow between systems.

  Integration with Website:
     Finally, integrate the chatbot widget onto your business website replacing placeholder AGENT_ID with the actual identifier created earlier on ElevenLabs.

  By adhering to these comprehensive guidelines, users can successfully deploy a sophisticated voice-driven chatbot capable of delivering precise answers utilizing advanced retrieval-augmented generation techniques powered by OpenAI and ElevenLabs technologies.

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.googleDrive","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.embeddingsOpenAi","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.memoryBufferWindow","@n8n/n8n-nodes-langchain.textSplitterTokenSplitter","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.vectorStoreQdrant","@n8n/n8n-nodes-langchain.toolVectorStore"]

workflow_json:
  {"id":"ibiHg6umCqvcTF4g","meta":{"instanceId":"a4bfc93e975ca233ac45ed7c9227d84cf5a2329310525917adaf3312e10d5462","templateCredsSetupCompleted":true},"name":"Voice RAG Chatbot with ElevenLabs and OpenAI","tags":[],"nodes":[{"id":"5898da57-38b0-4d29-af25-fe029cda7c4a","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[-180,800],"parameters":{"text":"={{ $json.body.question }}","options":{},"promptType":"define"},"typeVersion":1.7},{"id":"81bbedb6-5a07-4977-a68f-2bdc75b17aba","name":"Vector Store Tool","type":"@n8n/n8n-nodes-langchain.toolVectorStore","position":[20,1040],"parameters":{"name":"company","description":"Risponde alle domande relative a ciò che ti viene chiesto"},"typeVersion":1},{"id":"fd021f6c-248d-41f4-a4f9-651e70692327","name":"Qdrant Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStoreQdrant","position":[-140,1300],"parameters":{"options":{},"qdrantCollection":{"__rl":true,"mode":"id","value":"=COLLECTION"}},"credentials":{"qdrantApi":{"id":"iyQ6MQiVaF3VMBmt","name":"QdrantApi account"}},"typeVersion":1},{"id":"84aca7bb-4812-498f-b319-88831e4ca412","name":"Embeddings OpenAI","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[-140,1460],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"CDX6QM4gLYanh0P4","name":"OpenAi account"}},"typeVersion":1.1},{"id":"82e430db-2ad7-427d-bcf9-6aa226253d18","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-760,520],"parameters":{"color":5,"width":1400,"height":240,"content":"# STEP 4\n\n## RAG System\n\nClick on \"test workflow\" on n8n and \"Test AI agent\" on ElevenLabs. If everything is configured correctly, when you ask a question to the agent, the webhook on n8n is activated with the \"question\" field in the body filled with the question asked to the voice agent.\n\nThe AI ​​Agent will extract the information from the vector database, send it to the model to create the response which will be sent via the response webhook to ElevenLabs which will transform it into voice"},"typeVersion":1},{"id":"6a19e9fa-50fa-4d51-ba41-d03c999e4649","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-780,-880],"parameters":{"color":3,"width":1420,"height":360,"content":"# STEP 1\n\n## Create an Agent on ElevenLabs \n- Create an agent on ElevenLabs (eg. test_n8n)\n- Add \"First message\" (eg. Hi, Can I help you?)\n- Add the \"System Prompt\" message... eg:\n'You are the waiter of \"Pizzeria da Michele\" in Verona. If you are asked a question, use the tool \"test_chatbot_elevenlabs\". When you receive the answer from \"test_chatbot_elevenlabs\" answer the user clearly and precisely.'\n- In Tools add a Webhook called eg. \"test_chatbot_elevenlabs\" and add the following description:\n'You are the waiter. Answer the questions asked and store them in the question field.'\n- Add the n8n webhook URL (method POST)\n- Enable \"Body Parameters\" and insert in the description \"Ask the user the question to ask the place.\", then in the \"Properties\" add a data type string called \"question\", value type \"LLM Prompt\" and description \"user question\""},"typeVersion":1},{"id":"ec053ee7-3a4a-4697-a08c-5645810d23f0","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-740,-200],"parameters":{},"typeVersion":1},{"id":"3e71e40c-a5cc-40cf-a159-aeedc97c47d1","name":"Create collection","type":"n8n-nodes-base.httpRequest","position":[-440,-340],"parameters":{"url":"https://QDRANTURL/collections/COLLECTION","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":"240283fc-50ec-475c-bd24-e6d0a367c10c","name":"Refresh collection","type":"n8n-nodes-base.httpRequest","position":[-440,-80],"parameters":{"url":"https://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":"7d10fda0-c6ab-4bf5-b73e-b93a84937eff","name":"Get folder","type":"n8n-nodes-base.googleDrive","position":[-220,-80],"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":"id","value":"=test-whatsapp"}},"options":{},"resource":"fileFolder"},"credentials":{"googleDriveOAuth2Api":{"id":"HEy5EuZkgPZVEa9w","name":"Google Drive account"}},"typeVersion":3},{"id":"c5761ad2-e66f-4d65-b653-0e89ea017f17","name":"Download Files","type":"n8n-nodes-base.googleDrive","position":[0,-80],"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"}},"typeVersion":3},{"id":"1f031a11-8ef3-4392-a7db-9bca00840b8f","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[380,120],"parameters":{"options":{},"dataType":"binary"},"typeVersion":1},{"id":"7f614392-7bc7-408c-8108-f289a81d5cf6","name":"Token Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterTokenSplitter","position":[360,280],"parameters":{"chunkSize":300,"chunkOverlap":30},"typeVersion":1},{"id":"648c5b3d-37a8-4a89-b88c-38e1863f09dc","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-240,-400],"parameters":{"color":6,"width":880,"height":220,"content":"# STEP 2\n\n## Create Qdrant Collection\nChange:\n- QDRANTURL\n- COLLECTION"},"typeVersion":1},{"id":"a6c50f3c-3c73-464e-9bdc-49de96401c1b","name":"Qdrant Vector Store1","type":"@n8n/n8n-nodes-langchain.vectorStoreQdrant","position":[240,-80],"parameters":{"mode":"insert","options":{},"qdrantCollection":{"__rl":true,"mode":"id","value":"=COLLECTION"}},"credentials":{"qdrantApi":{"id":"iyQ6MQiVaF3VMBmt","name":"QdrantApi account"}},"typeVersion":1},{"id":"7e19ac49-4d90-4258-bd44-7ca4ffa0128a","name":"Embeddings OpenAI1","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[220,120],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"CDX6QM4gLYanh0P4","name":"OpenAi account"}},"typeVersion":1.1},{"id":"bfa104a2-1f9c-4200-ae7b-4659894c1e6f","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-460,-140],"parameters":{"color":4,"width":620,"height":400,"content":"# STEP 3\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":"a148ffcf-335f-455d-8509-d98c711ed740","name":"Respond to ElevenLabs","type":"n8n-nodes-base.respondToWebhook","position":[380,800],"parameters":{"options":{}},"typeVersion":1.1},{"id":"5d19f73a-b8e8-4e75-8f67-836180597572","name":"OpenAI","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-300,1040],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"CDX6QM4gLYanh0P4","name":"OpenAi account"}},"typeVersion":1},{"id":"802b76e1-3f3e-490c-9e3b-65dc5b28d906","name":"Listen","type":"n8n-nodes-base.webhook","position":[-700,800],"webhookId":"e9f611eb-a8dd-4520-8d24-9f36deaca528","parameters":{"path":"test_voice_message_elevenlabs","options":{},"httpMethod":"POST","responseMode":"responseNode"},"typeVersion":2},{"id":"bdc55a38-1d4b-48fe-bbd8-29bf1afd954a","name":"Window Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[-140,1040],"parameters":{},"typeVersion":1.3},{"id":"2d5dd8cb-81eb-41bc-af53-b894e69e530c","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[200,1320],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"CDX6QM4gLYanh0P4","name":"OpenAi account"}},"typeVersion":1},{"id":"92d04432-1dbb-4d79-9edc-42378aee1c53","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-760,1620],"parameters":{"color":7,"width":1400,"height":240,"content":"# STEP 5\n\n## Add Widget\n\nAdd the widget to your business website by replacing AGENT_ID with the agent id you created on ElevenLabs\n\n<elevenlabs-convai agent-id=\"AGENT_ID\"></elevenlabs-convai><script src=\"https://elevenlabs.io/convai-widget/index.js\" async type=\"text/javascript\"></script>"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"6738abfe-e626-488d-a00b-81021cb04aaf","connections":{"Listen":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"OpenAI":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"AI Agent":{"main":[[{"node":"Respond to ElevenLabs","type":"main","index":0}]]},"Get folder":{"main":[[{"node":"Download Files","type":"main","index":0}]]},"Download Files":{"main":[[{"node":"Qdrant Vector Store1","type":"main","index":0}]]},"Token Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader","type":"ai_textSplitter","index":0}]]},"Embeddings OpenAI":{"ai_embedding":[[{"node":"Qdrant Vector Store","type":"ai_embedding","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"Vector Store Tool","type":"ai_languageModel","index":0}]]},"Vector Store Tool":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"Embeddings OpenAI1":{"ai_embedding":[[{"node":"Qdrant Vector Store1","type":"ai_embedding","index":0}]]},"Refresh collection":{"main":[[{"node":"Get folder","type":"main","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"Qdrant Vector Store1","type":"ai_document","index":0}]]},"Qdrant Vector Store":{"ai_vectorStore":[[{"node":"Vector Store Tool","type":"ai_vectorStore","index":0}]]},"Window Buffer Memory":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"Create collection","type":"main","index":0},{"node":"Refresh collection","type":"main","index":0}]]}}}


name: Chat with Postgresql Database
author_name: KumoHQ
author_username: kumohq
categories: []
created_at: 2025-02-07T10:20:16.255Z
updated_at: 2025-02-07T10:20:16.255Z
url: https://n8n.io/workflows/2859
scraped_at: 2025-07-06 21:16:30
description:
  Who is this template for?

  This workflow template is designed for any professionals seeking relevent data from database using natural language.

  How it works

  Each time user ask's question using the n8n chat interface, the workflow runs.
  Then the message is processed by AI Agent using relevent tools - Execute SQL Query, Get DB Schema and Tables List and Get Table Definition, if required. Agent uses these tool to form and run sql query which are necessary to answer the questions.
  Once AI Agent has the data, it uses it to form answer and returns it to the user.

  Set up instructions

  Complete the Set up credentials step when you first open the workflow. You'll need a Postgresql Credentials, and OpenAI api key.

  Template was created in n8n v1.77.0

nodes_used:
  ["@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.memoryBufferWindow"]

workflow_json:
  {"id":"eOUewYsEzJmQixI6","meta":{"instanceId":"77c4feba8f41570ef06dc76ece9a6ded0f0d44f7f1477a64c2d71a8508c11faa","templateCredsSetupCompleted":true},"name":"Chat with Postgresql Database","tags":[],"nodes":[{"id":"6501a54f-a68c-452d-b353-d7e871ca3780","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-300,-80],"webhookId":"cf1de04f-3e38-426c-89f0-3bdb110a5dcf","parameters":{"options":{}},"typeVersion":1.1},{"id":"cd32221b-2a36-408d-b57e-8115fcd810c9","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[0,-80],"parameters":{"agent":"openAiFunctionsAgent","options":{"systemMessage":"You are DB assistant. You need to run queries in DB aligned with user requests.\n\nRun custom SQL query to aggregate data and response to user. Make sure every table has schema prefix to it in sql query which you can get from `Get DB Schema and Tables List` tool.\n\nFetch all data to analyse it for response if needed.\n\n## Tools\n\n- Execute SQL query - Executes any sql query generated by AI\n- Get DB Schema and Tables List - Lists all the tables in database with its schema name\n- Get Table Definition - Gets the table definition from db using table name and schema name"}},"typeVersion":1.7},{"id":"8accbeeb-7eaf-4e9e-aabc-de8ab3a0459b","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-60,160],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"48uG61Ilo8jndw3r","name":"Your OpenAI Account Credentials"}},"typeVersion":1.2},{"id":"11f2013f-a080-4c9e-8773-c90492e2c628","name":"Get Table Definition","type":"n8n-nodes-base.postgresTool","position":[780,140],"parameters":{"query":"select\n  c.column_name,\n  c.data_type,\n  c.is_nullable,\n  c.column_default,\n  tc.constraint_type,\n  ccu.table_name AS referenced_table,\n  ccu.column_name AS referenced_column\nfrom\n  information_schema.columns c\nLEFT join\n  information_schema.key_column_usage kcu\n  ON c.table_name = kcu.table_name\n  AND c.column_name = kcu.column_name\nLEFT join\n  information_schema.table_constraints tc\n  ON kcu.constraint_name = tc.constraint_name\n  AND tc.constraint_type = 'FOREIGN KEY'\nLEFT join\n  information_schema.constraint_column_usage ccu\n  ON tc.constraint_name = ccu.constraint_name\nwhere\n  c.table_name = '{{ $fromAI(\"table_name\") }}'\n  AND c.table_schema = '{{ $fromAI(\"schema_name\") }}'\norder by\n  c.ordinal_position","options":{},"operation":"executeQuery","descriptionType":"manual","toolDescription":"Get table definition to find all columns and types"},"credentials":{"postgres":{"id":"nGI61D0TEEZz18rr","name":"Your Postgresql Database Credentials"}},"typeVersion":2.5},{"id":"760bc9bc-0057-4088-b3f0-3ee37b3519df","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-300,-240],"parameters":{"color":5,"width":560,"height":120,"content":"### 👨‍🎤 Setup\n1. Add your **postgresql** and **OpenAI** credentials.\n2. Click **Chat** button and start asking questions to your database.\n3. Activate the workflow and you can make the chat publicly available."},"typeVersion":1},{"id":"0df33341-c859-4a54-b6d9-a99670e8d76d","name":"Chat History","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[120,160],"parameters":{},"typeVersion":1.3},{"id":"4938b22e-f187-4ca0-b9f1-60835e823799","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[360,300],"parameters":{"color":7,"width":562,"height":156,"content":"🛠️ Tools Used:\n1. Execute SQL Query: Used to execute any query generated by the agent.\n2. Get DB Schema and Tables List: It returns the list of all the tables with its schema name.\n3. Get Table Definition: It returns table details like column names, foreign keys and more of a particular table in a schema."},"typeVersion":1},{"id":"39780c78-4fbc-403e-a220-aa6a4b06df8c","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-100,300],"parameters":{"color":7,"width":162,"height":99,"content":"👆 You can exchange this with any other chat model of your choice."},"typeVersion":1},{"id":"28a5692c-5003-46cb-9a09-b7867734f446","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[100,300],"parameters":{"color":7,"width":162,"height":159,"content":"👆 You can change how many number of messages to keep using `Context Window Length` option. It's 5 by default."},"typeVersion":1},{"id":"c18ced71-6330-4ba0-9c52-1bb5852b3039","name":"Execute SQL Query","type":"n8n-nodes-base.postgresTool","position":[380,140],"parameters":{"query":"{{ $fromAI(\"sql_query\", \"SQL Query\") }}","options":{},"operation":"executeQuery","descriptionType":"manual","toolDescription":"Get all the data from Postgres, make sure you append the tables with correct schema. Every table is associated with some schema in the database."},"credentials":{"postgres":{"id":"nGI61D0TEEZz18rr","name":"Your Postgresql Database Credentials"}},"typeVersion":2.5},{"id":"557623c6-e499-48a6-a066-744f64f8b6f3","name":"Get DB Schema and Tables List","type":"n8n-nodes-base.postgresTool","position":[580,140],"parameters":{"query":"SELECT \n    table_schema,\n    table_name\nFROM information_schema.tables\nWHERE table_type = 'BASE TABLE'\n    AND table_schema NOT IN ('pg_catalog', 'information_schema')\nORDER BY table_schema, table_name;","options":{},"operation":"executeQuery","descriptionType":"manual","toolDescription":"Get list of all tables with their schema in the database"},"credentials":{"postgres":{"id":"nGI61D0TEEZz18rr","name":"Your Postgresql Database Credentials"}},"typeVersion":2.5}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"10c7c74e-b383-4ac7-8cb2-c9a15a2818fe","connections":{"Chat History":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"Execute SQL Query":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Get Table Definition":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"When chat message received":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Get DB Schema and Tables List":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]}}}


name: AI Automated HR Workflow for CV Analysis and Candidate Evaluation
author_name: Davide
author_username: n3witalia
categories: []
created_at: 2025-02-07T12:30:06.464Z
updated_at: 2025-02-07T12:30:06.464Z
url: https://n8n.io/workflows/2860
scraped_at: 2025-07-06 21:16:30
description:
  How it Works

  This workflow automates the process of handling job applications by extracting relevant information from submitted CVs, analyzing the candidate's qualifications against a predefined profile, and storing the results in a Google Sheet. Here’s how it operates:

  Data Collection and Extraction: 
     The workflow begins with a form submission (On form submission node), which triggers the extraction of data from the uploaded CV file using the Extract from File node.
     Two informationExtractor nodes (Qualifications and Personal Data) are used to parse specific details such as educational background, work history, skills, city, birthdate, and telephone number from the text content of the CV.

  Processing and Evaluation:
     A Merge node combines the extracted personal and qualification data into a single output.
     This merged data is then passed through a Summarization Chain that generates a concise summary of the candidate’s profile.
     An HR Expert chain evaluates the candidate against a desired profile (Profile Wanted), assigning a score and providing considerations for hiring.
     Finally, all collected and processed data including the evaluation results are appended to a Google Sheets document via the Google Sheets node for further review or reporting purposes [[9]].

  Set Up Steps

  To replicate this workflow within your own n8n environment, follow these steps:

  Configuration:
     Begin by setting up an n8n instance if you haven't already; you can sign up directly on their website or self-host the application.
     Import the provided JSON configuration into your n8n workspace. Ensure that all necessary credentials (e.g., Google Drive, Google Sheets, OpenAI API keys) are correctly configured under the Credentials section since some nodes require external service integrations like Google APIs and OpenAI for language processing tasks.

  Customization:
     Adjust the parameters of each node according to your specific requirements. For example, modify the fields in the formTrigger node to match what kind of information you wish to collect from applicants.
     Customize the prompts given to AI models in nodes like Qualifications, Summarization Chain, and HR Expert so they align with the type of analyses you want performed on the candidates' profiles.
     Update the destination settings in the Google Sheets node to point towards your own spreadsheet where you would like the final outputs recorded.

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

nodes_used:
  ["n8n-nodes-base.googleSheets","n8n-nodes-base.googleDrive","@n8n/n8n-nodes-langchain.chainSummarization","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.outputParserStructured","@n8n/n8n-nodes-langchain.informationExtractor"]

workflow_json:
  {"id":"t1P14FvfibKYCh3E","meta":{"instanceId":"a4bfc93e975ca233ac45ed7c9227d84cf5a2329310525917adaf3312e10d5462","templateCredsSetupCompleted":true},"name":"HR-focused automation pipeline with AI","tags":[],"nodes":[{"id":"b1092f93-502c-4af0-962e-2b69311b92a3","name":"On form submission","type":"n8n-nodes-base.formTrigger","position":[-520,-200],"webhookId":"2a87705d-8ba1-41f1-80ef-85f364ce253e","parameters":{"options":{},"formTitle":"Send CV","formFields":{"values":[{"fieldLabel":"Name","placeholder":"Name","requiredField":true},{"fieldType":"email","fieldLabel":"Email","placeholder":"Email","requiredField":true},{"fieldType":"file","fieldLabel":"CV","requiredField":true,"acceptFileTypes":".pdf"}]}},"typeVersion":2.2},{"id":"77edfe2a-4c6a-48c8-8dc9-b275491be090","name":"Extract from File","type":"n8n-nodes-base.extractFromFile","position":[-160,-200],"parameters":{"options":{},"operation":"pdf","binaryPropertyName":"CV"},"typeVersion":1},{"id":"ebf2e194-3515-4c0a-8745-790b63bf336f","name":"Qualifications","type":"@n8n/n8n-nodes-langchain.informationExtractor","position":[160,-100],"parameters":{"text":"={{ $json.text }}","options":{"systemPromptTemplate":"You are an expert extraction algorithm.\nOnly extract relevant information from the text.\nIf you do not know the value of an attribute asked to extract, you may omit the attribute's value."},"attributes":{"attributes":[{"name":"Educational qualification","required":true,"description":"Summary of your academic career. Focus on your high school and university studies. Summarize in 100 words maximum and also include your grade if applicable."},{"name":"Job History","required":true,"description":"Work history summary. Focus on your most recent work experiences. Summarize in 100 words maximum"},{"name":"Skills","required":true,"description":"Extract the candidate’s technical skills. What software and frameworks they are proficient in. Make a bulleted list."}]}},"typeVersion":1},{"id":"4f40404c-1d47-4bde-9b4b-16367cf11e4f","name":"Summarization Chain","type":"@n8n/n8n-nodes-langchain.chainSummarization","position":[900,-220],"parameters":{"options":{"summarizationMethodAndPrompts":{"values":{"prompt":"=Write a concise summary of the following:\n\nCity: {{ $json.output.city }}\nBirthdate: {{ $json.output.birthdate }}\nEducational qualification: {{ $json.output[\"Educational qualification\"] }}\nJob History: {{ $json.output[\"Job History\"] }}\nSkills: {{ $json.output.Skills }}\n\nUse 100 words or less. Be concise and conversational.","combineMapPrompt":"=Write a concise summary of the following:\n\nCity: {{ $json.output.city }}\nBirthdate: {{ $json.output.birthdate }}\nEducational qualification: {{ $json.output[\"Educational qualification\"] }}\nJob History: {{ $json.output[\"Job History\"] }}\nSkills: {{ $json.output.Skills }}\n\nUse 100 words or less. Be concise and conversational."}}}},"typeVersion":2},{"id":"9f9c5f16-1dc2-4928-aef8-284daeb6be51","name":"Merge","type":"n8n-nodes-base.merge","position":[660,-220],"parameters":{"mode":"combine","options":{},"combineBy":"combineAll"},"typeVersion":3},{"id":"51bd14cc-2c54-4f72-b162-255f7e277aff","name":"Profile Wanted","type":"n8n-nodes-base.set","position":[1300,-220],"parameters":{"options":{},"assignments":{"assignments":[{"id":"a3d049b0-5a70-4e7b-a6f2-81447da5282a","name":"profile_wanted","type":"string","value":"We are a web agency and we are looking for a full-stack web developer who knows how to use PHP, Python and Javascript. He has experience in the sector and lives in Northern Italy."}]}},"typeVersion":3.4},{"id":"4a120e5d-b849-4a29-b7f3-12c653552367","name":"Google Sheets","type":"n8n-nodes-base.googleSheets","position":[1960,-220],"parameters":{"columns":{"value":{"CITY":"={{ $('Merge').item.json.output.city }}","DATA":"={{ $now.format('dd/LL/yyyy') }}","NAME":"={{ $('On form submission').item.json.Nome }}","VOTE":"={{ $json.output.vote }}","EMAIL":"={{ $('On form submission').item.json.Email }}","SKILLS":"={{ $('Merge').item.json.output.Skills }}","TELEFONO":"={{ $('Merge').item.json.output.telephone }}","SUMMARIZE":"={{ $('Summarization Chain').item.json.response.text }}","EDUCATIONAL":"={{ $('Merge').item.json.output[\"Educational qualification\"] }}","JOB HISTORY":"={{ $('Merge').item.json.output[\"Job History\"] }}","DATA NASCITA":"={{ $('Merge').item.json.output.birthdate }}","CONSIDERATION":"={{ $json.output.consideration }}"},"schema":[{"id":"DATA","type":"string","display":true,"required":false,"displayName":"DATA","defaultMatch":false,"canBeUsedToMatch":true},{"id":"NAME","type":"string","display":true,"required":false,"displayName":"NAME","defaultMatch":false,"canBeUsedToMatch":true},{"id":"PHONE","type":"string","display":true,"removed":false,"required":false,"displayName":"PHONE","defaultMatch":false,"canBeUsedToMatch":true},{"id":"CITY","type":"string","display":true,"required":false,"displayName":"CITY","defaultMatch":false,"canBeUsedToMatch":true},{"id":"EMAIL","type":"string","display":true,"required":false,"displayName":"EMAIL","defaultMatch":false,"canBeUsedToMatch":true},{"id":"DATA NASCITA","type":"string","display":true,"required":false,"displayName":"DATA NASCITA","defaultMatch":false,"canBeUsedToMatch":true},{"id":"EDUCATIONAL","type":"string","display":true,"required":false,"displayName":"EDUCATIONAL","defaultMatch":false,"canBeUsedToMatch":true},{"id":"JOB HISTORY","type":"string","display":true,"required":false,"displayName":"JOB HISTORY","defaultMatch":false,"canBeUsedToMatch":true},{"id":"SKILLS","type":"string","display":true,"required":false,"displayName":"SKILLS","defaultMatch":false,"canBeUsedToMatch":true},{"id":"SUMMARIZE","type":"string","display":true,"required":false,"displayName":"SUMMARIZE","defaultMatch":false,"canBeUsedToMatch":true},{"id":"VOTE","type":"string","display":true,"removed":false,"required":false,"displayName":"VOTE","defaultMatch":false,"canBeUsedToMatch":true},{"id":"CONSIDERATION","type":"string","display":true,"required":false,"displayName":"CONSIDERATION","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/1ssz5RvN1Hr20Q31pnYnbjCLu1MGBvoLttBAjXunMRQE/edit#gid=0","cachedResultName":"Foglio1"},"documentId":{"__rl":true,"mode":"list","value":"1ssz5RvN1Hr20Q31pnYnbjCLu1MGBvoLttBAjXunMRQE","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1ssz5RvN1Hr20Q31pnYnbjCLu1MGBvoLttBAjXunMRQE/edit?usp=drivesdk","cachedResultName":"Ricerca WebDev"}},"credentials":{"googleSheetsOAuth2Api":{"id":"JYR6a64Qecd6t8Hb","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"a154d8a5-9f85-45bb-b082-f702c13c3507","name":"Structured Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[1720,-20],"parameters":{"schemaType":"manual","inputSchema":"{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"vote\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n\t\t\"consideration\": {\n\t\t\t\"type\": \"string\"\n\t\t}\n\t}\n}"},"typeVersion":1.2},{"id":"037ac851-7885-4b78-ac75-dfa0ebb6003d","name":"HR Expert","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[1560,-220],"parameters":{"text":"=Profilo ricercato:\n{{ $json.profile_wanted }}\n\nCandidato:\n{{ $('Summarization Chain').item.json.response.text }}","messages":{"messageValues":[{"message":"Sei un esperto HR e devi capire se il candidato è in linea con il profilo ricercato dall'azienda.\n\nDevi dare un voto da 1 a 10 dove 1 significa che il candidato non è in linea con quanto richiesto mentre 10 significa che è il candidato ideale perchè rispecchia in toto il profilo cercato.\n\nInoltre nel campo \"consideration\" motiva il perchè hai dato quel voto. "}]},"promptType":"define","hasOutputParser":true},"typeVersion":1.5},{"id":"ed5744c4-df06-4a01-a103-af4dd470d482","name":"Personal Data","type":"@n8n/n8n-nodes-langchain.informationExtractor","position":[160,-280],"parameters":{"text":"={{ $json.text }}","options":{"systemPromptTemplate":"You are an expert extraction algorithm.\nOnly extract relevant information from the text.\nIf you do not know the value of an attribute asked to extract, you may omit the attribute's value."},"schemaType":"manual","inputSchema":"{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"telephone\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n      \"city\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n      \"birthdate\": {\n\t\t\t\"type\": \"string\"\n\t\t}\n\t}\n}"},"typeVersion":1},{"id":"181c1249-b05c-4c35-8cac-5f9738cc1fe6","name":"Upload CV","type":"n8n-nodes-base.googleDrive","position":[-160,-380],"parameters":{"name":"=CV-{{ $now.format('yyyyLLdd') }}-{{ $json.CV[0].filename }}","driveId":{"__rl":true,"mode":"list","value":"My Drive"},"options":{},"folderId":{"__rl":true,"mode":"list","value":"1tzeSpx4D3EAGXa3Wg-gqGbdaUk6LIZTV","cachedResultUrl":"https://drive.google.com/drive/folders/1tzeSpx4D3EAGXa3Wg-gqGbdaUk6LIZTV","cachedResultName":"CV"},"inputDataFieldName":"CV"},"credentials":{"googleDriveOAuth2Api":{"id":"HEy5EuZkgPZVEa9w","name":"Google Drive account"}},"typeVersion":3},{"id":"d31ee1c4-e4be-41d9-8f36-e6fb797ced8e","name":"OpenAI","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[920,240],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"CDX6QM4gLYanh0P4","name":"OpenAi account"}},"typeVersion":1.2},{"id":"0290cb72-a581-4aff-8b5d-1aa63e0a630f","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-560,-680],"parameters":{"color":3,"width":540,"content":"## HR Expert \nThis workflow automates the process of handling job applications by extracting relevant information from submitted CVs, analyzing the candidate's qualifications against a predefined profile, and storing the results in a Google Sheet"},"typeVersion":1},{"id":"361084ff-9735-4a56-8988-be573391838b","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-240,-460],"parameters":{"width":300,"height":420,"content":"The CV is uploaded to Google Drive and converted so that it can be processed\n"},"typeVersion":1},{"id":"4b6f004f-c77b-4522-99d4-737a68f6cfac","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[120,-380],"parameters":{"width":360,"height":440,"content":"The essential information for evaluating the candidate is collected in two different chains"},"typeVersion":1},{"id":"73e11af9-65e3-4fcd-bb99-8a3f212ce9fb","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[860,-300],"parameters":{"width":320,"height":240,"content":"Summary of relevant information useful for classifying the candidate"},"typeVersion":1},{"id":"606711d1-8e6d-44b3-91ac-c047d8a4054f","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1240,-300],"parameters":{"width":220,"height":240,"content":"Characteristics of the profile sought by the company that intends to hire the candidate"},"typeVersion":1},{"id":"89c3210c-c599-41dc-97a3-bf8df2beb751","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1500,-300],"parameters":{"width":360,"height":240,"content":"Candidate evaluation with vote and considerations of the HR agent relating the profile sought with the candidate's skills"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"594728c0-b842-404d-8810-c6f7f3f4631d","connections":{"Merge":{"main":[[{"node":"Summarization Chain","type":"main","index":0}]]},"OpenAI":{"ai_languageModel":[[{"node":"Qualifications","type":"ai_languageModel","index":0},{"node":"Summarization Chain","type":"ai_languageModel","index":0},{"node":"HR Expert","type":"ai_languageModel","index":0},{"node":"Personal Data","type":"ai_languageModel","index":0}]]},"HR Expert":{"main":[[{"node":"Google Sheets","type":"main","index":0}]]},"Upload CV":{"main":[[]]},"Personal Data":{"main":[[{"node":"Merge","type":"main","index":0}]]},"Profile Wanted":{"main":[[{"node":"HR Expert","type":"main","index":0}]]},"Qualifications":{"main":[[{"node":"Merge","type":"main","index":1}]]},"Extract from File":{"main":[[{"node":"Qualifications","type":"main","index":0},{"node":"Personal Data","type":"main","index":0}]]},"On form submission":{"main":[[{"node":"Extract from File","type":"main","index":0},{"node":"Upload CV","type":"main","index":0}]]},"Summarization Chain":{"main":[[{"node":"Profile Wanted","type":"main","index":0}]]},"Structured Output Parser":{"ai_outputParser":[[{"node":"HR Expert","type":"ai_outputParser","index":0}]]}}}


name: 🤖🧠 AI Agent Chatbot + LONG TERM Memory + Note Storage + Telegram
author_name: Joseph LePage
author_username: joe
categories: []
created_at: 2025-02-09T19:29:31.836Z
updated_at: 2025-02-09T19:29:31.836Z
url: https://n8n.io/workflows/2872
scraped_at: 2025-07-06 21:16:30
description:
  This workflow template creates an AI agent chatbot with long-term memory and note storage using Google Docs and Telegram integration.

  Google Docs Integration 📄
  n8n Google Docs Node Setup
  Google Credentials

  Telegram Integration 💬
  Telegram Setup

  Core Features 🌟

  AI Agent Integration 🤖
  Implements a sophisticated AI agent with memory management capabilities
  Uses GPT-4o-mini and DeepSeek models for intelligent conversation handling
  Maintains context awareness through session management

  Memory System 🧠
  Long-term memory storage using Google Docs
  Separate note storage system for specific information
  Window buffer memory for maintaining conversation context
  Intelligent memory retrieval and storage mechanisms

  Communication Interface 💬
  Telegram integration for message handling
  Real-time message processing and response generation

  Technical Components 🔧

  Memory Architecture 📚
  Dual storage system separating memories from notes
  Automated memory retrieval before each interaction
  Structured memory saving with timestamps

  AI Models 🤖
  Primary GPT-4o-mini mini model for general interactions
  DeepSeek-V3 Chat for specialized processing
  Custom agent system with tool integration

  Storage Integration 💾
  Google Docs integration for persistent storage
  Separate document management for memories and notes
  Automated document updates and retrievals

nodes_used:
  ["n8n-nodes-base.telegram","n8n-nodes-base.googleDocs","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.memoryBufferWindow"]

workflow_json:
  {"id":"QJZLBn9L6NbmjmLK","meta":{"instanceId":"31e69f7f4a77bf465b805824e303232f0227212ae922d12133a0f96ffeab4fef"},"name":"🤖🧠 AI Agent Chatbot + LONG TERM Memory + Note Storage + Telegram","tags":[],"nodes":[{"id":"20a2d959-5412-447b-a2c4-7736b6b758b3","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-320,1600],"webhookId":"8ba8fa53-2c24-47a8-b4dd-67b88c106e3d","parameters":{"options":{}},"typeVersion":1.1},{"id":"de79c268-bac5-48ff-be4d-18f522861c22","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-100,1280],"parameters":{"color":4,"width":340,"height":380,"content":"## Retrieve Long Term Memories\nGoogle Docs"},"typeVersion":1},{"id":"000a94d1-57ce-4eec-a021-9123685d22bf","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[1040,1840],"parameters":{"width":280,"height":380,"content":"## Save To Current Chat Memory (Optional)"},"typeVersion":1},{"id":"1bf1cade-bb3e-450a-a531-9add259069df","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[1360,1840],"parameters":{"color":4,"width":280,"height":380,"content":"## Save Long Term Memories\nGoogle Docs"},"typeVersion":1},{"id":"8b30f207-8204-4548-8f51-38c387d98ae9","name":"gpt-4o-mini","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[820,1900],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"jEMSvKmtYfzAkhe6","name":"OpenAi account"}},"typeVersion":1.1},{"id":"50271e59-6dd2-4f54-9b28-dd4a9f33ddc5","name":"Chat Response","type":"n8n-nodes-base.set","position":[1440,1600],"parameters":{"options":{},"assignments":{"assignments":[{"id":"d6f68b1c-a6a6-44d4-8686-dc4dcdde4767","name":"output","type":"string","value":"={{ $json.output }}"}]}},"typeVersion":3.4},{"id":"1064a2bf-bf74-44cd-ba8a-48f93700e887","name":"Window Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[1140,2000],"parameters":{"sessionKey":"={{ $('When chat message received').item.json.sessionId }}","sessionIdType":"customKey","contextWindowLength":50},"typeVersion":1.3},{"id":"280fe3b1-faca-41b6-be0e-2ab906cd1662","name":"Save Long Term Memories","type":"n8n-nodes-base.googleDocsTool","position":[1460,2000],"parameters":{"actionsUi":{"actionFields":[{"text":"={ \n  \"memory\": \"{{ $fromAI('memory') }}\",\n  \"date\": \"{{ $now }}\"\n}","action":"insert"}]},"operation":"update","documentURL":"[Google Doc ID]","descriptionType":"manual","toolDescription":"Save Memory"},"credentials":{"googleDocsOAuth2Api":{"id":"YWEHuG28zOt532MQ","name":"Google Docs account"}},"typeVersion":2},{"id":"37baa147-120a-40a8-b92f-df319fc4bc46","name":"Retrieve Long Term Memories","type":"n8n-nodes-base.googleDocs","position":[20,1420],"parameters":{"operation":"get","documentURL":"[Google Doc ID]"},"credentials":{"googleDocsOAuth2Api":{"id":"YWEHuG28zOt532MQ","name":"Google Docs account"}},"typeVersion":2,"alwaysOutputData":true},{"id":"b047a271-d2aa-4a26-b663-6a76d249824a","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[720,1840],"parameters":{"color":3,"width":280,"height":380,"content":"## LLM"},"typeVersion":1},{"id":"15bb5fd5-7dfe-4da9-830c-e1d905831640","name":"Telegram Response","type":"n8n-nodes-base.telegram","position":[1440,1260],"parameters":{"text":"={{ $json.output }}","chatId":"=1234567891","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"8cc38a87-e214-4193-9fe6-ba4adc3d5530","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[1360,1160],"parameters":{"width":260,"height":300,"content":"## Telegram \n(Optional)"},"typeVersion":1},{"id":"38121a81-d768-4bb0-a9e6-39de0906e026","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[680,1500],"parameters":{"color":5,"width":1320,"height":780,"content":"## AI AGENT with Long Term Memory & Note Storage"},"typeVersion":1},{"id":"7d5d1466-b4c9-4055-a634-ea7025dc370a","name":"DeepSeek-V3  Chat","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[820,2060],"parameters":{"model":"=deepseek-chat","options":{}},"credentials":{"openAiApi":{"id":"MSl7SdcvZe0SqCYI","name":"deepseek"}},"typeVersion":1.1},{"id":"68303b67-2203-41e8-b370-220d884d2945","name":"AI Tools Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[1060,1600],"parameters":{"text":"={{ $('When chat message received').item.json.chatInput }}","options":{"systemMessage":"=## ROLE  \nYou are a friendly, attentive, and helpful AI assistant. Your primary goal is to assist the user while maintaining a personalized and engaging interaction.  \n\n---\n\n## RULES  \n\n1. **Memory Management**:  \n   - When the user sends a new message, evaluate whether it contains noteworthy or personal information (e.g., preferences, habits, goals, or important events).  \n   - If such information is identified, use the **Save Memory** tool to store this data in memory.  \n   - Always send a meaningful response back to the user, even if your primary action was saving information. This response should not reveal that information was stored but should acknowledge or engage with the user’s input naturally.  \n\n2. **Note Management**:  \n   - If the user provides information that is intended to be stored as a note (e.g., specific instructions, reminders, or standalone pieces of information), use the **Save Note** tool.  \n   - Notes should not be stored in memory using the **Save Memory** tool.  \n   - Ensure that notes are clear, concise, and accurately reflect the user’s input.  \n\n3. **Context Awareness**:  \n   - Use stored memories and notes to provide contextually relevant and personalized responses.  \n   - Always consider the **date and time** when a memory or note was collected to ensure your responses are up-to-date and accurate.\n\n4. **User-Centric Responses**:  \n   - Tailor your responses based on the user's preferences and past interactions.  \n   - Be proactive in recalling relevant details from memory or notes when appropriate but avoid overwhelming the user with unnecessary information.\n\n5. **Privacy and Sensitivity**:  \n   - Handle all user data with care and sensitivity. Avoid making assumptions or sharing stored information unless it directly enhances the conversation or task at hand.\n   - Never store passwords or usernames.\n\n6. **Fallback Responses**:  \n   - **IMPORTANT** If no specific task or question arises from the user’s message (e.g., when only saving information), respond in a way that keeps the conversation flowing naturally. For example:  \n     - Acknowledge their input: “Thanks for sharing that!”  \n     - Provide a friendly follow-up: “Is there anything else I can help you with today?”  \n   - DO NOT tell jokes as a fallback response.\n\n---\n\n## TOOLS  \n\n### Save Memory  \n- Use this tool to store summarized, concise, and meaningful information about the user.  \n- Extract key details from user messages that could enhance future interactions (e.g., likes/dislikes, important dates, hobbies).  \n- Ensure that the summary is clear and devoid of unnecessary details.\n\n### Save Note  \n- Use this tool to store specific instructions, reminders, or standalone pieces of information provided by the user.  \n- Notes should not include general personal preferences or habits meant for long-term memory storage.  \n- Ensure that notes are concise and accurately reflect what the user wants to store.\n\n---\n\n## MEMORIES  \n\n### Recent Noteworthy Memories  \nHere are the most recent memories collected from the user, including their date and time of collection:  \n\n**{{ $json.data[0].content }}**\n\n### Guidelines for Using Memories:  \n- Prioritize recent memories but do not disregard older ones if they remain relevant.  \n- Cross-reference memories to maintain consistency in your responses. For example, if a user shares conflicting preferences over time, clarify or adapt accordingly.\n\n---\n\n## NOTES  \n\n### Recent Notes Collected from User:  \nHere are the most recent notes collected from the user:  \n\n**{{ $json.data[1].content }}**\n\n### Guidelines for Using Notes:  \n- Use notes for tasks requiring specific instructions or reminders.\n- Do not mix note content with general memory content; keep them distinct.\n\n---\n\n## ADDITIONAL INSTRUCTIONS  \n\n- Think critically before responding to ensure your answers are thoughtful and accurate.  \n- Strive to build trust with the user by being consistent, reliable, and personable in your interactions.  \n- Avoid robotic or overly formal language; aim for a conversational tone that aligns with being \"friendly and helpful.\"  \n"},"promptType":"define"},"typeVersion":1.7,"alwaysOutputData":false},{"id":"a6741133-93a1-42f8-83b4-bc29b9f49ae2","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[1680,1840],"parameters":{"color":4,"width":280,"height":380,"content":"## Save Notes\nGoogle Docs"},"typeVersion":1},{"id":"87c88d31-811d-4265-b44e-ab30a45ff88b","name":"Save Notes","type":"n8n-nodes-base.googleDocsTool","position":[1780,2000],"parameters":{"actionsUi":{"actionFields":[{"text":"={ \n  \"note\": \"{{ $fromAI('memory') }}\",\n  \"date\": \"{{ $now }}\"\n}","action":"insert"}]},"operation":"update","documentURL":"[Google Doc ID]","descriptionType":"manual","toolDescription":"Save Notes"},"credentials":{"googleDocsOAuth2Api":{"id":"YWEHuG28zOt532MQ","name":"Google Docs account"}},"typeVersion":2},{"id":"b9b97837-d6f2-4cef-89c4-9301973015df","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[-100,1680],"parameters":{"color":4,"width":340,"height":380,"content":"## Retrieve Notes\nGoogle Docs"},"typeVersion":1},{"id":"0002a227-4240-4d3c-9a45-fc6e23fdc7f5","name":"Retrieve Notes","type":"n8n-nodes-base.googleDocs","onError":"continueRegularOutput","position":[20,1820],"parameters":{"operation":"get","documentURL":"[Google Doc ID]"},"credentials":{"googleDocsOAuth2Api":{"id":"YWEHuG28zOt532MQ","name":"Google Docs account"}},"typeVersion":2,"alwaysOutputData":true},{"id":"88f7024c-87d4-48b4-b6bb-f68c88202f56","name":"Aggregate","type":"n8n-nodes-base.aggregate","position":[520,1600],"parameters":{"options":{},"aggregate":"aggregateAllItemData"},"typeVersion":1},{"id":"48d576fc-870a-441e-a7be-3056ef7e1d7a","name":"Merge","type":"n8n-nodes-base.merge","position":[340,1600],"parameters":{},"typeVersion":3}],"active":false,"settings":{"timezone":"America/Vancouver","callerPolicy":"workflowsFromSameOwner","executionOrder":"v1"},"versionId":"8130e77c-ecbd-470e-afec-ec8728643e00","connections":{"Merge":{"main":[[{"node":"Aggregate","type":"main","index":0}]]},"Aggregate":{"main":[[{"node":"AI Tools Agent","type":"main","index":0}]]},"Save Notes":{"ai_tool":[[{"node":"AI Tools Agent","type":"ai_tool","index":0}]]},"gpt-4o-mini":{"ai_languageModel":[[{"node":"AI Tools Agent","type":"ai_languageModel","index":0}]]},"AI Tools Agent":{"main":[[{"node":"Telegram Response","type":"main","index":0},{"node":"Chat Response","type":"main","index":0}],[]]},"Retrieve Notes":{"main":[[{"node":"Merge","type":"main","index":1}]]},"DeepSeek-V3  Chat":{"ai_languageModel":[[]]},"Telegram Response":{"main":[[]]},"Window Buffer Memory":{"ai_memory":[[{"node":"AI Tools Agent","type":"ai_memory","index":0}]]},"Save Long Term Memories":{"ai_tool":[[{"node":"AI Tools Agent","type":"ai_tool","index":0}]]},"When chat message received":{"main":[[{"node":"Retrieve Long Term Memories","type":"main","index":0},{"node":"Retrieve Notes","type":"main","index":0}]]},"Retrieve Long Term Memories":{"main":[[{"node":"Merge","type":"main","index":0}]]}}}


name: Host Your Own AI Deep Research Agent with n8n, Apify and OpenAI o3
author_name: Jimleuk
author_username: jimleuk
categories: []
created_at: 2025-02-11T00:02:26.780Z
updated_at: 2025-02-11T00:02:26.780Z
url: https://n8n.io/workflows/2878
scraped_at: 2025-07-06 21:16:30
description:
  This template attempts to replicate OpenAI's DeepResearch feature which, at time of writing, is only available to their pro subscribers.

  &gt; An agent that uses reasoning to synthesize large amount of online information and complete multi-step research tasks for you.
  Source

  Though the inner workings of DeepResearch have not been made public, it is presumed the feature relies on the ability to deep search the web, scrape web content and invoking reasoning models to generate reports. All of which n8n is really good at!

  Using this workflow, n8n users can enjoy a variation of the Deep Research experience for themselves and their teams at a fraction of the cost. Better yet, learn and customise this Deep Research template for their businesses and/or organisations.

  Check out the generated reports here: https://jimleuk.notion.site/19486dd60c0c80da9cb7eb1468ea9afd?v=19486dd60c0c805c8e0c000ce8c87acf

  How it works
  A form is used to first capture the user's research query and how deep they'd like the researcher to go.
  Once submitted, a blank Notion page is created which will later hold the final report and the researcher gets to work.
  The user's query goes through a recursive series of web serches and web scraping to collect data on the research topic to generate partial learnings.
  Once complete, all learnings are combined and given to a reasoning LLM to generate the final report.
  The report is then written to the placeholder Notion page created earlier. 

  How to use
  Duplicate this Notion database template and make sure all Notion related nodes point to it.
  Sign-up for APIFY.com API Key for web search and scraping services.
  Ensure you have access to OpenAI's o3-mini model. Alternatively, switch this out for o1 series.
  You must publish this workflow and ensure the form url is publically accessible.

  On depth & breadth configuration
  For more detailed reports, increase depth and breadth but be warned the workflow will take exponentially longer and cost more to complete. The recommended defaults are usually good enough.

  Depth=1 & Breadth=2 - will take about 5 - 10mins.
  Depth=1 & Breadth=3 - will take about 15 - 20mins.
  Dpeth=3 & Breadth=5 - will take about 2+ hours!

  Customising this workflow
  I deliberately chose not to use AI-powered scrapers like Firecrawl as I felt these were quite costly and quotas would be quickly exhausted. However, feel free to switch web search and scraping services which suit your environment.
  Maybe you don't decide to source the web and instead, data collection comes from internal documents instead. This template gives you freedom to change this.
  Experiment with different Reasoning/Thinking models such as Deepseek and Google's Gemini 2.0.
  Finally, the LLM prompts could definitely be improved. Refine them to fit your use-case.

  Credits
  This template is largely based off the work by David Zhang (dzhng) and his open source implementation of Deep Research: https://github.com/dzhng/deep-research

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.notion","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.outputParserStructured","@n8n/n8n-nodes-langchain.lmChatGoogleGemini"]

workflow_json:
  {"meta":{"instanceId":"408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9","templateCredsSetupCompleted":true},"nodes":[{"id":"a342005e-a88e-419b-b929-56ecbba4a936","name":"Structured Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[1300,1180],"parameters":{"schemaType":"manual","inputSchema":"{\n  \"type\": \"object\",\n  \"properties\": {\n    \"learnings\": {\n      \"type\": \"array\",\n      \"description\": \"List of learnings, max of 3.\",\n      \"items\": { \"type\": \"string\" }\n    },\n    \"followUpQuestions\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"string\",\n        \"description\": \"List of follow-up questions to research the topic further, max of 3.\"\n      }\n    }\n  }\n}"},"typeVersion":1.2},{"id":"126b8151-6d20-43b8-8028-8163112c4c5b","name":"Set Variables","type":"n8n-nodes-base.set","position":[-1360,-460],"parameters":{"options":{},"assignments":{"assignments":[{"id":"df28b12e-7c20-4ff5-b5b8-dc773aa14d4b","name":"request_id","type":"string","value":"={{ $execution.id }}"},{"id":"9362c1e7-717d-444a-8ea2-6b5f958c9f3f","name":"prompt","type":"string","value":"={{ $json['What would you like to research?'] }}"},{"id":"09094be4-7844-4a9e-af82-cc8e39322398","name":"depth","type":"number","value":"={{\n!isNaN($json['input-depth'][0].toNumber())\n  ? $json['input-depth'][0].toNumber()\n  : 1\n}}"},{"id":"3fc30a30-7806-4013-835d-97e27ddd7ae1","name":"breadth","type":"number","value":"={{\n!isNaN($json['input-breadth'][0].toNumber())\n  ? $json['input-breadth'][0].toNumber()\n  : 1\n}}"}]}},"typeVersion":3.4},{"id":"1d0fb87b-263d-46c2-b016-a29ba1d407ab","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1120,1180],"parameters":{"model":{"__rl":true,"mode":"id","value":"o3-mini"},"options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1.2},{"id":"39b300d9-11ba-44f6-8f43-2fe256fe4856","name":"OpenAI Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-860,1760],"parameters":{"model":{"__rl":true,"mode":"id","value":"o3-mini"},"options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1.2},{"id":"018da029-a796-45c5-947c-791e087fe934","name":"OpenAI Chat Model2","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-1060,-300],"parameters":{"model":{"__rl":true,"mode":"id","value":"o3-mini"},"options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1.2},{"id":"525da936-a9eb-4523-b27a-ff6ae7b0e5ef","name":"Structured Output Parser1","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[-840,-300],"parameters":{"schemaType":"manual","inputSchema":"{\n  \"type\": \"object\",\n  \"properties\": {\n    \"questions\": {\n      \"type\": \"array\",\n      \"description\": \"Follow up questions to clarify the research direction, max of 3.\",\n      \"items\": {\n          \"type\": \"string\"\n      }\n    }\n  }\n}"},"typeVersion":1.2},{"id":"e6664883-cff4-4e09-881e-6b6f684f9cac","name":"On form submission","type":"n8n-nodes-base.formTrigger","position":[-1760,-460],"webhookId":"026629c8-7644-493c-b830-d9c72eea307d","parameters":{"options":{"path":"deep_research","ignoreBots":true,"buttonLabel":"Next"},"formTitle":" DeepResearcher","formFields":{"values":[{"fieldType":"html"}]},"formDescription":"=DeepResearcher is a multi-step, recursive approach using the internet to solve complex research tasks, accomplishing in tens of minutes what a human would take many hours.\n\nTo use, provide a short summary of what the research and how \"deep\" you'd like the workflow to investigate. Note, the higher the numbers the more time and cost will occur for the research.\n\nThe workflow is designed to complete independently and when finished, a report will be saved in a designated Notion Database."},"typeVersion":2.2},{"id":"6b8ebc08-c0b1-4af8-99cc-79d09eea7316","name":"Generate SERP Queries","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[-1040,820],"parameters":{"text":"=Given the following prompt from the user, generate a list of SERP queries to research the topic.\nReduce the number of words in each query to its keywords only.\nReturn a maximum of {{ $('JobType Router').first().json.data.breadth }} queries, but feel free to return less if the original prompt is clear. Make sure each query is unique and not similar to each other: <prompt>{{ $('JobType Router').first().json.data.query.trim() }}</prompt>\n\n{{\n$('JobType Router').first().json.data.learnings.length\n  ? `Here are some learnings from previous research, use them to generate more specific queries:\\n${$('JobType Router').first().json.data.learnings.map(text => `* ${text}`).join('\\n')}`\n  : ''\n}}","messages":{"messageValues":[{"type":"HumanMessagePromptTemplate","message":"=You are an expert researcher. Today is {{ $now.toLocaleString() }}. Follow these instructions when responding:\n  - You may be asked to research subjects that is after your knowledge cutoff, assume the user is right when presented with news.\n  - The user is a highly experienced analyst, no need to simplify it, be as detailed as possible and make sure your response is correct.\n  - Be highly organized.\n  - Suggest solutions that I didn't think about.\n  - Be proactive and anticipate my needs.\n  - Treat me as an expert in all subject matter.\n  - Mistakes erode my trust, so be accurate and thorough.\n  - Provide detailed explanations, I'm comfortable with lots of detail.\n  - Value good arguments over authorities, the source is irrelevant.\n  - Consider new technologies and contrarian ideas, not just the conventional wisdom.\n  - You may use high levels of speculation or prediction, just flag it for me."}]},"promptType":"define","hasOutputParser":true},"typeVersion":1.5},{"id":"34e1fa5d-bc0c-4b9e-84a7-35db2b08c772","name":"Structured Output Parser2","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[-860,980],"parameters":{"schemaType":"manual","inputSchema":"{\n  \"type\": \"object\",\n  \"properties\": {\n    \"queries\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"query\": {\n            \"type\": \"string\",\n            \"description\": \"The SERP query\"\n          },\n          \"researchGoal\": {\n            \"type\": \"string\",\n            \"description\": \"First talk about the goal of the research that this query is meant to accomplish, then go deeper into how to advance the research once the results are found, mention additional research directions. Be as specific as possible, especially for additional research directions.\"\n          }\n        }\n      }\n    }\n  }\n}"},"typeVersion":1.2},{"id":"be6dd6a2-aacf-4682-8f13-8ae24c4249a3","name":"OpenAI Chat Model3","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-1040,980],"parameters":{"model":{"__rl":true,"mode":"id","value":"o3-mini"},"options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1.2},{"id":"d5ce6e21-cd07-44fa-b6d0-90bf7531ee01","name":"Set Initial Query","type":"n8n-nodes-base.set","position":[-580,180],"parameters":{"options":{},"assignments":{"assignments":[{"id":"acb41e93-70c6-41a3-be0f-e5a74ec3ec88","name":"query","type":"string","value":"={{ $('JobType Router').first().json.data.query }}"},{"id":"7fc54063-b610-42bc-a250-b1e8847c4d1e","name":"learnings","type":"array","value":"={{ $('JobType Router').first().json.data.learnings }}"},{"id":"e8f1c158-56fb-41c8-8d86-96add16289bb","name":"breadth","type":"number","value":"={{ $('JobType Router').first().json.data.breadth }}"}]}},"typeVersion":3.4},{"id":"9de6e4a1-a2b5-4a6f-948e-a0585edcae48","name":"SERP to Items","type":"n8n-nodes-base.splitOut","position":[-700,820],"parameters":{"options":{},"fieldToSplitOut":"output.queries"},"typeVersion":1},{"id":"2c9c4cdf-942b-494c-83fb-ed5ec37385ee","name":"Item Ref","type":"n8n-nodes-base.noOp","position":[-220,1020],"parameters":{},"typeVersion":1},{"id":"703c57af-de19-4f00-b580-711a272fa5ca","name":"Research Goal + Learnings","type":"n8n-nodes-base.set","position":[1460,1160],"parameters":{"options":{},"assignments":{"assignments":[{"id":"9acec2cc-64c8-4e62-bed4-c3d9ffab1379","name":"researchGoal","type":"string","value":"={{ $('Item Ref').first().json.researchGoal }}"},{"id":"1b2d2dad-429b-4fc9-96c5-498f572a85c3","name":"learnings","type":"array","value":"={{ $json.output.learnings }}"},{"id":"7025f533-02ab-4031-9413-43390fb61f05","name":"followUpQuestions","type":"string","value":"={{ $json.output.followUpQuestions }}"},{"id":"c9e34ea4-5606-46d6-8d66-cb42d772a8b4","name":"urls","type":"array","value":"={{\n$('Get Markdown + URL')\n  .all()\n  .map(item => item.json.url)\n}}"}]}},"typeVersion":3.4},{"id":"16ed2835-3af4-45e3-b5a7-e4342d571aa0","name":"Accumulate Results","type":"n8n-nodes-base.set","position":[-200,180],"parameters":{"options":{},"assignments":{"assignments":[{"id":"db509e90-9a86-431f-8149-4094d22666cc","name":"should_stop","type":"boolean","value":"={{\n$runIndex >= ($('JobType Router').first().json.data.depth)\n}}"},{"id":"90986e2b-8aca-4a22-a9db-ed8809d6284d","name":"all_learnings","type":"array","value":"={{\nArray($runIndex+1)\n  .fill(0)\n  .flatMap((_,idx) => {\n    try {\n      return $('Generate Learnings')\n        .all(0,idx)\n        .flatMap(item => item.json.data.flatMap(d => d.learnings))\n    } catch (e) {\n      return []\n    }\n  })\n}}"},{"id":"3eade958-e8ab-4975-aac4-f4a4a983c163","name":"all_urls","type":"array","value":"={{\nArray($runIndex+1)\n  .fill(0)\n  .flatMap((_,idx) => {\n    try {\n      return $('Generate Learnings')\n        .all(0,idx)\n        .flatMap(item => item.json.data.flatMap(d => d.urls))\n    } catch (e) {\n      return []\n    }\n  })\n}}"}]}},"executeOnce":true,"typeVersion":3.4},{"id":"0011773e-85c6-4fe1-8554-c23ce50706d0","name":"DeepResearch Results","type":"n8n-nodes-base.set","position":[160,360],"parameters":{"mode":"raw","options":{},"jsonOutput":"={{ $('Generate Learnings').item.json }}"},"typeVersion":3.4},{"id":"c0b646d0-1246-4864-8f79-8b7a66e4e083","name":"Results to Items","type":"n8n-nodes-base.splitOut","position":[320,360],"parameters":{"options":{},"fieldToSplitOut":"data"},"typeVersion":1},{"id":"3c52ec3e-c952-4b5f-ab12-f1b5d02aba74","name":"Set Next Queries","type":"n8n-nodes-base.set","position":[480,360],"parameters":{"options":{},"assignments":{"assignments":[{"id":"d88bfe95-9e73-4d25-b45c-9f164b940b0e","name":"query","type":"string","value":"=Previous research goal: {{ $json.researchGoal }}\nFollow-up research directions: {{ $json.followUpQuestions.map(q => `\\n${q}`).join('') }}"},{"id":"4aa20690-d998-458a-b1e4-0d72e6a68e6b","name":"learnings","type":"array","value":"={{ $('Accumulate Results').item.json.all_learnings }}"},{"id":"89acafae-b04a-4d5d-b08b-656e715654e4","name":"breadth","type":"number","value":"={{ $('JobType Router').first().json.data.breadth }}"}]}},"typeVersion":3.4},{"id":"bc59dddc-2b03-481f-91c6-ea8aa378eef0","name":"For Each Query...","type":"n8n-nodes-base.splitInBatches","position":[-420,860],"parameters":{"options":{}},"typeVersion":3},{"id":"903c31c4-5fdc-4cb6-8baa-402555997266","name":"Feedback to Items","type":"n8n-nodes-base.splitOut","position":[-720,-460],"parameters":{"options":{},"fieldToSplitOut":"output.questions"},"typeVersion":1},{"id":"59ff671d-5d4f-42ff-b94f-ed30a8531e55","name":"Ask Clarity Questions","type":"n8n-nodes-base.form","position":[-360,-380],"webhookId":"d3375ba6-0008-4fcb-96bc-110374de2603","parameters":{"options":{"formTitle":"DeepResearcher","buttonLabel":"Answer","formDescription":"=<img\n  src=\"https://res.cloudinary.com/daglih2g8/image/upload/f_auto,q_auto/v1/n8n-workflows/o4wqztloz3j6okfxpeyw\"\n  width=\"100%\"\n  style=\"border:1px solid #ccc\"\n/>\n<p style=\"text-align:left\">\nAnswer the following clarification questions to assist the DeepResearcher better under the research topic.\n</p>\n<hr style=\"display:block;margin-top:16px;margin-bottom:0\" />\n<p style=\"text-align:left;font-family:sans-serif;font-weight:700;\">\nTotal {{ $('Feedback to Items').all().length }} questions.\n</p>"},"formFields":{"values":[{"fieldType":"textarea","fieldLabel":"={{ $json[\"output.questions\"] }}","placeholder":"=","requiredField":true}]}},"typeVersion":1},{"id":"1c2cf79b-f1a1-4ecc-bb45-3d4460c947bd","name":"For Each Question...","type":"n8n-nodes-base.splitInBatches","position":[-540,-460],"parameters":{"options":{}},"typeVersion":3},{"id":"0c9ffa99-2687-4df5-8581-0c5b0b2657a9","name":"DeepResearch Subworkflow","type":"n8n-nodes-base.executeWorkflowTrigger","position":[-1880,820],"parameters":{"workflowInputs":{"values":[{"name":"requestId","type":"any"},{"name":"jobType"},{"name":"data","type":"object"}]}},"typeVersion":1.1},{"id":"127ab95d-bf89-4762-bfb5-34521e620ae2","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1140,-680],"parameters":{"color":7,"width":1000,"height":560,"content":"## 2. Ask Clarifying Questions\n[Read more about form nodes](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.form/)\n\nTo handle the clarification questions generated by the LLM, I used the same technique found in my \"AI Interviewer\" template ([link](https://n8n.io/workflows/2566-conversational-interviews-with-ai-agents-and-n8n-forms/)).\nThis involves a looping of dynamically generated forms to collect answers from the user."},"typeVersion":1},{"id":"e87c0f19-6002-4aa2-931a-ca7546146a84","name":"Clarifying Questions","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[-1040,-460],"parameters":{"text":"=Given the following query from the user, ask some follow up questions to clarify the research direction. Return a maximum of 3 questions, but feel free to return less if the original query is clear: <query>{{ $json.prompt }}</query>`","messages":{"messageValues":[{"type":"HumanMessagePromptTemplate","message":"=You are an expert researcher. Today is {{ $now.toLocaleString() }}. Follow these instructions when responding:\n  - You may be asked to research subjects that is after your knowledge cutoff, assume the user is right when presented with news.\n  - The user is a highly experienced analyst, no need to simplify it, be as detailed as possible and make sure your response is correct.\n  - Be highly organized.\n  - Suggest solutions that I didn't think about.\n  - Be proactive and anticipate my needs.\n  - Treat me as an expert in all subject matter.\n  - Mistakes erode my trust, so be accurate and thorough.\n  - Provide detailed explanations, I'm comfortable with lots of detail.\n  - Value good arguments over authorities, the source is irrelevant.\n  - Consider new technologies and contrarian ideas, not just the conventional wisdom.\n  - You may use high levels of speculation or prediction, just flag it for me."}]},"promptType":"define","hasOutputParser":true},"typeVersion":1.5},{"id":"b84f9c4a-c1de-4288-bab2-b7f5ffb8b542","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-660,-60],"parameters":{"color":7,"width":1360,"height":640,"content":"## 6. Perform DeepSearch Loop\n[Learn more about the Looping in n8n](https://docs.n8n.io/flow-logic/looping/#creating-loops)\n\nThe key of the Deep Research flow is its extensive data collection capability. In this implementation, this capability is represented by a recursive web search & scrape loop which starts with the original query and extended by AI-generated subqueries. How many subqueries to generate are determined the depth and breadth parameters specified.\n\n\"Learnings\" are generated for each subquery and accumulate on each iteration of the loop. When the loop finishes when depth limit is reached, all learnings are collected and it's these learnings are what we use to generate the report."},"typeVersion":1},{"id":"0a8c3a01-d4d4-4075-9521-035b7df9aa5a","name":"End Form","type":"n8n-nodes-base.form","position":[960,-420],"webhookId":"88f2534b-2b82-4b40-a4bc-97d96384e8fd","parameters":{"options":{},"operation":"completion","completionTitle":"=Thank you for using DeepResearcher.","completionMessage":"=You may now close this window."},"typeVersion":1},{"id":"44a3603f-a5a1-4031-8c5f-c748b1007b47","name":"Initiate DeepResearch","type":"n8n-nodes-base.executeWorkflow","position":[600,-420],"parameters":{"mode":"each","options":{"waitForSubWorkflow":false},"workflowId":{"__rl":true,"mode":"id","value":"={{ $workflow.id }}"},"workflowInputs":{"value":{"data":"={{\n{\n  \"query\": $('Get Initial Query').first().json.query,\n  \"learnings\": [],\n  \"depth\": $('Set Variables').first().json.depth,\n  \"breadth\": $('Set Variables').first().json.breadth,\n}\n}}","jobType":"deepresearch_initiate","requestId":"={{ $('Set Variables').first().json.request_id }}"},"schema":[{"id":"requestId","display":true,"removed":false,"required":false,"displayName":"requestId","defaultMatch":false,"canBeUsedToMatch":true},{"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":"b243eb76-9ed9-4327-968f-c21844bc9df4","name":"Execution Data","type":"n8n-nodes-base.executionData","position":[-1700,820],"parameters":{"dataToSave":{"values":[{"key":"requestId","value":"={{ $json.requestId }}"},{"key":"=jobType","value":"={{ $json.jobType }}"}]}},"typeVersion":1},{"id":"57ca4b22-9349-4b34-8f6b-c502905b5172","name":"JobType Router","type":"n8n-nodes-base.switch","position":[-1520,820],"parameters":{"rules":{"values":[{"outputKey":"initiate","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.jobType }}","rightValue":"deepresearch_initiate"}]},"renameOutput":true},{"outputKey":"learnings","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"ecbfa54d-fc97-48c5-8d3d-f0538b8d727b","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.jobType }}","rightValue":"deepresearch_learnings"}]},"renameOutput":true},{"outputKey":"report","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"392f9a98-ec22-4e57-9c8e-0e1ed6b7dafa","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.jobType }}","rightValue":"deepresearch_report"}]},"renameOutput":true}]},"options":{}},"typeVersion":3.2},{"id":"1f880fbd-71ba-4e5b-8d99-9654ae0c949f","name":"OpenAI Chat Model4","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-20,-280],"parameters":{"model":{"__rl":true,"mode":"id","value":"o3-mini"},"options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1.2},{"id":"ea65589b-106f-4ff1-a6f2-763393c2cb07","name":"Get Initial Query","type":"n8n-nodes-base.set","position":[-360,-540],"parameters":{"options":{},"assignments":{"assignments":[{"id":"14b77741-c3c3-4bd2-be6e-37bd09fcea2b","name":"query","type":"string","value":"=Initial query: {{ $('Set Variables').first().json.prompt }}\nFollow-up Questions and Answers:\n{{\n$input.all()\n  .map(item => {\n    const q = Object.keys(item.json)[0];\n    const a = item.json[q];\n    return `question: ${q}\\nanswer: ${a}`;\n  })\n  .join('\\n')\n}}"}]}},"executeOnce":true,"typeVersion":3.4},{"id":"09a363f2-6300-430d-8c7e-3e1611ab8e68","name":"Structured Output Parser4","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[160,-280],"parameters":{"schemaType":"manual","inputSchema":"{\n  \"type\": \"object\",\n  \"properties\": {\n    \"title\": {\n      \"type\": \"string\",\n      \"description\":\" A short title summarising the research topic\"\n    },\n    \"description\": {\n      \"type\": \"string\",\n      \"description\": \"A short description to summarise the research topic\"\n    }\n  }\n}"},"typeVersion":1.2},{"id":"9910804e-8376-4e2e-a011-7d32ca951edf","name":"Create Row","type":"n8n-nodes-base.notion","position":[300,-420],"parameters":{"title":"={{ $json.output.title }}","options":{},"resource":"databasePage","databaseId":{"__rl":true,"mode":"list","value":"19486dd6-0c0c-80da-9cb7-eb1468ea9afd","cachedResultUrl":"https://www.notion.so/19486dd60c0c80da9cb7eb1468ea9afd","cachedResultName":"n8n DeepResearch"},"propertiesUi":{"propertyValues":[{"key":"Description|rich_text","textContent":"={{ $json.output.description }}"},{"key":"Status|status","statusValue":"Not started"},{"key":"Request ID|rich_text","textContent":"={{ $('Set Variables').first().json.request_id }}"},{"key":"Name|title","title":"={{ $json.output.title }}"}]}},"credentials":{"notionApi":{"id":"iHBHe7ypzz4mZExM","name":"Notion account"}},"typeVersion":2.2},{"id":"9f06d9ae-220d-4f5b-bcbf-761b88ba255c","name":"Report Page Generator","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[-20,-420],"parameters":{"text":"=Create a suitable title for the research report which will be created from the user's query.\n<query>{{ $json.query }}</query>","promptType":"define","hasOutputParser":true},"typeVersion":1.5},{"id":"5b434bdc-e1e7-4348-b03d-dcbb6a485263","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-120,-680],"parameters":{"color":7,"width":600,"height":560,"content":"## 3. Create Empty Report Page in Notion\n[Read more about the Notion node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.notion/)\n\nSome thought was given where to upload the final report and Notion was selected due to familiarity. This can be easily changed to whatever wiki tools you prefer.\n\nIf you're following along however, here's the Notion database you need to replicate - [Jim's n8n DeepResearcher Database](https://jimleuk.notion.site/19486dd60c0c80da9cb7eb1468ea9afd?v=19486dd60c0c805c8e0c000ce8c87acf)."},"typeVersion":1},{"id":"0cfb3548-14a8-4dcc-8362-a7ca1d4c328f","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[500,-680],"parameters":{"color":7,"width":640,"height":560,"content":"## 4. Trigger DeepResearch Asynchronously\n[Learn more about the Execute Trigger node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow/)\n\nn8n handles asynchronous jobs by spinning them off as separate executions. This basically means the user doesn't have to wait or keep their browser window open for our researcher to do its job.\n\nOnce we initiate the Deepresearcher job, we can close out the onboarding journey for a nice user experience."},"typeVersion":1},{"id":"b90456d0-fae3-4809-bc13-55649e6e919a","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-1160,620],"parameters":{"color":7,"width":620,"height":540,"content":"## 7. Generate Search Queries\n[Learn more about the Basic LLM node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainllm/)\n\nMuch like a human researcher, the DeepResearcher will rely on web search and content as the preferred source of information. To ensure it can cover a wide range of sources, the AI can first generate relevant research queries of which each can be explored separately."},"typeVersion":1},{"id":"9fd00d55-1c76-425b-8386-7bc5b2bb47ac","name":"Is Depth Reached?","type":"n8n-nodes-base.if","position":[-40,180],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"75d18d88-6ba6-43df-bef7-3e8ad99ad8bd","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ $json.should_stop }}","rightValue":""}]}},"typeVersion":2.2},{"id":"f658537b-4f4c-4427-a66f-56cfd950bffc","name":"Get Research Results","type":"n8n-nodes-base.set","position":[160,180],"parameters":{"options":{},"assignments":{"assignments":[{"id":"90b3da00-dcd5-4289-bd45-953146a3b0ba","name":"all_learnings","type":"array","value":"={{ $json.all_learnings }}"},{"id":"623dbb3d-83a1-44a9-8ad3-48d92bc42811","name":"all_urls","type":"array","value":"={{ $json.all_urls }}"}]}},"typeVersion":3.4},{"id":"6059f3ba-e4a0-4528-894c-6080eedb91c3","name":"Get Existing Row","type":"n8n-nodes-base.notion","position":[-1040,180],"parameters":{"limit":1,"filters":{"conditions":[{"key":"Request ID|rich_text","condition":"equals","richTextValue":"={{ $json.requestId.toString() }}"}]},"options":{},"resource":"databasePage","matchType":"allFilters","operation":"getAll","databaseId":{"__rl":true,"mode":"list","value":"19486dd6-0c0c-80da-9cb7-eb1468ea9afd","cachedResultUrl":"https://www.notion.so/19486dd60c0c80da9cb7eb1468ea9afd","cachedResultName":"n8n DeepResearch"},"filterType":"manual"},"credentials":{"notionApi":{"id":"iHBHe7ypzz4mZExM","name":"Notion account"}},"typeVersion":2.2},{"id":"100625bb-bf9a-4993-b387-1c61e486ba6d","name":"Set In-Progress","type":"n8n-nodes-base.notion","position":[-840,180],"parameters":{"pageId":{"__rl":true,"mode":"id","value":"={{ $json.id }}"},"options":{},"resource":"databasePage","operation":"update","propertiesUi":{"propertyValues":[{"key":"Status|status","statusValue":"In progress"}]}},"credentials":{"notionApi":{"id":"iHBHe7ypzz4mZExM","name":"Notion account"}},"typeVersion":2.2},{"id":"864332ea-dd25-4347-a49d-68ed6495c1a9","name":"Set Done","type":"n8n-nodes-base.notion","position":[1680,1600],"parameters":{"pageId":{"__rl":true,"mode":"id","value":"={{ $('Get Existing Row1').first().json.id }}"},"options":{},"resource":"databasePage","operation":"update","propertiesUi":{"propertyValues":[{"key":"Status|status","statusValue":"Done"},{"key":"Last Updated|date","date":"={{ $now.toISO() }}"}]}},"credentials":{"notionApi":{"id":"iHBHe7ypzz4mZExM","name":"Notion account"}},"executeOnce":true,"typeVersion":2.2},{"id":"6771568a-e6bd-4c89-a535-089fd1c18fc3","name":"Tags to Items","type":"n8n-nodes-base.splitOut","position":[-60,1600],"parameters":{"options":{},"fieldToSplitOut":"tag"},"typeVersion":1},{"id":"47fce580-7b5b-4bc6-ba52-a8e7af6595b5","name":"Convert to HTML","type":"n8n-nodes-base.markdown","position":[-380,1600],"parameters":{"mode":"markdownToHtml","options":{"tables":true},"markdown":"={{ $json.text }}"},"typeVersion":1},{"id":"e2fb5a31-9ca5-487b-a7f8-f020759ec53a","name":"HTML to Array","type":"n8n-nodes-base.set","position":[-220,1600],"parameters":{"options":{},"assignments":{"assignments":[{"id":"851b8a3f-c2d3-41ad-bf60-4e0e667f6c58","name":"tag","type":"array","value":"={{ $json.data.match(/<table[\\s\\S]*?<\\/table>|<ul[\\s\\S]*?<\\/ul>|<[^>]+>[^<]*<\\/[^>]+>/g) }}"}]}},"typeVersion":3.4},{"id":"5275f9dd-5420-4c59-a330-5f2775b47e51","name":"Notion Block Generator","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[100,1600],"parameters":{"text":"={{ $json.tag.trim() }}","messages":{"messageValues":[{"message":"=Convert the following html into its equivalent Notion Block as per Notion's API schema.\n* Ensure the content is always included and remains the same.\n* Return only a json response.\n* Generate child-level blocks. Should not define \"parent\" or \"children\" property.\n* Strongly prefer headings, paragraphs, tables and lists type blocks.\n* available headings are heading_1, heading_2 and heading_3 - h4,h5,h6 should use heading_3 type instead. ensure headings use the rich text definition.\n* ensure lists blocks include all list items.\n\n## Examples\n\n1. headings\n```\n<h3 id=\"references\">References</h3>\n```\nwould convert to \n```\n{\"object\":  \"block\", \"type\": \"heading_3\", \"heading_3\": { \"rich_text\": [{\"type\": \"text\",\"text\": {\"content\": \"References\"}}]}}\n```\n\n2. lists\n```\n<ul><li>hello</li><li>world</li></ul>\n```\nwould convert to\n```\n[\n{\n  \"object\": \"block\",\n  \"type\": \"bulleted_list_item\",\n  \"bulleted_list_item\": {\"rich_text\": [{\"type\": \"text\",\"text\": {\"content\": \"hello\"}}]}\n},\n{\n  \"object\": \"block\",\n  \"type\": \"bulleted_list_item\",\n  \"bulleted_list_item\": {\"rich_text\": [{\"type\": \"text\",\"text\": {\"content\": \"world\"}}]}\n}\n]\n```\n\n3. tables\n```\n<table>\n  <thead>\n    <tr><th>Technology</th><th>Potential Impact</th></tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td>5G Connectivity</td><td>Enables faster data speeds and advanced apps</td>\n    </tr>\n  </tbody>\n</table>\n```\nwould convert to\n```\n{\n  \"object\": \"block\",\n  \"type\": \"table\",\n  \"table\": {\n    \"table_width\": 2,\n    \"has_column_header\": true,\n    \"has_row_header\": false,\n    \"children\": [\n      {\n        \"object\": \"block\",\n        \"type\": \"table_row\",\n        \"table_row\": {\n          \"cells\": [\n            [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Technology\",\n                  \"link\": null\n                }\n              },\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Potential Impact\",\n                  \"link\": null\n                }\n              }\n            ],\n            [\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"5G Connectivity\",\n                  \"link\": null\n                }\n              },\n              {\n                \"type\": \"text\",\n                \"text\": {\n                  \"content\": \"Enables faster data speeds and advanced apps\",\n                  \"link\": null\n                }\n              }\n            ]\n          ]\n        }\n      }\n    ]\n  }\n}\n```\n4. anchor links\nSince Notion doesn't support anchor links, just convert them to rich text blocks instead.\n```\n<a href=\"#module-0-pre-course-setup-and-learning-principles\">Module 0: Pre-Course Setup and Learning Principles</a>\n```\nconverts to\n```\n{\n  \"object\": \"block\",\n  \"type\": \"paragraph\",\n  \"paragraph\": {\n    \"rich_text\": [\n      {\n        \"type\": \"text\",\n        \"text\": {\n          \"content\": \"Module 0: Pre-Course Setup and Learning Principles\"\n        }\n      }\n    ]\n  }\n}\n```\n5. Invalid html parts\nWhen the html is not syntax valid eg. orphaned closing tags, then just skip the conversion and use an empty rich text block.\n```\n</li>\\n</ol>\n```\ncan be substituted with\n```\n{\n  \"object\": \"block\",\n  \"type\": \"paragraph\",\n  \"paragraph\": {\n    \"rich_text\": [\n      {\n        \"type\": \"text\",\n        \"text\": {\n          \"content\": \" \"\n        }\n      }\n    ]\n  }\n}\n```"}]},"promptType":"define"},"typeVersion":1.5},{"id":"30e73ecf-5994-4229-b7f6-01e043e0e65b","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[80,1760],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"dSxo6ns5wn658r8N","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"85ce9f7e-0369-41bd-8c31-c4217f400472","name":"Parse JSON blocks","type":"n8n-nodes-base.set","onError":"continueRegularOutput","position":[420,1600],"parameters":{"options":{},"assignments":{"assignments":[{"id":"73fcb8a0-2672-4bd5-86de-8075e1e02baf","name":"=block","type":"array","value":"={{\n(function(){\n  const block = $json.text\n    .replace('```json', '')\n    .replace('```', '')\n    .trim()\n    .parseJson();\n  if (Array.isArray(block)) return block;\n  if (block.type.startsWith('heading_')) {\n    const prev = Number(block.type.split('_')[1]);\n    const next = Math.max(1, prev - 1);\n    if (next !== prev) {\n      block.type = `heading_${next}`;\n      block[`heading_${next}`] = Object.assign({}, block[`heading_${prev}`]);\n      block[`heading_${prev}`] = undefined;\n    }\n  }\n  return [block];\n})()\n}}"}]}},"executeOnce":false,"typeVersion":3.4},{"id":"349f4323-d65f-4845-accc-6f51340a84c4","name":"Upload to Notion Page","type":"n8n-nodes-base.httpRequest","onError":"continueRegularOutput","maxTries":2,"position":[1680,1760],"parameters":{"url":"=https://api.notion.com/v1/blocks/{{ $('Get Existing Row1').first().json.id }}/children","method":"PATCH","options":{"timeout":"={{ 1000 * 60 }}"},"jsonBody":"={{\n{\n  \"children\": $json.block\n}\n}}","sendBody":true,"sendHeaders":true,"specifyBody":"json","authentication":"predefinedCredentialType","headerParameters":{"parameters":[{"name":"Notion-Version","value":"2022-06-28"}]},"nodeCredentialType":"notionApi"},"credentials":{"notionApi":{"id":"iHBHe7ypzz4mZExM","name":"Notion account"}},"retryOnFail":true,"typeVersion":4.2,"waitBetweenTries":3000},{"id":"44c732a9-b805-432e-8e9c-ba279e4cca46","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-520,620],"parameters":{"color":7,"width":1340,"height":740,"content":"## 8. Web Search and Extracting Web Page Contents using [APIFY.com](https://www.apify.com?fpr=414q6)\n[Read more about the HTTP Request node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/)\n\nHere is where I deviated a little from the reference implementation. I opted not to use Firecrawl.ai due to (1) high cost of the service and (2) a regular non-ai crawler would work just as well and probably quicker. Instead I'm using [APIFY.com](https://www.apify.com?fpr=414q6) which is a more performant, cost-effective and reliable web scraper service. If you don't want to use Apify, feel free to swap this out with your preferred service.\n\nThis step is the most exciting in terms of improvements and optimisations eg. mix in internal data sources! Add in Perplexity.ai or Jina.ai! Possibilities are endless."},"typeVersion":1},{"id":"daf2e775-72d3-4366-882b-8c9eb65f11e8","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-1140,60],"parameters":{"color":7,"width":460,"height":360,"content":"## 5. Set Report to In-Progress\n[Read more about the Notion node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.notion/)"},"typeVersion":1},{"id":"2d1b394d-8b9a-43fc-a646-c4e05c92da5b","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[860,780],"parameters":{"color":7,"width":800,"height":580,"content":"## 9. Compile Learnings with Reasoning Model\n[Read more about the Basic LLM node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainllm/)\n\nWith our gathered sources, it's now just a case of giving it to our LLM to compile a list of \"learnings\" from them. For our DeepResearcher, we'll use OpenAI's o3-mini which is the latest reasoning model at time of writing. Reasoning perform better than regular chat models due their chain-of-thought or \"thinking\" process that they perform.\n\nThe \"Learnings\" are then combined with the generated research goal to complete one loop."},"typeVersion":1},{"id":"e2c29aa2-ff79-4bdd-b3c7-cf5e5866db8a","name":"Get Existing Row1","type":"n8n-nodes-base.notion","position":[-1020,1600],"parameters":{"limit":1,"filters":{"conditions":[{"key":"Request ID|rich_text","condition":"equals","richTextValue":"={{ $json.requestId.toString() }}"}]},"options":{},"resource":"databasePage","matchType":"allFilters","operation":"getAll","databaseId":{"__rl":true,"mode":"list","value":"19486dd6-0c0c-80da-9cb7-eb1468ea9afd","cachedResultUrl":"https://www.notion.so/19486dd60c0c80da9cb7eb1468ea9afd","cachedResultName":"n8n DeepResearch"},"filterType":"manual"},"credentials":{"notionApi":{"id":"iHBHe7ypzz4mZExM","name":"Notion account"}},"typeVersion":2.2},{"id":"9dff368e-c282-4fef-8894-e218ea266695","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[-1140,1400],"parameters":{"color":7,"width":660,"height":540,"content":"## 10. Generate DeepSearch Report using Learnings\n[Read more about the Basic LLM node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainllm/)\n\nFinally! After all learnings have been gathered - which may have taken up to an hour or more on the higher settings! - they are given to our LLM to generate the final research report in markdown format. Technically, the DeepResearch ends here but for this template, we need to push the output to Notion. If you're not using Notion, feel free to ignore the last few steps."},"typeVersion":1},{"id":"14bfd0fd-6bc4-4dbf-86b2-44ef1c3586f7","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[-460,1400],"parameters":{"color":7,"width":1060,"height":540,"content":"## 11. Reformat Report as Notion Blocks\n[Learn more about the Markdown node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.markdown/)\n\nTo write our report to our Notion page, we'll have to convert it to Notion \"blocks\" - these are specialised json objects which are required by the Notion API. There are quite a number of ways to do this conversion not involving the use of AI but for kicks, I decided to do so anyway. In this step, we first convert to HTML as it allows us to split the report semantically and makes for easier parsing for the LLM."},"typeVersion":1},{"id":"a2aff56d-78b9-40a4-ac78-bd8380802ea0","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[1220,1400],"parameters":{"color":7,"width":800,"height":580,"content":"## 13. Update Report in Notion\n[Read more about the HTTP request node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/)\n\nIn this step, we can use the Notion API to add the blocks to our page sequentially. A loop is used due to the unstable Notion API - the loop allows retries for blocks that require it."},"typeVersion":1},{"id":"b5beeccd-e498-48ed-b6f2-b29d4599e2c9","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[-1840,-680],"parameters":{"color":7,"width":680,"height":560,"content":"## 1. Let's Research!\n[Learn more about the form trigger node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.formtrigger)\n\nn8n forms are a really nice way to get our frontend up and running quickly and compared to chat, offers a superior user interface for user input. I've gone perhaps a little extra with the custom html fields but I do enjoy adding a little customisation now and then."},"typeVersion":1},{"id":"533ede84-1138-426c-93df-c2b862e2d063","name":"DeepResearch Report","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[-860,1600],"parameters":{"text":"=You are are an expert and insightful researcher.\n* Given the following prompt from the user, write a final report on the topic using the learnings from research.\n* Make it as as detailed as possible, aim for 3 or more pages, include ALL the learnings from research.\n* Format the report in markdown. Use headings, lists and tables only and where appropriate.\n\n<prompt>{{ $('JobType Router').first().json.data.query }}</prompt>\n\nHere are all the learnings from previous research:\n\n<learnings>\n{{\n$('JobType Router').first().json.data\n  .all_learnings\n  .map(item => `<learning>${item}</learning>`)  \n  .join('\\n')\n}}\n</learnings>","promptType":"define"},"typeVersion":1.5},{"id":"efe47725-7fd5-45e7-97c4-d6c133745e5f","name":"DeepResearch Learnings","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[1120,1020],"parameters":{"text":"=Given the following contents from a SERP search for the query <query>{{ $('Item Ref').first().json.query }}</query>, generate a list of learnings from the contents. Return a maximum of 3 learnings, but feel free to return less if the contents are clear. Make sure each learning is unique and not similar to each other. The learnings should be concise and to the point, as detailed and infromation dense as possible. Make sure to include any entities like people, places, companies, products, things, etc in the learnings, as well as any exact metrics, numbers, or dates. The learnings will be used to research the topic further.\n\n<contents>\n{{\n$input\n  .all()\n  .map(item =>`<content>\\n${item.json.markdown.substr(0, 25_000)}\\n</content>`)\n  .join('\\n')\n}}\n</contents>","messages":{"messageValues":[{"type":"HumanMessagePromptTemplate","message":"=You are an expert researcher. Today is {{ $now.toLocaleString() }}. Follow these instructions when responding:\n  - You may be asked to research subjects that is after your knowledge cutoff, assume the user is right when presented with news.\n  - The user is a highly experienced analyst, no need to simplify it, be as detailed as possible and make sure your response is correct.\n  - Be highly organized.\n  - Suggest solutions that I didn't think about.\n  - Be proactive and anticipate my needs.\n  - Treat me as an expert in all subject matter.\n  - Mistakes erode my trust, so be accurate and thorough.\n  - Provide detailed explanations, I'm comfortable with lots of detail.\n  - Value good arguments over authorities, the source is irrelevant.\n  - Consider new technologies and contrarian ideas, not just the conventional wisdom.\n  - You may use high levels of speculation or prediction, just flag it for me."}]},"promptType":"define","hasOutputParser":true},"executeOnce":true,"typeVersion":1.5},{"id":"d3b42d13-e8ca-4085-ace9-1d9fb53f5e71","name":"Generate Report","type":"n8n-nodes-base.executeWorkflow","position":[480,180],"parameters":{"options":{"waitForSubWorkflow":false},"workflowId":{"__rl":true,"mode":"id","value":"={{ $workflow.id }}"},"workflowInputs":{"value":{"data":"={{\n{\n  ...Object.assign({}, $json),\n  query: $('JobType Router').first().json.data.query\n}\n}}","jobType":"deepresearch_report","requestId":"={{ $('JobType Router').first().json.requestId }}"},"schema":[{"id":"requestId","display":true,"required":false,"displayName":"requestId","defaultMatch":false,"canBeUsedToMatch":true},{"id":"jobType","type":"string","display":true,"required":false,"displayName":"jobType","defaultMatch":false,"canBeUsedToMatch":true},{"id":"data","type":"object","display":true,"required":false,"displayName":"data","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":true}},"typeVersion":1.2},{"id":"2b0314ff-cd82-4b3b-a4a9-5fd8067391eb","name":"Generate Learnings","type":"n8n-nodes-base.executeWorkflow","position":[-380,180],"parameters":{"mode":"each","options":{"waitForSubWorkflow":true},"workflowId":{"__rl":true,"mode":"id","value":"={{ $workflow.id }}"},"workflowInputs":{"value":{"data":"={{ $json }}","jobType":"deepresearch_learnings","requestId":"={{ $('JobType Router').first().json.requestId }}"},"schema":[{"id":"requestId","display":true,"removed":false,"required":false,"displayName":"requestId","defaultMatch":false,"canBeUsedToMatch":true},{"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":"f4457d0b-d708-4bca-9973-46d96ed55826","name":"Confirmation","type":"n8n-nodes-base.form","position":[780,-420],"webhookId":"2eb17c47-c887-4e95-8641-1b3796452ab9","parameters":{"options":{"formTitle":"DeepResearcher","buttonLabel":"Done","formDescription":"=<img\n  src=\"https://res.cloudinary.com/daglih2g8/image/upload/f_auto,q_auto/v1/n8n-workflows/o4wqztloz3j6okfxpeyw\"\n  width=\"100%\"\n  style=\"border:1px solid #ccc\"\n/>\n<p style=\"text-align:left\">\n<strong style=\"display:block;font-family:sans-serif;font-weight:700;font-size:16px;margin-top:12px;margin-bottom:0;\">Your Report Is On Its Way!</strong>\n<br/>\nDeepResearcher will now work independently to conduct the research and the compiled report will be uploaded to the following Notion page below when finished.\n<br/><br/>\nPlease click the \"Done\" button to complete the form.\n</p>\n<hr style=\"display:block;margin-top:16px;margin-bottom:0\" />"},"formFields":{"values":[{"html":"=<a href=\"{{ $json.url }}\" style=\"text-decoration:none\" target=\"_blank\">\n<div style=\"display:flex;text-align:left;font-family:sans-serif;\">\n  <div style=\"width:150px;height:150px;padding:12px;\">\n    <img src=\"https://res.cloudinary.com/daglih2g8/image/upload/f_auto,q_auto/v1/n8n-workflows/cajjymprexcoesu4gg9g\" width=\"100%\" />\n  </div>\n  <div style=\"width:100%;padding:12px;\">\n    <div style=\"font-size:14px;font-weight:700\">{{ $json.name }}</div>\n    <div style=\"font-size:12px;color:#666\">\n      {{ $json.property_description }}\n    </div>\n  </div>\n</div>\n</a>","fieldType":"html"}]}},"typeVersion":1},{"id":"af8fe17a-4314-4e92-ad8e-8be0be62984b","name":"Research Request","type":"n8n-nodes-base.form","position":[-1560,-460],"webhookId":"46142c14-3692-40f6-80e5-f3d976e95191","parameters":{"options":{"formTitle":"DeepResearcher","formDescription":"=<img\n  src=\"https://res.cloudinary.com/daglih2g8/image/upload/f_auto,q_auto/v1/n8n-workflows/o4wqztloz3j6okfxpeyw\"\n  width=\"100%\"\n  style=\"border:1px solid #ccc\"\n/>"},"formFields":{"values":[{"fieldType":"textarea","fieldLabel":"What would you like to research?","requiredField":true},{"html":"<video\n    style=\"display:none\"\n    src=\"/when_will_n8n_support_range_sliders.mp4\"\n    onerror='\n  this.insertAdjacentHTML(`afterend`,\n  `<div class=\"form-group\" style=\"margin-bottom:16px;\">\n    <label class=\"form-label\" for=\"breadth\">\n      Enter research depth (Default 1)\n    </label>\n    <p style=\"font-size:12px;color:#666;text-align:left\">\n      This value determines how many sub-queries to generate.\n    </p>\n    <input\n      class=\"form-input\"\n      type=\"range\"\n      id=\"depth\"\n      name=\"field-1\"\n      value=\"1\"\n      step=\"1\"\n      max=\"5\"\n      min=\"1\"\n      list=\"depth-markers\"\n    >\n    <datalist\n      id=\"depth-markers\"\n      style=\"display: flex;\n      flex-direction: row;\n      justify-content: space-between;\n      writing-mode: horizontal-tb;\n      margin-top: -10px;\n      text-align: center;\n      font-size: 10px;\n      margin-left: 16px;\n      margin-right: 16px;\"\n    >\n      <option value=\"1\" label=\"1\"></option>\n      <option value=\"2\" label=\"2\"></option>\n      <option value=\"3\" label=\"3\"></option>\n      <option value=\"4\" label=\"4\"></option>\n      <option value=\"5\" label=\"5\"></option>\n    </datalist>\n  </div>`)\n  '\n/>","fieldType":"html","elementName":"input-depth"},{"html":"<video\n    style=\"display:none\"\n    src=\"/when_will_n8n_support_range_sliders.mp4\"\n    onerror='\n  this.insertAdjacentHTML(`afterend`,\n  `<div class=\"form-group\" style=\"margin-bottom:16px;\">\n    <label class=\"form-label\" for=\"breadth\">\n      Enter research breadth (Default 2)\n    </label>\n    <p style=\"font-size:12px;color:#666;text-align:left\">\n      This value determines how many sources to explore.\n    </p>\n    <input\n      class=\"form-input\"\n      type=\"range\"\n      id=\"breadth\"\n      name=\"field-2\"\n      value=\"2\"\n      step=\"1\"\n      max=\"5\"\n      min=\"1\"\n      list=\"breadth-markers\"\n    >\n    <datalist\n      id=\"breadth-markers\"\n      style=\"display: flex;\n      flex-direction: row;\n      justify-content: space-between;\n      writing-mode: horizontal-tb;\n      margin-top: -10px;\n      text-align: center;\n      font-size: 10px;\n      margin-left: 16px;\n      margin-right: 16px;\"\n    >\n      <option value=\"1\" label=\"1\"></option>\n      <option value=\"2\" label=\"2\"></option>\n      <option value=\"3\" label=\"3\"></option>\n      <option value=\"4\" label=\"4\"></option>\n      <option value=\"5\" label=\"5\"></option>\n    </datalist>\n  </div>`)\n  '\n/>\n","fieldType":"html","elementName":"input-breadth"},{"fieldType":"dropdown","fieldLabel":"={{ \"\" }}","multiselect":true,"fieldOptions":{"values":[{"option":"=I understand higher depth and breath values I've selected may incur longer wait times and higher costs. I acknowledging this and wish to proceed with the research request."}]},"requiredField":true}]}},"typeVersion":1},{"id":"c67a5e5c-f82b-4e8a-9c99-065d16dfa576","name":"Valid Blocks","type":"n8n-nodes-base.filter","position":[740,1600],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"f68cefe0-e109-4d41-9aa3-043f3bc6c449","operator":{"type":"string","operation":"notExists","singleValue":true},"leftValue":"={{ $json.error }}","rightValue":""}]}},"typeVersion":2.2},{"id":"b89cf700-d955-4de4-bbac-b5c55995a1ee","name":"Sticky Note12","type":"n8n-nodes-base.stickyNote","position":[620,1400],"parameters":{"color":7,"width":580,"height":580,"content":"## 12. Append URL Sources List\n[Read more about the Code node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code)\n\nFor our source URLs, we'll manually compose the Notion blocks for them - this is because there's usually a lot of them! We'll then append to the end of the other blocks."},"typeVersion":1},{"id":"70c898a1-a757-452d-83ef-de1998fe13ae","name":"Append Blocks","type":"n8n-nodes-base.merge","position":[1000,1760],"parameters":{},"typeVersion":3},{"id":"591a3fcd-1748-43f7-9766-bc2059c195a0","name":"URL Sources to Lists","type":"n8n-nodes-base.code","position":[740,1760],"parameters":{"jsCode":"const urls = Object.values($('JobType Router').first().json.data.all_urls\n  .reduce((acc, url) => ({ ...acc, [url]: url }),{}));\nconst chunksize = 50;\nconst splits = Math.max(1, Math.floor(urls.length/chunksize));\n\nconst blocks = Array(splits).fill(0)\n  .map((_, idx) => {\n    const block = urls\n      .slice(\n        idx * chunksize, \n        (idx * chunksize) + chunksize - 1\n      )\n      .map(url => {\n        return {\n          object: \"block\",\n          type: \"bulleted_list_item\",\n          bulleted_list_item: {\n            rich_text: [\n              { type: \"text\", text: { content: url } }\n            ]\n          }\n        }\n      });\n    return { json: { block } }\n  });\n\nreturn [\n  { json: {\n    block:[{\n      \"object\": \"block\",\n      \"type\": \"heading_2\",\n      \"heading_2\": {\n        \"rich_text\": [\n          {\n            \"type\": \"text\",\n            \"text\": {\n              \"content\": \"Sources\"\n            }\n          }\n        ]\n      }\n    }]\n  } },\n  ...blocks\n];"},"typeVersion":2},{"id":"e59dbeea-ccf3-4619-9fe1-24874a91bdab","name":"Empty Response","type":"n8n-nodes-base.set","position":[640,1160],"parameters":{"options":{},"assignments":{"assignments":[{"id":"1de40158-338b-4db3-9e22-6fd63b21f825","name":"ResearchGoal","type":"string","value":"={{ $('Item Ref').first().json.researchGoal }}"},{"id":"9f59a2d4-5e5a-4d0b-8adf-2832ce746f0f","name":"learnings","type":"array","value":"={{ [] }}"},{"id":"972ab5f5-0537-4755-afcb-d1db4f09ad60","name":"followUpQuestions","type":"array","value":"={{ [] }}"},{"id":"90cef471-76b0-465d-91a4-a0e256335cd3","name":"urls","type":"array","value":"={{ [] }}"}]}},"typeVersion":3.4},{"id":"34035b2e-eee9-483e-8125-3b6f1f41cd1d","name":"Has Content?","type":"n8n-nodes-base.if","position":[480,1020],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"1ef1039a-4792-47f9-860b-d2ffcffd7129","operator":{"type":"object","operation":"notEmpty","singleValue":true},"leftValue":"={{ $json }}","rightValue":""}]}},"typeVersion":2.2},{"id":"5e9f80e2-db58-4f89-8aec-a1b8e73e18eb","name":"Sticky Note13","type":"n8n-nodes-base.stickyNote","position":[-1820,-240],"parameters":{"color":5,"width":300,"height":100,"content":"### Not using forms?\nFeel free ot swap this out for chat or even webhooks to fit your existing workflows."},"typeVersion":1},{"id":"3e513463-2f4c-4e3e-921d-e5c8ea5ec078","name":"Sticky Note14","type":"n8n-nodes-base.stickyNote","position":[-1880,540],"parameters":{"color":5,"width":460,"height":240,"content":"### 🚏 The Subworkflow Event Pattern \nIf you're new to n8n, this advanced technique might need some explaining but in gist, we're using subworkflows to run different parts of our DeepResearcher workflow as separate executions.\n\n* Necessary to implement the recursive loop mechanism needed to enable this workflow.\n* Negates the need to split this workflow into multiple templates.\n* Great generally for building high performance n8n workflows (a topic for a future post!)"},"typeVersion":1},{"id":"fea2568e-86c9-4663-b141-a9b2a36b84f5","name":"Sticky Note15","type":"n8n-nodes-base.stickyNote","position":[720,-60],"parameters":{"color":5,"width":340,"height":200,"content":"### Recursive Looping\nThe recursive looping implemented for this workflow is an advanced item-linking technique. It works by specifically controlling which nodes \"execute once\" vs\" execute for each item\" because of this becareful of ermoving nodes! Always check the settings of the node you're replacing and ensure the settings match. "},"typeVersion":1},{"id":"fd3fec73-4b1a-4882-8c5a-d4825d9038ad","name":"Combine & Send back to Loop","type":"n8n-nodes-base.aggregate","position":[-220,860],"parameters":{"options":{},"aggregate":"aggregateAllItemData"},"typeVersion":1},{"id":"7c183897-e2ce-46da-90bd-0a39122b85f2","name":"For Each Block...","type":"n8n-nodes-base.splitInBatches","position":[1440,1600],"parameters":{"options":{}},"typeVersion":3},{"id":"bc04462a-780c-48e9-bc38-8eaf8ac1175c","name":"Sticky Note16","type":"n8n-nodes-base.stickyNote","position":[-2420,-920],"parameters":{"width":520,"height":1060,"content":"## n8n DeepResearcher\n### This template attempts to replicate OpenAI's DeepResearch feature which, at time of writing, is only available to their pro subscribers.\n\nThough the inner workings of DeepResearch have not been made public, it is presumed the feature relies on the ability to deep search the web, scrape web content and invoking reasoning models to generate reports. All of which n8n is really good at!\n\n### How it works\n* A form is used to first capture the user's research query and how deep they'd like the researcher to go.\n* Once submitted, a blank Notion page is created which will later hold the final report and the researcher gets to work.\n* The user's query goes through a recursive series of web serches and web scraping to collect data on the research topic to generate partial learnings.\n* Once complete, all learnings are combined and given to a reasoning LLM to generate the final report.\n* The report is then written to the placeholder Notion page created earlier. \n\n### How to use\n* Duplicate this Notion database to use with this template: https://jimleuk.notion.site/19486dd60c0c80da9cb7eb1468ea9afd?v=19486dd60c0c805c8e0c000ce8c87acf\n* Sign-up for [APIFY.com](https://www.apify.com?fpr=414q6) API Key for web search and scraping services.\n* Ensure you have access to OpenAI's o3-mini model. Alternatively, switch this out for o1 series.\n* You must publish this workflow and ensure the form url is publically accessible.\n\n### On Depth & Breadth Configuration\nFor more detailed reports, increase depth and breadth but be warned the workflow will take a exponentially more time and money to complete. The defaults are usually good enough.\n\nDepth=1 & Breadth=2 - will take about 5 - 10mins.\nDepth=1 & Breadth=3 - will take about 15 - 20mins.\nDpeth=3 & Breadth=5 - will take about 2+ hours!\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":"654362c8-bc85-47d1-b277-50630f6f3999","name":"Sticky Note17","type":"n8n-nodes-base.stickyNote","position":[-2420,-1180],"parameters":{"color":7,"width":520,"height":240,"content":"![](https://res.cloudinary.com/daglih2g8/image/upload/f_auto,q_auto/v1/n8n-workflows/o4wqztloz3j6okfxpeyw#full-width)"},"typeVersion":1},{"id":"c2ddbec3-4579-4d4e-81bf-293c9eee9b73","name":"Sticky Note18","type":"n8n-nodes-base.stickyNote","position":[-80,1000],"parameters":{"width":180,"height":260,"content":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n### UPDATE APIFY CREDENTIAL HERE!"},"typeVersion":1},{"id":"43461d7d-1a04-424a-b2b0-4a4cbc46f1c2","name":"Sticky Note20","type":"n8n-nodes-base.stickyNote","position":[1640,1740],"parameters":{"width":180,"height":260,"content":"\n\n\n\n\n\n\n\n\n\n\n\n### UPDATE NOTION CREDENTIAL HERE!"},"typeVersion":1},{"id":"48b83b0f-94e7-44e2-8bd4-0addddd62264","name":"Valid Results","type":"n8n-nodes-base.filter","position":[300,1020],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"f44691e4-f753-47b0-b66a-068a723b6beb","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.crawl.requestStatus }}","rightValue":"handled"},{"id":"8e05df2b-0d4a-47da-9aab-da7e8907cbca","operator":{"type":"string","operation":"notEmpty","singleValue":true},"leftValue":"={{ $json.markdown }}","rightValue":""}]}},"typeVersion":2.2,"alwaysOutputData":true},{"id":"6124becb-2584-472d-8354-b714d9f1e858","name":"RAG Web Browser","type":"n8n-nodes-base.httpRequest","onError":"continueRegularOutput","position":[-40,1020],"parameters":{"url":"https://api.apify.com/v2/acts/apify~rag-web-browser/run-sync-get-dataset-items","method":"POST","options":{},"sendBody":true,"sendQuery":true,"authentication":"genericCredentialType","bodyParameters":{"parameters":[{"name":"query","value":"={{\n`${$json.query} -filetype:pdf (-site:tiktok.com OR -site:instagram.com OR -site:youtube.com OR -site:linkedin.com OR -site:reddit.com)`\n}}"}]},"genericAuthType":"httpHeaderAuth","queryParameters":{"parameters":[{"name":"memory","value":"4096"},{"name":"timeout","value":"180"}]}},"credentials":{"httpQueryAuth":{"id":"cO2w8RDNOZg8DRa8","name":"Apify API"},"httpHeaderAuth":{"id":"SV9BDKc1cRbZBeoL","name":"Apify.com (personal token)"}},"typeVersion":4.2},{"id":"749a5d4d-85ae-4ee3-a79b-6659af666a3a","name":"Get Markdown + URL","type":"n8n-nodes-base.set","position":[940,1020],"parameters":{"options":{},"assignments":{"assignments":[{"id":"c41592db-f9f0-4228-b6d8-0514c9a21fca","name":"markdown","type":"string","value":"={{ $json.markdown }}"},{"id":"5579a411-94dc-4b10-a276-24adf775be1d","name":"url","type":"string","value":"={{ $json.searchResult.url }}"}]}},"typeVersion":3.4},{"id":"4a5ad2e4-b274-4a2f-bc0f-15d067ad469c","name":"Is Apify Auth Error?","type":"n8n-nodes-base.if","position":[140,1020],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"8722e13a-d788-4145-8bea-5bc0ce0a83f8","operator":{"type":"number","operation":"equals"},"leftValue":"={{ $json.error.status }}","rightValue":401}]}},"typeVersion":2.2},{"id":"54118cbc-6466-448d-8832-91ad62a931e2","name":"Stop and Error","type":"n8n-nodes-base.stopAndError","position":[300,860],"parameters":{"errorMessage":"=Apify Auth Error! Check your API token is valid and make sure you put \"Bearer <api_key>\" if using HeaderAuth."},"typeVersion":1},{"id":"aae46fd1-70bc-4629-8a47-6ae75ce8afb1","name":"Sticky Note19","type":"n8n-nodes-base.stickyNote","position":[-460,1960],"parameters":{"color":5,"width":560,"height":300,"content":"### Self-hosting n8n? Consider using one of these to upload to Notion!\nThis template uses an LLM to convert markdown to Notion which isn't the most efficient but it's \"easier\" because doesn't require installing other software. To speed this up and reduce errors in the conversation, consider the following options to replace this flow if you're able to install them yourself.\n\n* [Notion ⇄ Markdown Conversion Community Node](https://community.n8n.io/t/now-available-notion-markdown-conversion-community-node/59087)\n* [tryfabric/martian: Markdown to Notion: Convert Markdown and GitHub Flavoured Markdown to Notion API Blocks and RichText 🔀📝](https://github.com/tryfabric/martian)\n* [brittonhayes/notionmd: 🪄 Convert Markdown into Notion Blocks](https://github.com/brittonhayes/notionmd)\n\n\n**Note**: Recommendation onl, requires due diligence and use at your own risk!"},"typeVersion":1}],"connections":{"Item Ref":{"main":[[{"node":"RAG Web Browser","type":"main","index":0}]]},"Create Row":{"main":[[{"node":"Initiate DeepResearch","type":"main","index":0}]]},"Confirmation":{"main":[[{"node":"End Form","type":"main","index":0}]]},"Has Content?":{"main":[[{"node":"Get Markdown + URL","type":"main","index":0}],[{"node":"Empty Response","type":"main","index":0}]]},"Valid Blocks":{"main":[[{"node":"Append Blocks","type":"main","index":0}]]},"Append Blocks":{"main":[[{"node":"For Each Block...","type":"main","index":0}]]},"HTML to Array":{"main":[[{"node":"Tags to Items","type":"main","index":0}]]},"SERP to Items":{"main":[[{"node":"For Each Query...","type":"main","index":0}]]},"Set Variables":{"main":[[{"node":"Clarifying Questions","type":"main","index":0}]]},"Tags to Items":{"main":[[{"node":"Notion Block Generator","type":"main","index":0}]]},"Valid Results":{"main":[[{"node":"Has Content?","type":"main","index":0}]]},"Empty Response":{"main":[[{"node":"For Each Query...","type":"main","index":0}]]},"Execution Data":{"main":[[{"node":"JobType Router","type":"main","index":0}]]},"JobType Router":{"main":[[{"node":"Get Existing Row","type":"main","index":0}],[{"node":"Generate SERP Queries","type":"main","index":0}],[{"node":"Get Existing Row1","type":"main","index":0}]]},"Convert to HTML":{"main":[[{"node":"HTML to Array","type":"main","index":0}]]},"RAG Web Browser":{"main":[[{"node":"Is Apify Auth Error?","type":"main","index":0}]]},"Set In-Progress":{"main":[[{"node":"Set Initial Query","type":"main","index":0}]]},"Get Existing Row":{"main":[[{"node":"Set In-Progress","type":"main","index":0}]]},"Research Request":{"main":[[{"node":"Set Variables","type":"main","index":0}]]},"Results to Items":{"main":[[{"node":"Set Next Queries","type":"main","index":0}]]},"Set Next Queries":{"main":[[{"node":"Generate Learnings","type":"main","index":0}]]},"Feedback to Items":{"main":[[{"node":"For Each Question...","type":"main","index":0}]]},"For Each Block...":{"main":[[{"node":"Set Done","type":"main","index":0}],[{"node":"Upload to Notion Page","type":"main","index":0}]]},"For Each Query...":{"main":[[{"node":"Combine & Send back to Loop","type":"main","index":0}],[{"node":"Item Ref","type":"main","index":0}]]},"Get Existing Row1":{"main":[[{"node":"DeepResearch Report","type":"main","index":0}]]},"Get Initial Query":{"main":[[{"node":"Report Page Generator","type":"main","index":0}]]},"Is Depth Reached?":{"main":[[{"node":"Get Research Results","type":"main","index":0}],[{"node":"DeepResearch Results","type":"main","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"DeepResearch Learnings","type":"ai_languageModel","index":0}]]},"Parse JSON blocks":{"main":[[{"node":"Valid Blocks","type":"main","index":0},{"node":"URL Sources to Lists","type":"main","index":0}]]},"Set Initial Query":{"main":[[{"node":"Generate Learnings","type":"main","index":0}]]},"Accumulate Results":{"main":[[{"node":"Is Depth Reached?","type":"main","index":0}]]},"Generate Learnings":{"main":[[{"node":"Accumulate Results","type":"main","index":0}]]},"Get Markdown + URL":{"main":[[{"node":"DeepResearch Learnings","type":"main","index":0}]]},"On form submission":{"main":[[{"node":"Research Request","type":"main","index":0}]]},"OpenAI Chat Model1":{"ai_languageModel":[[{"node":"DeepResearch Report","type":"ai_languageModel","index":0}]]},"OpenAI Chat Model2":{"ai_languageModel":[[{"node":"Clarifying Questions","type":"ai_languageModel","index":0}]]},"OpenAI Chat Model3":{"ai_languageModel":[[{"node":"Generate SERP Queries","type":"ai_languageModel","index":0}]]},"OpenAI Chat Model4":{"ai_languageModel":[[{"node":"Report Page Generator","type":"ai_languageModel","index":0}]]},"DeepResearch Report":{"main":[[{"node":"Convert to HTML","type":"main","index":0}]]},"Clarifying Questions":{"main":[[{"node":"Feedback to Items","type":"main","index":0}]]},"DeepResearch Results":{"main":[[{"node":"Results to Items","type":"main","index":0}]]},"For Each Question...":{"main":[[{"node":"Get Initial Query","type":"main","index":0}],[{"node":"Ask Clarity Questions","type":"main","index":0}]]},"Get Research Results":{"main":[[{"node":"Generate Report","type":"main","index":0}]]},"Is Apify Auth Error?":{"main":[[{"node":"Stop and Error","type":"main","index":0}],[{"node":"Valid Results","type":"main","index":0}]]},"URL Sources to Lists":{"main":[[{"node":"Append Blocks","type":"main","index":1}]]},"Ask Clarity Questions":{"main":[[{"node":"For Each Question...","type":"main","index":0}]]},"Generate SERP Queries":{"main":[[{"node":"SERP to Items","type":"main","index":0}]]},"Initiate DeepResearch":{"main":[[{"node":"Confirmation","type":"main","index":0}]]},"Report Page Generator":{"main":[[{"node":"Create Row","type":"main","index":0}]]},"Upload to Notion Page":{"main":[[{"node":"For Each Block...","type":"main","index":0}],[]]},"DeepResearch Learnings":{"main":[[{"node":"Research Goal + Learnings","type":"main","index":0}]]},"Notion Block Generator":{"main":[[{"node":"Parse JSON blocks","type":"main","index":0}]]},"DeepResearch Subworkflow":{"main":[[{"node":"Execution Data","type":"main","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"Notion Block Generator","type":"ai_languageModel","index":0}]]},"Structured Output Parser":{"ai_outputParser":[[{"node":"DeepResearch Learnings","type":"ai_outputParser","index":0}]]},"Research Goal + Learnings":{"main":[[{"node":"For Each Query...","type":"main","index":0}]]},"Structured Output Parser1":{"ai_outputParser":[[{"node":"Clarifying Questions","type":"ai_outputParser","index":0}]]},"Structured Output Parser2":{"ai_outputParser":[[{"node":"Generate SERP Queries","type":"ai_outputParser","index":0}]]},"Structured Output Parser4":{"ai_outputParser":[[{"node":"Report Page Generator","type":"ai_outputParser","index":0}]]}}}


name: Upload to Instagram, Tiktok & Youtube from Google Drive
author_name: Juan Carlos Cavero Gracia
author_username: carlosgracia
categories: []
created_at: 2025-02-12T20:39:02.442Z
updated_at: 2025-02-12T20:39:02.442Z
url: https://n8n.io/workflows/2894
scraped_at: 2025-07-06 21:16:30
description:
  Description
  This automation template is designed for content creators, digital marketers, and social media managers looking to simplify their video posting workflow. It automates the process of generating engaging video descriptions and uploading content to both Instagram and TikTok, making your social media management more efficient and error-free.

  Who Is This For?
  Content Creators & Influencers:** Streamline your video uploads and focus more on creating content.
  Digital Marketers:** Ensure consistent posting across multiple platforms with minimal manual intervention.
  Social Media Managers:** Automate repetitive tasks and maintain a steady online presence.

  What Problem Does This Workflow Solve?
  Manually creating descriptions and uploading videos to different platforms can be time-consuming and error-prone. This workflow addresses these challenges by:
  Automating Video Uploads:** Monitors a designated Google Drive folder for new videos.
  Generating Descriptions:** Uses OpenAI to transcribe video audio and generate engaging, customized social media descriptions.
  Ensuring Multi-Platform Consistency:** Simultaneously posts your video with the generated description to Instagram and TikTok.
  Error Notifications:** Optional Telegram integration sends alerts in case of issues, ensuring smooth operations.

  How It Works
  Video Upload: Place your video in the designated Google Drive folder.
  Description Generation: The automation triggers OpenAI to transcribe your video’s audio and generate a captivating description.
  Content Distribution: Automatically uploads the video and description to both Instagram and TikTok.
  Error Handling: Sends Telegram notifications if any issues arise during the process.

  Setup
  Generate an API token at upload-post.com and configure it in both the Upload to TikTok and Upload to Instagram nodes.
  Google Cloud Project: Create a project in Google Cloud Platform, enable the Google Drive API, and generate the necessary OAuth credentials to connect to your Google Drive account.
  Set up your Google Drive folder in the Google Drive Trigger node.
  Customize the OpenAI prompt in the Generate Social Description node to match your brand’s tone.
  (Optional) Configure Telegram credentials for error notifications.

  Requirements
  Accounts:** upload-post.com, Google Drive, and (optionally) Telegram.
  API Keys & Credentials:** Upload-post.com API token, OpenAI API key, and (optional) Telegram bot token.
  Google Cloud:** A project with the Google Drive API enabled and valid OAuth credentials.

  Use this template to enhance your productivity, maintain consistency across your social media channels, and engage your audience with high-quality video content.

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

workflow_json:
  {"id":"9nBQ1BfwxLhuzTcK","meta":{"instanceId":"3378b0d68c3b7ebfc71b79896d94e1a044dec38e99a1160aed4e9c323910fbe2"},"name":"google drive to instagram, tiktok and youtube","tags":[],"nodes":[{"id":"b6c1d2f5-a8de-42dc-a164-3b1e80b2f19d","name":"Google Drive Trigger","type":"n8n-nodes-base.googleDriveTrigger","position":[220,320],"parameters":{"event":"fileCreated","options":{},"pollTimes":{"item":[{"mode":"everyMinute"}]},"triggerOn":"specificFolder","folderToWatch":{"__rl":true,"mode":"list","value":"18m0i341QLQuyWuHv_FBdz8-r-QDtofYm","cachedResultUrl":"https://drive.google.com/drive/folders/18m0i341QLQuyWuHv_FBdz8-r-QDtofYm","cachedResultName":"Influencersde"}},"credentials":{"googleDriveOAuth2Api":{"id":"2TbhWtnbRfSloGxX","name":"Google Drive account"}},"typeVersion":1},{"id":"1dda484a-f6f5-4677-85a3-09b2a47e69c4","name":"Google Drive","type":"n8n-nodes-base.googleDrive","position":[400,320],"parameters":{"fileId":{"__rl":true,"mode":"","value":"={{ $json.id || $json.data[0].id }}"},"options":{},"operation":"download","authentication":"oAuth2"},"credentials":{"googleDriveOAuth2Api":{"id":"2TbhWtnbRfSloGxX","name":"Google Drive account"}},"retryOnFail":true,"typeVersion":1,"waitBetweenTries":5000},{"id":"f9388923-b20e-40f0-ba10-fd00b463b1a7","name":"Error Trigger","type":"n8n-nodes-base.errorTrigger","position":[620,660],"parameters":{},"typeVersion":1},{"id":"eda45ad6-d976-4665-9b6d-dae4c3212191","name":"Telegram","type":"n8n-nodes-base.telegram","position":[960,640],"webhookId":"f6729386-9905-45f1-800f-4fe01a06ac9c","parameters":{"text":"=🔔 ERROR SUBIENDO VIDEOS","additionalFields":{"appendAttribution":false}},"retryOnFail":true,"typeVersion":1.2,"waitBetweenTries":5000},{"id":"7b1d6015-49b8-423c-be64-e905ff791574","name":"If","type":"n8n-nodes-base.if","position":[760,660],"parameters":{"options":{},"conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"9fadb3fd-2547-42bd-8f40-f410a97dcf57","operator":{"type":"string","operation":"notContains"},"leftValue":"={{ $json.trigger.error.message }}","rightValue":"The DNS server returned an error, perhaps the server is offline"}]}},"typeVersion":2.1},{"id":"6e9882aa-b11f-4c1a-8600-eedda9d92046","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-220,0],"parameters":{"width":860,"height":260,"content":"## Description\nThis automation allows you to upload a video to a configured Google Drive folder, and it will automatically create descriptions and upload it to Instagram and TikTok.\n\n## How to Use\n1. Generate an API token at upload-post.com and add to Upload to Tiktok and Upload to Instagram nodes\n2. Configure your Google Drive folder\n3. Customize the OpenAI prompt for your specific use case\n4. Optional: Configure Telegram for error notifications\n\n## Requirements\n- upload-post.com account\n- Google Drive account\n- OpenAI API key\n"},"typeVersion":1},{"id":"b3eed1dc-8273-4593-ab07-8860fffa0907","name":"Get Audio from Video","type":"@n8n/n8n-nodes-langchain.openAi","notes":"Extract the audio from video for generate the description","position":[860,320],"parameters":{"options":{},"resource":"audio","operation":"transcribe"},"credentials":{"openAiApi":{"id":"XJdxgMSXFgwReSsh","name":"n8n key"}},"notesInFlow":true,"retryOnFail":true,"typeVersion":1,"waitBetweenTries":5000},{"id":"b057fea0-087e-4c7f-b5ac-6d16ca658437","name":"Read video from Google Drive","type":"n8n-nodes-base.writeBinaryFile","position":[580,320],"parameters":{"options":{},"fileName":"={{ $json.originalFilename.replaceAll(\" \", \"_\") }}"},"typeVersion":1},{"id":"f9296b8f-b631-4df4-b8b5-aa7139dd65cd","name":"Generate Description for Videos  in Tiktok and Instagram","type":"@n8n/n8n-nodes-langchain.openAi","notes":"Request to OpenAi for generate description with the audio extracted from the video","position":[1060,320],"parameters":{"modelId":{"__rl":true,"mode":"list","value":"gpt-4o","cachedResultName":"GPT-4O"},"options":{},"messages":{"values":[{"role":"system","content":"You are an expert assistant in creating engaging social media video titles."},{"content":"=I'm going to upload a video to social media. Here are some examples of descriptions that have worked well on Instagram:\n\nFollow and save for later. Discover InfluencersDe, the AI tool that automates TikTok creation and publishing to drive traffic to your website. Perfect for entrepreneurs and brands.\n#digitalmarketing #ugc #tiktok #ai #influencersde #contentcreation\n\nDiscover the video marketing revolution with InfluencersDe!\n.\n.\n.\n#socialmedia #videomarketing #ai #tiktok #influencersde #growthhacking\n\nDon't miss InfluencersDe, the tool that transforms your marketing strategy with just one click!\n.\n.\n.\n#ugc #ai #tiktok #digitalmarketing #influencersde #branding\n\nCan you create another title for the Instagram post based on this recognized audio from the video?\n\nAudio: {{ $('Get Audio from Video').item.json.text }}\n\nIMPORTANT: Reply only with the description, don't add anything else."}]}},"credentials":{"openAiApi":{"id":"XJdxgMSXFgwReSsh","name":"n8n key"}},"notesInFlow":true,"retryOnFail":true,"typeVersion":1.4,"waitBetweenTries":5000},{"id":"e80758fd-5532-48b0-b663-085629137fc0","name":"Read Video from Google Drive","type":"n8n-nodes-base.readBinaryFile","position":[1620,100],"parameters":{"filePath":"={{ $('Read video from Google Drive').item.json.originalFilename.replaceAll(\" \", \"_\") }}","dataPropertyName":"datavideo"},"typeVersion":1},{"id":"8f13c601-4282-4a44-8e8a-dc88e4165ee4","name":"Read Video from Google Drive2","type":"n8n-nodes-base.readBinaryFile","position":[1620,400],"parameters":{"filePath":"={{ $('Read video from Google Drive').item.json.originalFilename.replaceAll(\" \", \"_\") }}","dataPropertyName":"datavideo"},"typeVersion":1},{"id":"1b46976e-be37-49bd-b77b-e48d8e619954","name":"Upload Video and Description to Tiktok","type":"n8n-nodes-base.httpRequest","notes":"Generate in upload-post.com the token and add to the credentials in the header-> Authorization: Apikey (token here)","position":[1880,100],"parameters":{"url":"https://api.upload-post.com/api/upload","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","authentication":"genericCredentialType","bodyParameters":{"parameters":[{"name":"title","value":"={{ $('Generate Description for Videos  in Tiktok and Instagram').item.json.message.content.replaceAll(\"\\\"\", \"\") }}"},{"name":"platform[]","value":"tiktok"},{"name":"video","parameterType":"formBinaryData","inputDataFieldName":"datavideo"},{"name":"user","value":"Add user generated in upload-post"}]},"genericAuthType":"httpHeaderAuth"},"credentials":{"httpHeaderAuth":{"id":"WNjAx7UqrEZ1JDrR","name":"VituManco"}},"notesInFlow":true,"typeVersion":4.2},{"id":"0404a57f-2c1a-4ccd-90df-893dd01acaa0","name":"Upload Video and Description to Instagram","type":"n8n-nodes-base.httpRequest","notes":"Generate in upload-post.com the token and add to the credentials in the header-> Authorization: Apikey (token here)","position":[1880,400],"parameters":{"url":"https://api.upload-post.com/api/upload","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","authentication":"genericCredentialType","bodyParameters":{"parameters":[{"name":"title","value":"={{ $('Generate Description for Videos  in Tiktok and Instagram').item.json.message.content.replaceAll(\"\\\"\", \"\") }}"},{"name":"platform[]","value":"instagram"},{"name":"video","parameterType":"formBinaryData","inputDataFieldName":"datavideo"},{"name":"user","value":"Add user generated in upload-post"}]},"genericAuthType":"httpHeaderAuth"},"credentials":{"httpHeaderAuth":{"id":"47dO31ED0WIaJkR6","name":"Header Auth account"}},"notesInFlow":true,"typeVersion":4.2},{"id":"358da7b7-2d0a-475b-a10d-ffc499b5e99d","name":"Read Video from Google Drive3","type":"n8n-nodes-base.readBinaryFile","position":[1620,660],"parameters":{"filePath":"={{ $('Read video from Google Drive').item.json.originalFilename.replaceAll(\" \", \"_\") }}","dataPropertyName":"datavideo"},"typeVersion":1},{"id":"0e46ee9b-e466-4a5d-8916-3836eed4fc2d","name":"Upload Video and Description to Youtube","type":"n8n-nodes-base.httpRequest","notes":"Generate in upload-post.com the token and add to the credentials in the header-> Authorization: Apikey (token here)","position":[1880,660],"parameters":{"url":"https://api.upload-post.com/api/upload","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","authentication":"genericCredentialType","bodyParameters":{"parameters":[{"name":"title","value":"={{ $('Generate Description for Videos  in Tiktok and Instagram').item.json.message.content.replaceAll(\"\\\"\", \"\").substring(0, 70) }}\n"},{"name":"platform[]","value":"youtube"},{"name":"video","parameterType":"formBinaryData","inputDataFieldName":"datavideo"},{"name":"user","value":"test2"}]},"genericAuthType":"httpHeaderAuth"},"credentials":{"httpHeaderAuth":{"id":"47dO31ED0WIaJkR6","name":"Header Auth account"}},"notesInFlow":true,"typeVersion":4.2}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"13975e04-a6c4-42d0-887c-e6c4ff219f42","connections":{"If":{"main":[[{"node":"Telegram","type":"main","index":0}]]},"Google Drive":{"main":[[{"node":"Read video from Google Drive","type":"main","index":0}]]},"Error Trigger":{"main":[[{"node":"If","type":"main","index":0}]]},"Get Audio from Video":{"main":[[{"node":"Generate Description for Videos  in Tiktok and Instagram","type":"main","index":0}]]},"Google Drive Trigger":{"main":[[{"node":"Google Drive","type":"main","index":0}]]},"Read Video from Google Drive":{"main":[[{"node":"Upload Video and Description to Tiktok","type":"main","index":0}]]},"Read video from Google Drive":{"main":[[{"node":"Get Audio from Video","type":"main","index":0}]]},"Read Video from Google Drive2":{"main":[[{"node":"Upload Video and Description to Instagram","type":"main","index":0}]]},"Read Video from Google Drive3":{"main":[[{"node":"Upload Video and Description to Youtube","type":"main","index":0}]]},"Generate Description for Videos  in Tiktok and Instagram":{"main":[[{"node":"Read Video from Google Drive","type":"main","index":0},{"node":"Read Video from Google Drive2","type":"main","index":0},{"node":"Read Video from Google Drive3","type":"main","index":0}]]}}}


name: N8N for Beginners: Looping over Items
author_name: Dominik Baranowski
author_username: dom
nodes_used: ["n8n-nodes-base.code"]
categories: []
created_at: 2025-02-13T00:40:12.140Z
updated_at: 2025-02-13T00:40:12.140Z
url: https://n8n.io/workflows/2896
scraped_at: 2025-07-06 21:16:30
description:
  N8N for Beginners: Looping Over Items

  Description

  This workflow is designed for n8n beginners to understand how n8n handles looping (iteration) over multiple items. It highlights two key behaviors:

  Built-In Looping:** By default, most n8n nodes iterate over each item in an input array.
  Explicit Looping:* The *Loop Over Items* node allows controlled iteration, enabling *custom batch processing** and multi-step workflows.

  This workflow demonstrates the difference between processing an unsplit array of strings (single item) vs. a split array (multiple items).

  Setup

  1. Input Data

  To begin, paste the following JSON into the Manual Trigger node:

  {
    "urls": [
      "https://www.reddit.com",
      "https://www.n8n.io/",
      "https://n8n.io/",
      "https://supabase.com/",
      "https://duckduckgo.com/"
    ]
  }

  📌 Steps to Paste Data:
  Double-click** the "Manual Trigger" node.
  Click "Edit Output" (top-right corner).
  Paste the JSON and Save.
  The node turns purple, indicating that test data is pinned.

  1. Click "Test Workflow" button at the bottom of the canvas

  Explanation of the n8n Nodes in the Workflow

  | Node Name | Purpose | Documentation Link |
  |-----------|---------|--------------------|
  | Manual Trigger | Starts the workflow manually and sends test data | Docs |
  | Split Out | Converts an array of strings into separate JSON objects | Docs |
  | Loop Over Items (Loop Over Items 1) | Demonstrates how an unsplit array is treated as one item | Docs |
  | Loop Over Items (Loop Over Items 2) | Iterates over each item separately | Docs |
  | Wait | Introduces a delay per iteration (set to 1 second) | Docs |
  | Code | Adds a constant parameter (param1) to each item | Docs |
  | NoOp (Result Nodes) | Displays output for inspection | Docs |

  Execution Details

  1. How the Workflow Runs

  Manual Trigger starts execution** with the pasted JSON data.
  The workflow follows two paths:
    Unsplit Array Path → Loop Over Items 1  
       Processes the entire array as a single item.
       Result1 & Result5: Show that the array was not split.
    
    Split Array Path → Split Out → Loop Over Items 2
       Splits the array into separate objects.
       Result2, Result3, Result4: Show that each item is processed individually.
       A Wait node (1 sec delay) demonstrates controlled execution.
       Code nodes modify the JSON, adding a parameter (param1).

  2. What You Will See

  | Node | Expected Output |
  |------|---------------|
  | Result1 & Result5 | The entire array is processed as one item. |
  | Result2, Result3, Result4 | The array is split and processed as individual items. |
  | Wait Node | Adds a 1-second delay per item in Loop Over Items 2. |

  Use Cases

  This workflow is useful for:

  ✅ API Data Processing: Loop through API responses containing arrays.  
  ✅ Web Scraping: Process multiple URLs individually.  
  ✅ Task Automation: Execute a sequence of actions per item.  
  ✅ Workflow Optimization: Control execution order, delays, and dependencies.

  Notes

  Sticky notes are included in the workflow for easy reference.
  The Wait node is optional—remove it for faster execution.
  This template is structured for beginners but serves as a building block for more advanced automations.

workflow_json:
  {"id":"CDVBZRDH5gNUzIml","meta":{"instanceId":"ab60b809a7fa5daa22fa7edffc14e989a6e59d4063ec838ad62f2655caafd963","templateCredsSetupCompleted":true},"name":"N8N for Beginners: Looping over Items","tags":[],"nodes":[{"id":"500304a1-5164-4907-b0a7-e514e455e3dc","name":"Result1","type":"n8n-nodes-base.noOp","notes":"Look Here to see resulting output","position":[880,-280],"parameters":{},"notesInFlow":true,"typeVersion":1},{"id":"32808ad1-1a35-497f-b1d3-c935a924c541","name":"Result2","type":"n8n-nodes-base.noOp","notes":"Look here to see resulting output","position":[880,40],"parameters":{},"notesInFlow":true,"typeVersion":1},{"id":"f3c9fa5d-a4c7-4cf0-beb5-774d8483974f","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[800,-340],"parameters":{"color":3,"width":320,"height":240,"content":"\n### Result1 shows that the array of strings is seen as one item by Loop1"},"typeVersion":1},{"id":"0bb96765-60ce-4618-9b39-7cd203a3cb48","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[800,-60],"parameters":{"color":3,"width":320,"height":260,"content":"### Result2 shows that the Loop2 sees 5 items after the array of strings is split into separate objects"},"typeVersion":1},{"id":"b71fcc86-b0cd-4241-b0d6-21abe4c6b68d","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-1680,-1100],"parameters":{"width":1200,"height":2480,"content":"# N8N for Beginners: Looping Over Items\n\n## Description\n\nThis workflow is designed for **n8n beginners** to understand how n8n handles **looping (iteration)** over multiple items. It highlights two key behaviors:\n\n- **Built-In Looping:** By default, most n8n nodes iterate over each item in an input array.\n- **Explicit Looping:** The **Loop Over Items** node allows controlled iteration, enabling **custom batch processing** and multi-step workflows.\n\nThis workflow demonstrates the difference between processing an **unsplit array of strings (single item)** vs. **a split array (multiple items)**.\n\n---\n\n## Setup\n\n### 1. Input Data\n\nTo begin, **paste the following JSON** into the **Manual Trigger** node:\n\n```json\n{\n  \"urls\": [\n    \"https://www.reddit.com\",\n    \"https://www.n8n.io/\",\n    \"https://n8n.io/\",\n    \"https://supabase.com/\",\n    \"https://duckduckgo.com/\"\n  ]\n}\n```\n\nðŸ“Œ **Steps to Paste Data:**\n- **Double-click** the \"Manual Trigger\" node.\n- Click **\"Edit Output\"** (top-right corner).\n- Paste the JSON and **Save**.\n- The node **turns purple**, indicating that test data is pinned. \n\n---\n\n## Explanation of the n8n Nodes in the Workflow\n\n### Manual Trigger  \nThis node starts the workflow manually and sends test data.  \n**Documentation:** [Manual Trigger Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.manualtrigger/)\n\n### Split Out (Split Array of Strings into Array of Objects)  \nExtracts the `urls` array and splits it so that each URL becomes a separate JSON object.  \n**Documentation:** [Split Out Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.splitout/)\n\n### Loop Over Items (Loop Over Items 1)  \nDemonstrates how an **unsplit** array is treated as one item, processing it as a single unit.  \n**Documentation:** [Loop Over Items Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.splitinbatches/)\n\n### Loop Over Items (Loop Over Items 2)  \nProcesses the **split array** one item at a time. This demonstrates individual iteration and controlled looping.  \n**Documentation:** [Loop Over Items Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.splitinbatches/)\n\n### Wait Node  \nIntroduces a **1-second delay** per iteration to demonstrate sequential execution. This can be removed for faster performance.  \n**Documentation:** [Wait Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.wait/)\n\n### Code Nodes (Add param1 to outputX)  \nEach Code node adds a constant field (`param1`) to the data, ensuring that every item gets enriched with the same parameter.  \n**Documentation:** [Code Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/)\n\n### NoOp Nodes (Result1, Result2, Result3, Result4, Result5)\nThese nodes display the output at different stages of the workflow for inspection.\n**Documentation:** [NoOp Node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.noop/)\n\n\n\n---\n\n## Execution Details\n\n### 1. How the Workflow Runs\n\n- **Manual Trigger starts execution** with the pasted JSON data.\n- The workflow follows **two paths**:\n\n#### Unsplit Array Path â†’ Loop Over Items 1  \n- The original JSON is processed **as a single item**.  \n- **Result1 & Result5:** Show that the array was **not split** before processing.\n\n#### Split Array Path â†’ Split Out â†’ Loop Over Items 2  \n- The **Split Out** node converts the `urls` array into separate objects.\n- The **Loop Over Items 2** node processes each URL **one by one**.\n- A **Wait node** (1-second delay) demonstrates **controlled execution**.\n- **Code nodes** modify the JSON, adding the field (`param1`).\n- **Result2, Result3, Result4:** Display the final processed output.\n\n### 2. What You Will See\n\n- **Result1 & Result5:** The entire array is processed **as one item** before splitting.\n- **Result2, Result3, Result4:** Each URL is processed **individually** after being split.\n- **Wait Node:** Adds a **1-second delay per item** in **Loop Over Items 2**.\n\n---\n\n## Notes\n\n- Sticky notes are included in the workflow **for easy reference**.\n- The **Wait node** is **optional**â€”remove it for faster execution.\n- This template is structured for **beginners** but serves as a **building block** for more advanced automations.\n\n---\n\n"},"typeVersion":1},{"id":"53e7d23a-2a4f-4ada-aeb5-de128acf8625","name":"Split Array of Strings into Array of Objects","type":"n8n-nodes-base.splitOut","position":[-20,380],"parameters":{"options":{"destinationFieldName":"url"},"fieldToSplitOut":"urls"},"typeVersion":1},{"id":"4910fec6-d600-43be-97b2-5050039db416","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[800,700],"parameters":{"color":3,"width":320,"height":260,"content":"### Result4 shows that we can turn off the looping feature by setting the looping behavior to \"Run Once For All Items\""},"typeVersion":1},{"id":"f0e68b30-5341-4672-8d8e-7a24d894eb03","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[800,420],"parameters":{"color":3,"width":320,"height":240,"content":"### Result3 shows that looping over items is built in to n8n nodes"},"typeVersion":1},{"id":"70a987b9-6a4a-49c3-a87c-0dd9cc1879ed","name":"Result3","type":"n8n-nodes-base.noOp","notes":"Look here to see resulting output","position":[900,500],"parameters":{},"notesInFlow":true,"typeVersion":1},{"id":"9de5fac9-e987-4fb1-8f7f-b59af2985e5c","name":"Result4","type":"n8n-nodes-base.noOp","notes":"Look here to see resulting output","position":[900,780],"parameters":{},"notesInFlow":true,"typeVersion":1},{"id":"d5fee847-7758-44ac-a270-6334dd81bb97","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[800,-640],"parameters":{"color":3,"width":320,"height":260,"content":"### Result5 shows that the array of strings is seen as one item by Code5. So the behavior is the same as Loop1"},"typeVersion":1},{"id":"9a134620-4067-4c7a-8b0f-30e19c93a66c","name":"Result5","type":"n8n-nodes-base.noOp","notes":"Look here to see resulting output","position":[880,-540],"parameters":{},"notesInFlow":true,"typeVersion":1},{"id":"c273cd55-708d-4f86-81f2-3bbe991f59f8","name":"Paste JSON into this node","type":"n8n-nodes-base.manualTrigger","position":[-400,-540],"parameters":{},"typeVersion":1},{"id":"8f64b987-05c5-43a9-89c0-201499df0aa6","name":"Add param1 to output5","type":"n8n-nodes-base.code","position":[320,-540],"parameters":{"jsCode":"\n  $json.param1 =  'add_me_to_all_items_and_name_me_param1';\n\n\nreturn $json"},"typeVersion":2,"alwaysOutputData":true},{"id":"4920b4e4-b511-4059-b38a-623d14b6df25","name":"Add param1 to output1","type":"n8n-nodes-base.code","position":[500,-180],"parameters":{"mode":"runOnceForEachItem","jsCode":"\n  $json.param1 = \"add_me_to_all_items_and_name_me_param1\"\n\nreturn $json"},"typeVersion":2,"alwaysOutputData":true},{"id":"28ce5239-6437-4b7a-9395-3beb162fded6","name":"Loop over Items 2","type":"n8n-nodes-base.splitInBatches","position":[320,60],"parameters":{"options":{}},"typeVersion":3},{"id":"628edc5e-1b7f-4f50-9c29-8990bd4a5cc0","name":"Loop over Items 1","type":"n8n-nodes-base.splitInBatches","position":[320,-260],"parameters":{"options":{"reset":false}},"typeVersion":3},{"id":"ffccda97-066d-4c13-b4eb-a13ff849b90a","name":"Add param1 to output2","type":"n8n-nodes-base.code","position":[680,220],"parameters":{"mode":"runOnceForEachItem","jsCode":"\n  $json.param1 =   \"add_me_to_all_items_and_name_me_param1\"\n\n\nreturn $json"},"typeVersion":2,"alwaysOutputData":true},{"id":"6fb44840-6365-46db-9c50-eecd420f274f","name":"Add param1 to output3","type":"n8n-nodes-base.code","position":[320,500],"parameters":{"mode":"runOnceForEachItem","jsCode":"\n  $json.param1 =   \"add_me_to_all_items_and_name_me_param1\"\n\n\nreturn $json"},"typeVersion":2,"alwaysOutputData":true},{"id":"51b8d766-25ed-407f-a956-693b93bda95f","name":"Add param1 to output4","type":"n8n-nodes-base.code","position":[320,780],"parameters":{"jsCode":"\n  $json.param1 =   \"add_me_to_all_items_and_name_me_param1\"\n\n\nreturn $json"},"typeVersion":2,"alwaysOutputData":true},{"id":"f8edde34-cf47-42e2-bbd3-552df2509451","name":"Wait one second(just for show)","type":"n8n-nodes-base.wait","position":[480,180],"webhookId":"61aef80b-4e9d-43ae-a083-cd87b4fdec11","parameters":{"amount":1},"typeVersion":1.1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"e1eff37a-1ffd-4691-9560-eada5baab88d","connections":{"Result1":{"main":[[]]},"Result2":{"main":[[]]},"Loop over Items 1":{"main":[[{"node":"Result1","type":"main","index":0}],[{"node":"Add param1 to output1","type":"main","index":0}]]},"Loop over Items 2":{"main":[[{"node":"Result2","type":"main","index":0}],[{"node":"Wait one second(just for show)","type":"main","index":0}]]},"Add param1 to output1":{"main":[[{"node":"Loop over Items 1","type":"main","index":0}]]},"Add param1 to output2":{"main":[[{"node":"Loop over Items 2","type":"main","index":0}]]},"Add param1 to output3":{"main":[[{"node":"Result3","type":"main","index":0}]]},"Add param1 to output4":{"main":[[{"node":"Result4","type":"main","index":0}]]},"Add param1 to output5":{"main":[[{"node":"Result5","type":"main","index":0}]]},"Paste JSON into this node":{"main":[[{"node":"Split Array of Strings into Array of Objects","type":"main","index":0},{"node":"Add param1 to output5","type":"main","index":0},{"node":"Loop over Items 1","type":"main","index":0}]]},"Wait one second(just for show)":{"main":[[{"node":"Add param1 to output2","type":"main","index":0}]]},"Split Array of Strings into Array of Objects":{"main":[[{"node":"Loop over Items 2","type":"main","index":0},{"node":"Add param1 to output4","type":"main","index":0},{"node":"Add param1 to output3","type":"main","index":0}]]}}}


name: AI-Powered Social Media Content Generator & Publisher
author_name: Amjid Ali
author_username: amjid
categories: []
created_at: 2025-02-20T12:47:09.520Z
updated_at: 2025-02-20T12:47:09.520Z
url: https://n8n.io/workflows/2950
scraped_at: 2025-07-06 21:16:30
description:
  AI-Powered Social Media Content Generator & Publisher 🚀  

  This AI-driven n8n workflow automates social media content creation and publishing across LinkedIn, Instagram, Facebook, and Twitter (X). It generates engaging, platform-optimized posts using Google Gemini AI, based on user inputs such as a post title, keywords, and an uploaded image. The workflow ensures seamless content generation and publishing, making it a perfect tool for marketers, business owners, influencers, and content creators.  

  🌟 Features & Benefits  

  ✅ AI-Generated Social Media Posts – Uses Google Gemini AI to create high-quality, optimized content.  
  ✅ Multi-Platform Support – Automatically generates posts for LinkedIn, Instagram, Facebook, and Twitter (X).  
  ✅ Hashtag & SEO Optimization – Includes trending hashtags to enhance visibility and engagement.  
  ✅ Image Upload & Processing – Allows image uploads for Instagram and Facebook using imgbb and Facebook Graph API.  
  ✅ Automated Publishing – Posts are automatically published on all selected platforms.  
  ✅ Custom Call-to-Action – Each platform's post is optimized with CTAs for better engagement.  
  ✅ User-Friendly Form Submission – Easy-to-use form where users can enter post titles, keywords, links, and images.  
  ✅ Performance Tracking – Provides confirmation and tracking links for published posts.  

  📌 How It Works  

  1️⃣ User Submission Form  
     Fill out the form with Post Title, Keywords, and an Optional Link.  
     Upload an image for Instagram & Facebook posts.  

  2️⃣ AI Content Generation  
     Google Gemini AI generates optimized content for each platform.  
     The AI ensures professional, engaging, and audience-specific content.  

  3️⃣ Content Review  
     Users review and approve the AI-generated content before publishing.  

  4️⃣ Automated Publishing  
     Posts are automatically published on LinkedIn, Facebook, Instagram, and Twitter (X).  
     Uses Facebook Graph API, LinkedIn API, Twitter API, and Instagram API.  

  5️⃣ Post Confirmation & Tracking  
     Get links to track published posts on each platform.  

  🛠️ Prerequisites  

  Before using this workflow, ensure you have:  

  ✅ n8n Instance (Cloud or Self-Hosted)  
  ✅ Social Media API Credentials (Facebook, Instagram, LinkedIn, Twitter API)  
  ✅ Google Gemini AI API Key  
  ✅ imgbb API Key (for image hosting)  

  Get N8n
  My Affiliate Link
  Buy My Book:  
  Mastering n8n on Amazon

  Full Courses & Tutorials:  
  http://lms.syncbricks.com

  📺 YouTube Video Tutorial 🎥  

  Watch the step-by-step tutorial on how to set up and use this n8n workflow template:  

  🔗 YouTube Tutorial - AI-Powered Social Media Posting in n8n  

  🎯 Use Cases  

  📌 Marketing Agencies – Automate client content scheduling.  
  📌 Businesses & Brands – Maintain a consistent brand presence on social media.  
  📌 Content Creators & Influencers – Generate high-quality posts quickly.  
  📌 E-commerce & Startups – Promote products and services effortlessly.  
  📌 Corporate & Enterprise Teams – Streamline internal and external communications.  

  Important
  Start with n8n  

  Learn n8n with Amjid   
  Get n8n Book 

  👨‍💻 Creator Information  

  👤 Developed by: Amjid Ali  
  🌐 Website: SyncBricks  
  📧 Email: info@syncbricks.com  
  💼 LinkedIn: Amjid Ali  
  📺 YouTube: SyncBricks  

  💡 Support & Contributions  

  If you find this workflow helpful, consider supporting my work:  

  👉 Donate via PayPal  

  For full courses on * AI Automation*, visit:  

  📚 SyncBricks LMS  

  📚 AI and Auotmation Course 

  👉  Get Started with N8N  

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

workflow_json:
  {"id":"LzDLmNc63zyqQBXz","meta":{"instanceId":"942ff96108ceedc60ba777eabc4e8ea2ae87415579996cd64d20cc647c4d3523"},"name":"Social Media Tutorial","tags":[],"nodes":[{"id":"8034d082-f50e-4f6b-8a79-ce7f86012d72","name":"On form submission","type":"n8n-nodes-base.formTrigger","position":[920,20],"webhookId":"syncbricks-social-posting-ai-agent","parameters":{},"typeVersion":2.2},{"id":"e38a74d5-a733-4f5c-a97b-2c761b46919b","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[1180,520],"parameters":{},"typeVersion":1.7},{"id":"ca0a8aef-0251-45ed-bc9b-05ee977febf9","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[980,780],"parameters":{},"typeVersion":1},{"id":"31e88059-94ca-4d4e-a673-e0f8cd1ac96e","name":"Structured Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[1300,780],"parameters":{},"typeVersion":1.2},{"id":"ffda1c79-faa4-4cc8-8655-6f7fc14b7e2d","name":"Split Form Input","type":"n8n-nodes-base.set","position":[1320,40],"parameters":{},"typeVersion":3.2},{"id":"37e443e1-6925-44a1-a07e-9eb1120e55a9","name":"Upload Image","type":"n8n-nodes-base.form","position":[320,1160],"webhookId":"0dc811ef-b2e0-4213-a0c9-e9b5fb9fcbf1","parameters":{},"typeVersion":1},{"id":"265068ce-22fc-4c41-9ed2-93eadc0ce25f","name":"Split Data","type":"n8n-nodes-base.set","position":[1560,40],"parameters":{},"typeVersion":3.2},{"id":"b8470879-413e-4901-bf39-23a19beaee5f","name":"Data for AI","type":"n8n-nodes-base.set","position":[1880,40],"parameters":{},"typeVersion":3.4},{"id":"eef02dcb-7c7f-4d6c-a1fd-039c8b30f10d","name":"Aggregate","type":"n8n-nodes-base.aggregate","position":[1680,760],"parameters":{},"typeVersion":1},{"id":"097e7724-4dc0-4cc9-b12c-2dbdae4e024f","name":"Form","type":"n8n-nodes-base.form","position":[1820,1960],"webhookId":"e84b9492-038c-4701-a367-c68237ddebf6","parameters":{},"typeVersion":1},{"id":"7b1d64fc-02ad-4b8f-ad1e-be8894abd932","name":"Nest Top Meta","type":"n8n-nodes-base.set","position":[940,1160],"parameters":{},"typeVersion":3.3},{"id":"11ddcfe8-1978-4f5a-8c29-67e72920431a","name":"Rename Image Binary Top Image","type":"n8n-nodes-base.code","position":[-40,1960],"parameters":{},"typeVersion":2},{"id":"19892590-5ddf-47ac-b544-7a72a68bd45e","name":"Publish to Facebook","type":"n8n-nodes-base.facebookGraphApi","position":[440,2080],"parameters":{},"typeVersion":1},{"id":"b3b0068b-c75a-427c-bb2d-77b21bc6ff16","name":"Publish to LinkedIn","type":"n8n-nodes-base.linkedIn","position":[420,1840],"parameters":{},"typeVersion":1},{"id":"ed5fe0c2-a07a-45f1-90cb-65f21d416a1a","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[860,-80],"parameters":{"content":""},"typeVersion":1},{"id":"c4a2e59d-165a-49cc-8074-9868ee4e0d6c","name":"X","type":"n8n-nodes-base.twitter","position":[440,1600],"parameters":{},"typeVersion":2},{"id":"66ba98a9-24c0-4128-9ad9-792a0d400aae","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[860,340],"parameters":{"content":""},"typeVersion":1},{"id":"02fafdc7-0272-4f34-9b66-dfbe8e16e70d","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-240,960],"parameters":{"content":""},"typeVersion":1},{"id":"21d945c3-446c-4bb9-8696-a70034801485","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-240,1480],"parameters":{"content":""},"typeVersion":1},{"id":"c9efdc38-94c6-494e-a932-45b75312bb54","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1620,1480],"parameters":{"content":""},"typeVersion":1},{"id":"93632f4f-9182-4b76-bbe0-e6d5dd230452","name":"Edit Fields","type":"n8n-nodes-base.set","position":[800,1600],"parameters":{},"typeVersion":3.4},{"id":"89f22cf8-9499-4b7f-872d-97099c5d1e50","name":"Image for Instagram","type":"n8n-nodes-base.httpRequest","position":[740,2280],"parameters":{},"typeVersion":4.2},{"id":"c415eeb9-f916-4c08-afb1-baed3f3280cc","name":"Publish to Instagram","type":"n8n-nodes-base.facebookGraphApi","position":[1060,2280],"parameters":{},"typeVersion":1},{"id":"1c8f6ba6-c28b-45a8-ba0d-3f2f21ccbfa0","name":"Merge1","type":"n8n-nodes-base.merge","position":[1380,1940],"parameters":{},"typeVersion":3},{"id":"d9cfdcd1-18db-4d0d-9b6a-66897600e496","name":"Upload Image to imgbb.com","type":"n8n-nodes-base.httpRequest","position":[440,2280],"parameters":{},"typeVersion":4.2},{"id":"f7e5b1b1-aeaa-4851-be04-53e8255fa343","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[-240,-80],"parameters":{"content":""},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"4a55bf93-ae0c-4aa9-84a8-cd4d02375e51","connections":{"X":{"main":[[{"node":"Edit Fields","type":"main","index":0}]]},"Merge1":{"main":[[{"node":"Form","type":"main","index":0}]]},"AI Agent":{"main":[[{"node":"Aggregate","type":"main","index":0}]]},"Aggregate":{"main":[[{"node":"Upload Image","type":"main","index":0}]]},"Split Data":{"main":[[{"node":"Data for AI","type":"main","index":0}]]},"Data for AI":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Edit Fields":{"main":[[{"node":"Merge1","type":"main","index":0}]]},"Upload Image":{"main":[[{"node":"Nest Top Meta","type":"main","index":0}]]},"Nest Top Meta":{"main":[[{"node":"Rename Image Binary Top Image","type":"main","index":0}]]},"Split Form Input":{"main":[[{"node":"Split Data","type":"main","index":0}]]},"On form submission":{"main":[[{"node":"Split Form Input","type":"main","index":0}]]},"Image for Instagram":{"main":[[{"node":"Publish to Instagram","type":"main","index":0}]]},"Publish to Facebook":{"main":[[{"node":"Merge1","type":"main","index":2}]]},"Publish to LinkedIn":{"main":[[{"node":"Merge1","type":"main","index":1}]]},"Publish to Instagram":{"main":[[{"node":"Merge1","type":"main","index":3}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Structured Output Parser":{"ai_outputParser":[[{"node":"AI Agent","type":"ai_outputParser","index":0}]]},"Upload Image to imgbb.com":{"main":[[{"node":"Image for Instagram","type":"main","index":0}]]},"Rename Image Binary Top Image":{"main":[[{"node":"X","type":"main","index":0},{"node":"Publish to LinkedIn","type":"main","index":0},{"node":"Publish to Facebook","type":"main","index":0},{"node":"Upload Image to imgbb.com","type":"main","index":0}]]}}}


name: 🤖 AI Powered RAG Chatbot for Your Docs + Google Drive + Gemini + Qdrant
author_name: Joseph LePage
author_username: joe
categories: []
created_at: 2025-02-23T01:59:29.690Z
updated_at: 2025-02-23T01:59:29.690Z
url: https://n8n.io/workflows/2982
scraped_at: 2025-07-06 21:16:30
description:
  🤖 AI-Powered RAG Chatbot with Google Drive Integration

  This workflow creates a powerful RAG (Retrieval-Augmented Generation) chatbot that can process, store, and interact with documents from Google Drive using Qdrant vector storage and Google's Gemini AI.

  How It Works

  Document Processing & Storage 📚
  Retrieves documents from a specified Google Drive folder
  Processes and splits documents into manageable chunks
  Extracts metadata using AI for enhanced search capabilities
  Stores document vectors in Qdrant for efficient retrieval

  Intelligent Chat Interface 💬
  Provides a conversational interface powered by Google Gemini
  Uses RAG to retrieve relevant context from stored documents
  Maintains chat history in Google Docs for reference
  Delivers accurate, context-aware responses

  Vector Store Management 🗄️
  Features secure delete operations with human verification
  Includes Telegram notifications for important operations
  Maintains data integrity with proper version control
  Supports batch processing of documents

  Setup Steps

  Configure API Credentials:
     Set up Google Drive & Docs access
     Configure Gemini AI API
     Set up Qdrant vector store connection
     Add Telegram bot for notifications
     Add OpenAI Api Key to the 'Delete Qdrant Points by File ID' node

  Configure Document Sources:
     Set Google Drive folder ID
     Define Qdrant collection name
     Set up document processing parameters

  Test and Deploy:
     Verify document processing
     Test chat functionality
     Confirm vector store operations
     Check notification system


  This workflow is ideal for organizations needing to create intelligent chatbots that can access and understand large document repositories while maintaining context and providing accurate responses through RAG technology.

nodes_used:
  ["n8n-nodes-base.telegram","n8n-nodes-base.googleDrive","n8n-nodes-base.googleDocs","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.code","@n8n/n8n-nodes-langchain.embeddingsOpenAi","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.memoryBufferWindow","@n8n/n8n-nodes-langchain.textSplitterTokenSplitter","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.vectorStoreQdrant","@n8n/n8n-nodes-langchain.lmChatGoogleGemini","@n8n/n8n-nodes-langchain.informationExtractor"]

workflow_json:
  {"id":"8tusZTTtcyaiznEG","meta":{"instanceId":"31e69f7f4a77bf465b805824e303232f0227212ae922d12133a0f96ffeab4fef","templateCredsSetupCompleted":true},"name":"🤖 AI Powered RAG Chatbot for Your Docs + Google Drive + Gemini + Qdrant","tags":[],"nodes":[{"id":"7ad5796b-d1a0-4cc1-bed6-105ff499beeb","name":"Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[620,720],"parameters":{"options":{"metadata":{"metadataValues":[{"name":"file_id","value":"={{ $json.id }}"},{"name":"pubkey","value":"={{ $json.name }}"},{"name":"=overarching_theme","value":"={{ $('Extract Meta Data').item.json.output.overarching_theme }}"},{"name":"recurring_topics","value":"={{ $('Extract Meta Data').item.json.output.recurring_topics }}"},{"name":"pain_points","value":"={{ $('Extract Meta Data').item.json.output.pain_points }}"},{"name":"analytical_insights","value":"={{ $('Extract Meta Data').item.json.output.analytical_insights }}"},{"name":"conclusion","value":"={{ $('Extract Meta Data').item.json.output.conclusion }}"},{"name":"keywords","value":"={{ $('Extract Meta Data').item.json.output.keywords }}"}]}},"dataType":"binary","binaryMode":"specificField"},"typeVersion":1},{"id":"84986ee2-4d79-49e8-8778-b8a955cf2174","name":"Token Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterTokenSplitter","position":[720,860],"parameters":{"chunkSize":3000},"typeVersion":1},{"id":"82aa7016-f3af-4de8-a410-b1c802041213","name":"Qdrant Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStoreQdrant","onError":"continueRegularOutput","position":[540,520],"parameters":{"mode":"insert","options":{},"qdrantCollection":{"__rl":true,"mode":"id","value":"=nostr-damus-user-profiles"}},"credentials":{"qdrantApi":{"id":"DJQ4hVAVdWZytjr2","name":"QdrantApi account"}},"executeOnce":false,"retryOnFail":true,"typeVersion":1},{"id":"07f4d14a-1864-406b-946b-09c776e3038b","name":"Loop Over Items","type":"n8n-nodes-base.splitInBatches","onError":"continueRegularOutput","position":[180,-140],"parameters":{"options":{}},"typeVersion":3},{"id":"b0f9b066-62de-41bc-afce-dcb4d20d100c","name":"Wait","type":"n8n-nodes-base.wait","position":[1020,840],"webhookId":"237d7f8a-aead-479a-b813-f407d1f37fa5","parameters":{},"typeVersion":1.1},{"id":"2a883003-f5ec-409e-97e4-809360ca11ed","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-1160,-280],"parameters":{},"typeVersion":1},{"id":"cfbb6b77-142f-4689-b051-436f40ababe6","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[1120,-20],"parameters":{"options":{"temperature":0.4},"modelName":"models/gemini-2.0-flash-exp"},"credentials":{"googlePalmApi":{"id":"L9UNQHflYlyF9Ngd","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"c9c50387-64a3-473f-9ea7-509a301836a3","name":"Merge","type":"n8n-nodes-base.merge","position":[820,200],"parameters":{"mode":"combine","options":{},"combineBy":"combineAll"},"typeVersion":3},{"id":"ea143b9f-9bd8-4f3f-8979-5a0fd2691e9d","name":"Extract Meta Data","type":"@n8n/n8n-nodes-langchain.informationExtractor","position":[1020,-180],"parameters":{"text":"={{ $json.data }}","options":{"systemPromptTemplate":"You are an expert extraction algorithm.\nOnly extract relevant information from the text.\nIf you do not know the value of an attribute asked to extract, you may omit the attribute's value."},"attributes":{"attributes":[{"name":"overarching_theme","description":"Summarize the main theme(s) discussed in the \"Overarching Theme\" section."},{"name":"recurring_topics","description":"List the recurring topics mentioned in the \"Common Threads\" section as an array of strings."},{"name":"pain_points","description":"Summarize the user's frustrations or challenges mentioned in the \"Pain Points\" section as an array of strings."},{"name":"analytical_insights","description":"Extract a list of key analytical observations from the \"Analytical Insights\" section, including shifts in tone or behavior."},{"name":"conclusion","description":"Summarize the conclusions drawn about the user’s threads and their overall focus."},{"name":"keywords","description":"Generate a list of 10 keywords that capture the essence of the document (e.g., \"askNostr,\" \"decentralization,\" \"spam filtering\")."}]}},"typeVersion":1},{"id":"2ddd778f-6676-4a4b-b592-536401831bc8","name":"Get File Contents","type":"n8n-nodes-base.extractFromFile","position":[820,-180],"parameters":{"options":{},"operation":"text"},"typeVersion":1},{"id":"cdbb8bbc-967c-4f01-b844-4d31328153df","name":"Download File From Google Drive","type":"n8n-nodes-base.googleDrive","position":[500,-180],"parameters":{"fileId":{"__rl":true,"mode":"id","value":"={{ $json.id }}"},"options":{},"operation":"download"},"credentials":{"googleDriveOAuth2Api":{"id":"UhdXGYLTAJbsa0xX","name":"Google Drive account"}},"typeVersion":3},{"id":"399e196c-76ec-4077-aacc-f669173b0229","name":"Find File Ids in Google Drive Folder","type":"n8n-nodes-base.googleDrive","position":[-620,-160],"parameters":{"filter":{"driveId":{"mode":"list","value":"My Drive"},"folderId":{"__rl":true,"mode":"id","value":"={{ $json.folder_id }}"}},"options":{},"resource":"fileFolder","returnAll":true},"credentials":{"googleDriveOAuth2Api":{"id":"UhdXGYLTAJbsa0xX","name":"Google Drive account"}},"typeVersion":3},{"id":"3bc4f005-c6c8-4f73-816a-1573d6dfb62f","name":"text-embeddings-3-large","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[480,720],"parameters":{"model":"text-embedding-3-large","options":{}},"credentials":{"openAiApi":{"id":"jEMSvKmtYfzAkhe6","name":"OpenAi account"}},"typeVersion":1},{"id":"5d42b34a-7156-4163-a2c4-a9cb3c984c96","name":"Google Folder ID","type":"n8n-nodes-base.set","position":[-820,-160],"parameters":{"options":{},"assignments":{"assignments":[{"id":"e6f6188f-c895-4c8c-b39a-0ef55b490fd6","name":"folder_id","type":"string","value":"[Your-Google-Folder-ID]"}]}},"typeVersion":3.4},{"id":"7be310c2-d30f-42a2-8f57-33c7b184e429","name":"gpt-4o-mini1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-400,940],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"jEMSvKmtYfzAkhe6","name":"OpenAi account"}},"typeVersion":1},{"id":"18aacfd9-3f6e-4fba-9f68-d8cc95bc667b","name":"Delete Qdrant Points by File ID","type":"@n8n/n8n-nodes-langchain.code","position":[-500,800],"parameters":{"code":{"execute":{"code":"const { QdrantVectorStore } = require(\"@langchain/qdrant\");\nconst { OpenAIEmbeddings } = require(\"@langchain/openai\");\n\n// Qdrant connection details\nconst url = \"http://localhost:6333/\";\nconst apiKey = \"\";\n\n// OpenAI API configuration\nconst openAIApiKey = \"[Your-OpenAI-API-Key]\";\n\n// Get input data\nconst items = this.getInputData()[0];\n// console.log(items)\n\nconst collectionName =  items.json.qdrant_collection_name;\n// console.log(collectionName)\n\nasync function deleteDocumentsFromQdrant() {\n  try {\n    // Initialize OpenAI embeddings\n    const embeddings = new OpenAIEmbeddings({\n      model: \"text-embedding-3-large\",\n      openAIApiKey: openAIApiKey\n    });\n\n    // Connect to existing Qdrant collection\n    const vectorStore = await QdrantVectorStore.fromExistingCollection(embeddings, {\n      url: url,\n      apiKey: apiKey,\n      collectionName: collectionName,\n    });\n\n    const fileIds = items.json.appended_id.map(item => item);\n\n    console.log(fileIds)\n\n    // Delete points by fileId\n    const deletionResults = await Promise.all(fileIds.map(async (file_id) => {\n      const filter = {\n        must: [\n          {\n            key: \"metadata.file_id\",\n            match: { value: file_id }\n          }\n        ]\n      };\n\n      try {\n        // Access the underlying Qdrant client to perform the deletion\n        await vectorStore.client.delete(collectionName, { filter });\n        return { file_id, status: \"deleted\" };\n      } catch (error) {\n        console.error(`Error deleting documents for fileId ${file_id}:`, error);\n        return { file_id, status: \"error\", message: error.message };\n      }\n    }));\n\n    return deletionResults;\n  } catch (error) {\n    console.error(\"An error occurred during the deletion process:\", error);\n    return error.message;\n  }\n}\n\n// Execute the deletion process\ntry {\n  const result = await deleteDocumentsFromQdrant();\n  console.log(\"Deletion process completed:\", result);\n  return [];\n} catch (error) {\n  console.error(\"Failed to execute deletion process:\", error);\n  return [{ json: { error } }];\n}\n\n"}},"inputs":{"input":[{"type":"main","required":true,"maxConnections":1},{"type":"ai_languageModel","required":true,"maxConnections":1}]},"outputs":{"output":[{"type":"main"}]}},"typeVersion":1},{"id":"329cec97-aac1-4714-97ce-add5915b1078","name":"Qdrant Collection Name","type":"n8n-nodes-base.set","position":[-700,100],"parameters":{"options":{},"assignments":{"assignments":[{"id":"11fa71e9-6cbc-4183-9439-e3379b2b970e","name":"qdrant_collection_name","type":"string","value":"nostr-damus-user-profiles"}]}},"typeVersion":3.4},{"id":"82e98da8-530d-4a3c-97e6-5e91ad644a46","name":"File Id List","type":"n8n-nodes-base.summarize","position":[-700,280],"parameters":{"options":{},"fieldsToSummarize":{"values":[{"field":"id","aggregation":"append"}]}},"typeVersion":1.1},{"id":"f3def614-2709-4847-831d-d6a80c86ec1c","name":"Merge1","type":"n8n-nodes-base.merge","position":[-340,340],"parameters":{"mode":"combine","options":{},"combineBy":"combineByPosition"},"typeVersion":3},{"id":"cfe399fb-8560-4ac4-98f7-4f539ae6a52c","name":"Merge2","type":"n8n-nodes-base.merge","position":[-80,-140],"parameters":{},"typeVersion":3},{"id":"1059da47-2abd-4884-b9c2-6b7d1623e31d","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1280,560],"parameters":{"color":3,"width":1180,"height":760,"content":"## Prepare Qdrant Vector Store"},"typeVersion":1},{"id":"2616e08f-070e-45b5-906f-40e832519aa2","name":"Confirm Qdrant Delete Points","type":"n8n-nodes-base.telegram","position":[-1060,760],"webhookId":"29aac1ac-9345-4e44-babf-ebcfae701d88","parameters":{"chatId":"={{ $env.TELEGRAM_CHAT_ID }}","message":"=WARNING - {{ $json.appended_id.length }} Records in the Qdrant vector store collection \"{{ $json.qdrant_collection_name }}\" will be deleted.  Are you sure you want to continue?  This action cannot be undone!","options":{"limitWaitTime":{"values":{"resumeUnit":"minutes","resumeAmount":15}}},"operation":"sendAndWait","approvalOptions":{"values":{"approvalType":"double"}}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"9d167192-e87b-41be-87f2-d7ddf866bb8d","name":"If","type":"n8n-nodes-base.if","position":[-1060,1000],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"20f530d6-fd55-420d-b8a9-70e5303f688e","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ $json.data.approved }}","rightValue":""}]}},"typeVersion":2.2},{"id":"1178f8cf-ece0-4b11-942d-18dd025da366","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[320,420],"parameters":{"color":7,"width":920,"height":640,"content":"## Perform Qdrant Vector Store Operations"},"typeVersion":1},{"id":"cbf17a08-2f4c-4605-8418-5bf93ade7cf4","name":"Send Declined Message","type":"n8n-nodes-base.telegram","position":[-740,1120],"webhookId":"382a3b43-b83f-47b1-a276-67c6b98a441a","parameters":{"text":"Qdrant vector store upsert declined","chatId":"={{ $env.TELEGRAM_CHAT_ID }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"890f478a-e000-418d-8582-4fef946e44d8","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-900,-380],"parameters":{"width":480,"height":840,"content":"## 🌟Workflow Config\n\n- Google Drive Folder Id\n- Qdrant Collection Name\n- List of Google Drive File Id's"},"typeVersion":1},{"id":"d2bc2fed-c134-4e54-bd9d-69996be966a3","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[740,-280],"parameters":{"color":6,"width":640,"height":420,"content":"## Extract Metadata for Qdrant Hybrid Search"},"typeVersion":1},{"id":"61f3c21e-bc2a-47bc-8ab1-678b1f425ee3","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[400,-280],"parameters":{"color":2,"width":300,"height":320,"content":"## Google Drive"},"typeVersion":1},{"id":"61e608e4-ac6a-4131-9ca8-c46a5134bff9","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[80,-360],"parameters":{"color":5,"width":1360,"height":1480,"content":"## ✨ Save Documents to Qdrant Vector Store"},"typeVersion":1},{"id":"410681cb-e757-42c0-89de-902edbe998e3","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-580,680],"parameters":{"color":5,"width":420,"height":400,"content":"## Delete From Qdrant Vector Store\nThis operation can not be undone!!!"},"typeVersion":1},{"id":"238469ce-3710-4681-b1b2-200c1b699d5e","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-1200,640],"parameters":{"color":4,"width":380,"height":520,"content":"## Human In The Loop\nUser must verify deletion of points from Qdrant vector store"},"typeVersion":1},{"id":"0b2f6ff4-dd02-4f0e-b2eb-60b1ce736cf5","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[-1280,-380],"parameters":{"color":4,"width":340,"height":460,"content":"## 👍Start Here!"},"typeVersion":1},{"id":"abde545b-1a23-4b3e-8046-335b9d0fa445","name":"Webhook","type":"n8n-nodes-base.webhook","disabled":true,"position":[-1160,-100],"webhookId":"3a30557f-9264-4bc8-a253-a9356677c791","parameters":{"path":"upsert","options":{}},"typeVersion":2},{"id":"897d29af-719d-4fe7-93a9-44c693cc6547","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[-600,-1200],"parameters":{"text":"={{ $json.chatInput }}","options":{"systemMessage":"=You are an intelligent assistant specialized in answering user questions using Nostr user profiles. Your primary goal is to provide precise, contextually relevant, and concise answers based on the tools and resources available.\n\n### TOOL\nUse the \"nostr_damus_user_profiles\" tool to:\n- perform semantic similarity searches and retrieve information from Nostr user profiles relevant to the user's query.\n- access detailed information about Nostr and/or Damus users when additional context or specifics are required.\n\n### Key Instructions\n1. **Response Guidelines**:\n   - Clearly explain how the retrieved information addresses the user's query, if applicable.\n   - If no relevant information is found, respond with: \"I cannot find the answer in the available resources.\"\n\n2. **Focus and Relevance**:\n   - Ensure all responses are directly aligned with the user's question.\n   - Avoid including extraneous details or relying solely on internal knowledge.\n"},"promptType":"define"},"typeVersion":1.7},{"id":"316b0d8d-bbc7-4c40-b6d0-d0c762554fca","name":"Window Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[-580,-1000],"parameters":{"contextWindowLength":40},"typeVersion":1.3},{"id":"f1e342a8-d50e-48a8-9d7a-850f8be93cff","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-1160,-1200],"webhookId":"5f1c0c82-0ff9-40c7-9e2e-b1a96ffe24cd","parameters":{"options":{}},"typeVersion":1.1},{"id":"12902fa9-5bcb-4e8b-ac13-7f4cb6e7e1d0","name":"Google Gemini Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[-760,-1000],"parameters":{"options":{"maxOutputTokens":8192},"modelName":"models/gemini-2.0-flash-exp"},"credentials":{"googlePalmApi":{"id":"L9UNQHflYlyF9Ngd","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"1c5818d4-6251-4d14-8b4f-d1f3ddfbed38","name":"text-embeddings-3-large1","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[-320,-840],"parameters":{"model":"text-embedding-3-large","options":{}},"credentials":{"openAiApi":{"id":"jEMSvKmtYfzAkhe6","name":"OpenAi account"}},"typeVersion":1},{"id":"80056067-5d2b-4ac7-8e69-e75bd66a1ad4","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[-900,-1300],"parameters":{"color":5,"width":860,"height":680,"content":"## 🤖Retrieve Content from Qdrant Vector Store"},"typeVersion":1},{"id":"b45b18e4-7773-4eec-837b-f43fc0eeb90c","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[-1280,-1300],"parameters":{"color":4,"width":340,"height":320,"content":"## 🗣️ Chat with Your Documents"},"typeVersion":1},{"id":"8fe891dd-dee6-4abb-bc09-d90e6d7bf3cb","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[-1360,-480],"parameters":{"color":7,"width":2880,"height":1880,"content":"# Step 1 - Save Documents to Qdrant Vector Store"},"typeVersion":1},{"id":"4a9bf716-3fc3-4ccc-b831-19a1afdb4588","name":"Sticky Note12","type":"n8n-nodes-base.stickyNote","position":[-1360,-1420],"parameters":{"color":7,"width":1780,"height":880,"content":"# Step 2 - Chat with Your Documents from Qdrant Vector Store"},"typeVersion":1},{"id":"fccedfde-c5aa-4237-9d1c-feb9ebabf4f3","name":"Google Drive","type":"n8n-nodes-base.googleDrive","disabled":true,"position":[120,-780],"parameters":{"name":"=Nostr Chatbot - Avatar - {{ $now }}","content":"={{ $json.output }}","driveId":{"__rl":true,"mode":"list","value":"My Drive"},"options":{},"folderId":{"__rl":true,"mode":"list","value":"root","cachedResultName":"/ (Root folder)"},"operation":"createFromText"},"credentials":{"googleDriveOAuth2Api":{"id":"UhdXGYLTAJbsa0xX","name":"Google Drive account"}},"typeVersion":3},{"id":"6d6813f6-4f2e-499a-9e5c-fe15624a91ef","name":"Respond to User","type":"n8n-nodes-base.set","position":[120,-960],"parameters":{"options":{},"assignments":{"assignments":[{"id":"cd8f88e1-19c0-4b9e-914d-e2e7ba21d9fa","name":"output","type":"string","value":"={{ $json.output }}"}]}},"typeVersion":3.4},{"id":"1c73bae9-2bdd-4383-a6f8-3cf43d3c15be","name":"Sticky Note13","type":"n8n-nodes-base.stickyNote","position":[0,-1300],"parameters":{"color":4,"width":340,"height":300,"content":"## Save Chat History"},"typeVersion":1},{"id":"db3dcc69-d1d0-48a1-b949-37f2de802b4a","name":"Update Chat History","type":"n8n-nodes-base.googleDocs","position":[120,-1200],"parameters":{"actionsUi":{"actionFields":[{"text":"=\n-------------------------------\n\n{{ $now }}\n\n{{ $('When chat message received').item.json.chatInput  }}\n\n{{ $json.output }}","action":"insert"}]},"operation":"update","documentURL":"1ej_qLolUFp1h4eZkrb99T3DWQ3JOwXVEMS3VUjWyVf0"},"credentials":{"googleDocsOAuth2Api":{"id":"YWEHuG28zOt532MQ","name":"Google Docs account"}},"typeVersion":2},{"id":"2dd28eed-b71b-44fb-bb78-8cb50b0d0c93","name":"Qdrant Vector Store Tool","type":"@n8n/n8n-nodes-langchain.vectorStoreQdrant","position":[-420,-1000],"parameters":{"mode":"retrieve-as-tool","topK":20,"options":{},"toolName":"nostr_damus_user_profiles","toolDescription":"Retrieve information about Nostr or Damus users","qdrantCollection":{"__rl":true,"mode":"list","value":"nostr-damus-user-profiles","cachedResultName":"nostr-damus-user-profiles"}},"credentials":{"qdrantApi":{"id":"DJQ4hVAVdWZytjr2","name":"QdrantApi account"}},"typeVersion":1},{"id":"3b130cf8-ab8e-4001-a3d0-a129194aee98","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","disabled":true,"position":[-760,-820],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"jEMSvKmtYfzAkhe6","name":"OpenAi account"}},"typeVersion":1.2},{"id":"ccc64645-ad14-4b6b-a507-0b5fb0ac945f","name":"Send Completed Message","type":"n8n-nodes-base.telegram","position":[500,200],"webhookId":"382a3b43-b83f-47b1-a276-67c6b98a441a","parameters":{"text":"Qdrant vector store upsert completed","chatId":"={{ $env.TELEGRAM_CHAT_ID }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"pAIFhguJlkO3c7aQ","name":"Telegram account"}},"typeVersion":1.2},{"id":"885fef53-2246-45b1-a122-ab5b82374585","name":"Sticky Note14","type":"n8n-nodes-base.stickyNote","position":[-2120,-480],"parameters":{"width":700,"height":1240,"content":"# 🤖 AI-Powered RAG Chatbot with Google Drive Integration\n\nThis workflow creates a powerful RAG (Retrieval-Augmented Generation) chatbot that can process, store, and interact with documents from Google Drive using Qdrant vector storage and Google's Gemini AI.\n\n## How It Works\n\n### Document Processing & Storage 📚\n- Retrieves documents from a specified Google Drive folder\n- Processes and splits documents into manageable chunks\n- Extracts metadata using AI for enhanced search capabilities\n- Stores document vectors in Qdrant for efficient retrieval\n\n### Intelligent Chat Interface 💬\n- Provides a conversational interface powered by Google Gemini\n- Uses RAG to retrieve relevant context from stored documents\n- Maintains chat history in Google Docs for reference\n- Delivers accurate, context-aware responses\n\n### Vector Store Management 🗄️\n- Features secure delete operations with human verification\n- Includes Telegram notifications for important operations\n- Maintains data integrity with proper version control\n- Supports batch processing of documents\n\n## Setup Steps\n\n1. Configure API Credentials:\n   - Set up Google Drive & Docs access\n   - Configure Gemini AI API\n   - Set up Qdrant vector store connection\n   - Add Telegram bot for notifications\n\n2. Configure Document Sources:\n   - Set Google Drive folder ID\n   - Define Qdrant collection name\n   - Set up document processing parameters\n\n3. Test and Deploy:\n   - Verify document processing\n   - Test chat functionality\n   - Confirm vector store operations\n   - Check notification system\n\n\nThis workflow is ideal for organizations needing to create intelligent chatbots that can access and understand large document repositories while maintaining context and providing accurate responses through RAG technology.\n"},"typeVersion":1}],"active":false,"settings":{"timezone":"America/Vancouver","callerPolicy":"workflowsFromSameOwner","executionOrder":"v1"},"versionId":"0c0d90e5-02f9-4169-b477-fd90c52ce44e","connections":{"If":{"main":[[{"node":"Delete Qdrant Points by File ID","type":"main","index":0}],[{"node":"Send Declined Message","type":"main","index":0}]]},"Wait":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Merge":{"main":[[{"node":"Qdrant Vector Store","type":"main","index":0}]]},"Merge1":{"main":[[{"node":"Confirm Qdrant Delete Points","type":"main","index":0}]]},"Merge2":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Webhook":{"main":[[{"node":"Google Folder ID","type":"main","index":0}]]},"AI Agent":{"main":[[{"node":"Update Chat History","type":"main","index":0},{"node":"Respond to User","type":"main","index":0}]]},"Data Loader":{"ai_document":[[{"node":"Qdrant Vector Store","type":"ai_document","index":0}]]},"File Id List":{"main":[[{"node":"Merge1","type":"main","index":1}]]},"gpt-4o-mini1":{"ai_languageModel":[[{"node":"Delete Qdrant Points by File ID","type":"ai_languageModel","index":0}]]},"Token Splitter":{"ai_textSplitter":[[{"node":"Data Loader","type":"ai_textSplitter","index":0}]]},"Loop Over Items":{"main":[[{"node":"Send Completed Message","type":"main","index":0}],[{"node":"Download File From Google Drive","type":"main","index":0}]]},"Respond to User":{"main":[[]]},"Google Folder ID":{"main":[[{"node":"Find File Ids in Google Drive Folder","type":"main","index":0}]]},"Extract Meta Data":{"main":[[{"node":"Merge","type":"main","index":0}]]},"Get File Contents":{"main":[[{"node":"Extract Meta Data","type":"main","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[]]},"Qdrant Vector Store":{"main":[[{"node":"Wait","type":"main","index":0}]]},"Update Chat History":{"main":[[]]},"Window Buffer Memory":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"Qdrant Collection Name":{"main":[[{"node":"Merge1","type":"main","index":0}]]},"text-embeddings-3-large":{"ai_embedding":[[{"node":"Qdrant Vector Store","type":"ai_embedding","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"Extract Meta Data","type":"ai_languageModel","index":0}]]},"Qdrant Vector Store Tool":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]],"ai_vectorStore":[[]]},"text-embeddings-3-large1":{"ai_embedding":[[{"node":"Qdrant Vector Store Tool","type":"ai_embedding","index":0}]]},"Google Gemini Chat Model1":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"When chat message received":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Confirm Qdrant Delete Points":{"main":[[{"node":"If","type":"main","index":0}]]},"Delete Qdrant Points by File ID":{"main":[[{"node":"Merge2","type":"main","index":1}]]},"Download File From Google Drive":{"main":[[{"node":"Get File Contents","type":"main","index":0},{"node":"Merge","type":"main","index":1}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"Google Folder ID","type":"main","index":0}]]},"Find File Ids in Google Drive Folder":{"main":[[{"node":"File Id List","type":"main","index":0},{"node":"Qdrant Collection Name","type":"main","index":0},{"node":"Merge2","type":"main","index":0}]]}}}


name: All-in-One Telegram/Baserow AI Assistant 🤖🧠 Voice/Photo/Save Notes/Long Term Mem
author_name: Rod
author_username: xxbean-sproutxx
categories: []
created_at: 2025-02-23T09:02:25.572Z
updated_at: 2025-02-23T09:02:25.572Z
url: https://n8n.io/workflows/2986
scraped_at: 2025-07-06 21:16:30
description:
  Telegram Personal Assistant with Long-Term Memory & Note-Taking

  This n8n workflow transforms your Telegram bot into a powerful personal assistant that handles voice, photo, and text messages. The assistant uses AI to interpret messages, save important details as long-term memories or notes in a Baserow database, and recall information for future interactions.

  🌟 How It Works

  Message Reception & Routing  
     Telegram Integration: The workflow is triggered by incoming messages on your Telegram bot.  
     Dynamic Routing: A switch node inspects the message to determine whether it's voice, text, or photo (with captions) and routes it for the appropriate processing.

  Content Processing  
     Voice Messages: Audio files are retrieved and sent to an AI transcription node to convert spoken words into text.  
     Text Messages: Text is directly captured and prepared for analysis.  
     Photos: If an image is received, the bot fetches the file (and caption, if provided) and uses an AI-powered image analysis node to extract relevant details.

  AI-Powered Agent & Memory Management  
     The core AI agent (powered by GPT-4o-mini) processes the incoming message along with any previous conversation history stored in PostgreSQL memory buffers.  
     Long-Term Memory: When a message contains personal or noteworthy information, the assistant uses a dedicated tool to save this data as a long-term memory in Baserow.  
     Note-Taking: For specific instructions or reminders, the assistant saves concise notes in a separate Baserow table.  
     The AI agent follows defined rules to decide which details are saved as memories and which are saved as notes.

  Response Generation  
     After processing the message and updating memory/notes as needed, the AI agent crafts a contextual and personalized response.  
     The response is sent back to the user via Telegram, ensuring smooth and natural conversation flow.

  🚀 Key Features

  Multimodal Input:**  
    Seamlessly handles voice, photo (with captions), and text messages.

  Long-Term Memory & Note-Taking:**  
    Uses a Baserow database to store personal details and notes, enhancing conversational context over time.

  AI-Driven Contextual Responses:**  
    Leverages an AI agent to generate personalized, context-aware replies based on current input and past interactions.

  User Security & Validation:**  
    Incorporates validation steps to verify the user's Telegram ID before processing, ensuring secure and personalized interactions.

  Easy Baserow Setup:**  
    Comes with a clear setup guide and sample configurations to quickly integrate Baserow for managing memories and notes.

  🔧 Setup Guide

  Telegram Bot Setup:  
     Create your bot via BotFather and obtain the Bot Token.  
     Configure the Telegram webhook in n8n with your bot's token and URL.

  Baserow Database Configuration:  
     Memory Table:  
       Create a workspace titled "Memories and Notes".  
       Set up a table (e.g., "Memory Table") with at least two fields:  
         Memory (long text)  
         Date Added (US date format with time)  
     Notes Table:  
       Duplicate the Memory Table and rename it to "Notes Table".  
       Change the first field's name from "Memory" to "Notes".

  n8n Workflow Import & Configuration:  
     Import the workflow JSON into your n8n instance.  
     Update credentials for Telegram, Baserow, OpenAI, and PostgreSQL (for memory buffering) as needed.
     Adjust node settings if you need to customize AI agent prompts or memory management rules.

  Testing & Deployment:  
     Test your bot by sending various message types (text, voice, photo) to confirm that the workflow processes them correctly, updates Baserow, and returns the appropriate response.  
     Monitor logs to ensure that memory and note entries are correctly stored and retrieved.

  ✨ Example Interactions

  Voice Message Processing:**  
    User sends a voice note requesting a reminder.  
    Bot Response: "Thanks for your message! I've noted your reminder and saved it for future reference."

  Photo with Caption:**  
    User sends a photo with the caption "Save this recipe for dinner ideas."  
    Bot Response: "Got it! I've saved this recipe along with the caption for you."

  Text Message for Memory Saving:**  
    User: "I love hiking on weekends."  
    Bot Response: "Noted! I’ll remember your interest in hiking."

  Retrieving Information:**  
    User asks: "What notes do I have?"  
    Bot Response: "Here are your latest notes: [list of saved notes]."

  🛠️ Resources & Next Steps

  Telegram Bot Configuration:** Telegram BotFather Guide  
  n8n Documentation:** n8n Docs  
  Community Forums:** Join discussions and share your customizations!

  This workflow not only streamlines message processing but also empowers users with a personal AI assistant that remembers details over time. Customize the rules and responses further to fit your unique requirements and enjoy a more engaging, intelligent conversation experience on Telegram!

nodes_used:
  ["n8n-nodes-base.telegram","n8n-nodes-base.baserow","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.memoryBufferWindow","@n8n/n8n-nodes-langchain.openAi","@n8n/n8n-nodes-langchain.memoryPostgresChat"]

workflow_json:
  {"id":"Dctc6QKyRXK17oEq","meta":{"instanceId":"ca87034fd2d5cf9c52373260a6e37ca15a4a059ecc2971ac41c079ce4aa21138","templateCredsSetupCompleted":true},"name":"All-in-One Telegram/Baserow AI Assistant 🤖🧠 Voice/Photo/Save Notes/Long Term Mem","tags":[],"nodes":[{"id":"bbcaac28-f07c-421b-91c6-e3b2d024a71f","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-900,80],"parameters":{"color":4,"width":340,"height":380,"content":"## Retrieve Long Term Memories\nBaserow"},"typeVersion":1},{"id":"399c0a44-72b5-4e71-b578-3e4eb8087b3c","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[-180,420],"parameters":{"width":280,"height":380,"content":"## Save To Current Chat Memory"},"typeVersion":1},{"id":"d0438c1d-42e4-47d0-b23b-78f9cee5a28c","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[140,420],"parameters":{"color":4,"width":280,"height":380,"content":"## Save Long Term Memories\nBaserow"},"typeVersion":1},{"id":"d8cbf733-2a69-45d5-9767-43e8c67a43ee","name":"gpt-4o-mini","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-400,580],"parameters":{"options":{}},"credentials":{"openAiApi":{"id":"lpt7A1AOIMshaaE7","name":"OpenAi account"}},"typeVersion":1.1},{"id":"3cd6b923-b369-45e6-a3c1-5fff74a3074c","name":"Chat Response","type":"n8n-nodes-base.set","position":[220,160],"parameters":{"options":{},"assignments":{"assignments":[{"id":"d6f68b1c-a6a6-44d4-8686-dc4dcdde4767","name":"output","type":"string","value":"={{ $json.output }}"}]}},"typeVersion":3.4},{"id":"912bf06d-ae8f-4513-a0c9-83c1edb1c159","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-500,420],"parameters":{"color":3,"width":280,"height":380,"content":"## LLM"},"typeVersion":1},{"id":"d5cf2019-d9bb-4fb6-b95c-e9e9f9ac5808","name":"Telegram Response","type":"n8n-nodes-base.telegram","position":[560,180],"webhookId":"2ae9d05c-68e8-440a-9f13-08e5ef92bf6c","parameters":{"text":"={{ $json.output }}","chatId":"={{ $('Listen for Telegram Events').item.json.body.message.chat.id }}","additionalFields":{"parse_mode":"HTML","appendAttribution":false}},"credentials":{"telegramApi":{"id":"EDuT6lIMLHRxdqqN","name":"Telegram account"}},"typeVersion":1.2},{"id":"0858e353-8d83-437c-90bc-f57b31e92d1c","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[440,60],"parameters":{"width":360,"height":300,"content":"## Telegram \n(Optional)"},"typeVersion":1},{"id":"c315e630-2ed3-4141-a715-ab08849336be","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-540,80],"parameters":{"color":5,"width":1320,"height":780,"content":"## AI AGENT with Long Term Memory & Note Storage"},"typeVersion":1},{"id":"2d09319d-f3be-43b8-a134-929992d4f469","name":"AI Tools Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[-140,180],"parameters":{"text":"={{\n  (() => {\n    try {\n      return $('Edit Fields').item.json.text;\n    } catch (e) {\n      return undefined;\n    }\n  })() ||\n  (() => {\n    try {\n      return $('Edit Fields1').item.json.text;\n    } catch (e) {\n      return undefined;\n    }\n  })() ||\n  (() => {\n    try {\n      return $('Transcribe Recording').item.json.text;\n    } catch (e) {\n      return undefined;\n    }\n  })() ||\n  'default value' // optional default if all are undefined\n}}\n","options":{"systemMessage":"=## ROLE  \nYou are a friendly, attentive, and helpful AI assistant. Your primary goal is to assist the user while maintaining a personalized and engaging interaction. When possible, address the user by their first name to create a warmer, more personal experience.\n\n---\n\n## KEY TOOLS: MEMORY & NOTE MANAGEMENT\n\nThese are the core features of this workflow. **You do not need permission to save notes and memories; it’s your decision based on the conversation.**\n\n### Memory Management  \n- **When to Use:**  \n  Evaluate each incoming message for noteworthy or personal information (e.g., preferences, habits, goals, important events, etc.).  \n- **Action:**  \n  If the message contains such details, autonomously use the **Save Memory** Baserow tool to store a clear, concise summary.  \n- **Response:**  \n  Always provide a meaningful reply that naturally acknowledges the input without revealing that a memory was saved.\n\n### Note Management  \n- **When to Use:**  \n  If the user shares specific instructions, reminders, or standalone pieces of information meant to be retained, use the **Save Note** Baserow tool.  \n- **Action:**  \n  Save these as concise notes without asking for permission.  \n- **Response:**  \n  Your reply should integrate the note context naturally, ensuring that the note’s purpose is honored without overemphasizing the saving action.\n\n---\n\n## GENERAL RULES\n\n1. **Context Awareness:**  \n   - Use stored memories and notes to craft contextually relevant and personalized responses.  \n   - Always consider the date and time when a memory or note was collected to ensure your responses are up-to-date.\n\n2. **User-Centric Responses:**  \n   - Tailor your responses based on the user's preferences and past interactions.  \n   - If the user’s first name is provided in the user info section, address them by name when it feels natural and appropriate.  \n   - Be proactive in recalling relevant details from memory or notes without overwhelming the conversation.\n\n3. **Privacy and Sensitivity:**  \n   - Handle all user data with care. Do not share or expose stored information unless it directly enhances the interaction.  \n   - Never store passwords or usernames.\n\n4. **Fallback Responses:**  \n   - If no specific task or question arises (e.g., when only saving information), respond in a way that keeps the conversation flowing naturally:  \n     - “Thanks for sharing that, [First Name]! Is there anything else I can help you with today?”  \n   - DO NOT tell jokes as a fallback response.\n\n5. **Additional Tools:**  \n   - The remaining tools (Contacts, Calendar, Web Search, Qdrant Vector Retrieval) are available as extra features. They can be used when relevant but are secondary to the core Memory and Note management functionalities.\n\n---\n\n## USER INFO\n\n- **First Name**: {{ $('Listen for Telegram Events').item.json.body.message.from.first_name }}\n- **Age**: (if provided)  \n- **Location**: (if provided)  \n- **Job/Profession**: (if provided)\n\nUtilize this information to personalize your responses. For example, if the user's first name is available, begin responses with “Hi [First Name], …”\n\n---\n\n## REMAINING TOOLS\n\n### <More Tools>\n- <if you add more tools, add them here and add descriptions>\n\n---\n\n## MEMORIES  \n\n### Recent Noteworthy Memories  \nHere are the most recent memories collected from the user, including their date and time of collection:  \n\n**{{  \n  $json.data.map(item => item.Memory).join('\\n')  \n}}**\n\n**Guidelines:**  \n- Prioritize recent memories while considering older ones if still relevant.  \n- Cross-reference memories for consistency (e.g., if conflicting details are present, clarify as needed).\n\n---\n\n## NOTES  \n\n### Recent Notes Collected from User:  \nHere are the most recent notes collected from the user:  \n\n**{{  \n  $json.data.map(item => item.Notes).join('\\n')  \n}}**\n\n**Guidelines:**  \n- Use notes for specific instructions or reminders.  \n- Keep note content distinct from general memory content.\n\n---\n\n## ADDITIONAL INSTRUCTIONS  \n\n- Think critically before responding to ensure your answers are thoughtful and accurate.  \n- Strive to build trust with the user by being consistent, reliable, and personable.  \n- Avoid robotic or overly formal language; aim for a conversational tone that is both friendly and helpful.\n\n## CURRENT DATE\n\n - {{ $now.setZone('America/Chicago').toISO() }} (Set Timezone Accordingly) \n"},"promptType":"define"},"typeVersion":1.7,"alwaysOutputData":false},{"id":"4a5a636a-e526-4b0f-bf11-8cd623e46c68","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[460,420],"parameters":{"color":4,"width":280,"height":380,"content":"## Save Notes\nBaserow"},"typeVersion":1},{"id":"46cb38d9-4932-481e-96f2-14b3224de0a9","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[-900,480],"parameters":{"color":4,"width":340,"height":380,"content":"## Retrieve Notes\nBaserow"},"typeVersion":1},{"id":"c643683f-eee6-49c2-9f1a-05ba9a0742a6","name":"Aggregate","type":"n8n-nodes-base.aggregate","position":[-320,180],"parameters":{"options":{},"aggregate":"aggregateAllItemData"},"typeVersion":1},{"id":"cdd999a7-d14f-4e20-88ea-4170c8cd521c","name":"Merge","type":"n8n-nodes-base.merge","position":[-480,180],"parameters":{},"typeVersion":3},{"id":"a60582a7-63ca-497e-aec0-2be8077ebc53","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-2160,180],"parameters":{"color":7,"width":420,"height":260,"content":"## Validate Telegram User\n"},"typeVersion":1},{"id":"3b3b2573-5a2e-4c0f-8005-376ed55b068b","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-2220,780],"parameters":{"color":6,"width":1289,"height":432,"content":"# Process Image"},"typeVersion":1},{"id":"3d27c492-758b-45d2-bc79-a51cc69ac2ef","name":"Get Audio File","type":"n8n-nodes-base.telegram","position":[-1380,180],"webhookId":"4f5c2290-ff1a-4ce0-8319-e84807b1b1fc","parameters":{"fileId":"={{ $json.body.message.voice.file_id }}","resource":"file"},"credentials":{"telegramApi":{"id":"EDuT6lIMLHRxdqqN","name":"Telegram account"}},"typeVersion":1.2},{"id":"9bef0848-30a5-4e98-b0e8-640e061c475d","name":"Analyze Image","type":"@n8n/n8n-nodes-langchain.openAi","position":[-1460,1000],"parameters":{"modelId":{"__rl":true,"mode":"list","value":"gpt-4o-mini","cachedResultName":"GPT-4O-MINI"},"options":{},"resource":"image","inputType":"base64","operation":"analyze"},"credentials":{"openAiApi":{"id":"lpt7A1AOIMshaaE7","name":"OpenAi account"}},"typeVersion":1.6},{"id":"b493ea36-c9f6-470d-97a9-8df43c10af18","name":"Transcribe Recording","type":"@n8n/n8n-nodes-langchain.openAi","position":[-1100,180],"parameters":{"options":{},"resource":"audio","operation":"transcribe","binaryPropertyName":"=data"},"credentials":{"openAiApi":{"id":"lpt7A1AOIMshaaE7","name":"OpenAi account"}},"typeVersion":1.6},{"id":"05aff1e5-daf0-47d3-8df3-a548ca4ca2cd","name":"Edit Fields","type":"n8n-nodes-base.set","position":[-1240,540],"parameters":{"options":{},"assignments":{"assignments":[{"id":"b37b48ba-8fef-4e6c-bbca-73e6c2e1e0a8","name":"text","type":"string","value":"={{ $json.body.message.text }}"}]}},"typeVersion":3.4},{"id":"ea70790d-716b-4f5d-b3d0-99259481ef22","name":"Convert to Image File","type":"n8n-nodes-base.convertToFile","position":[-1640,1000],"parameters":{"options":{"fileName":"={{ $json.result.file_path }}"},"operation":"toBinary","sourceProperty":"data"},"typeVersion":1.1},{"id":"3e5913bf-0270-4e32-8647-80138abefde5","name":"Extract from File to Base64","type":"n8n-nodes-base.extractFromFile","position":[-1820,1000],"parameters":{"options":{},"operation":"binaryToPropery"},"typeVersion":1},{"id":"7d13ffbe-9496-4037-a7f2-d7b5774698ca","name":"Sticky Note12","type":"n8n-nodes-base.stickyNote","position":[-1440,80],"parameters":{"color":6,"width":513,"height":309,"content":"# Process Audio"},"typeVersion":1},{"id":"73570d5a-87a6-4d1f-95f3-2b8ed087a28a","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-1440,420],"parameters":{"color":6,"width":513,"height":329,"content":"# Process Text"},"typeVersion":1},{"id":"f8851e90-d710-4bc6-9705-af4828d65a48","name":"Message Router","type":"n8n-nodes-base.switch","position":[-1880,480],"parameters":{"rules":{"values":[{"outputKey":"audio","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"operator":{"type":"object","operation":"exists","singleValue":true},"leftValue":"={{ $json.body.message.voice }}","rightValue":""}]},"renameOutput":true},{"outputKey":"text","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"342f0883-d959-44a2-b80d-379e39c76218","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $json.body.message.text }}","rightValue":""}]},"renameOutput":true},{"outputKey":"image","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"ded3a600-f861-413a-8892-3fc5ea935ecb","operator":{"type":"array","operation":"exists","singleValue":true},"leftValue":"={{ $json.body.message.photo }}","rightValue":""}]},"renameOutput":true}]},"options":{"fallbackOutput":"extra"}},"typeVersion":3.2},{"id":"88127339-2cc5-4364-9f27-6dea9df505ff","name":"Image Schema1","type":"n8n-nodes-base.set","position":[-2160,880],"parameters":{"options":{},"assignments":{"assignments":[{"id":"17989eb0-feca-4631-b5c8-34b1d4a6c72b","name":"image_file_id","type":"string","value":"={{ $json.body.message.photo.last().file_id }}"},{"id":"9317d7ae-dffd-4b1f-9a9c-b3cc4f1e0dd3","name":"caption","type":"string","value":"={{ $json.body.message.caption }}"}]}},"typeVersion":3.4},{"id":"b0922d42-9864-4d9a-a5c9-b674892935ff","name":"caption","type":"n8n-nodes-base.splitOut","position":[-1460,860],"parameters":{"options":{},"fieldToSplitOut":"caption"},"typeVersion":1},{"id":"74256b12-6f3b-44ba-a98b-bd233f90c360","name":"Merge1","type":"n8n-nodes-base.merge","position":[-1260,860],"parameters":{"mode":"combine","options":{},"combineBy":"combineByPosition"},"typeVersion":3},{"id":"9f77577b-167c-4628-b2d1-37e17d9ddb10","name":"Get Image","type":"n8n-nodes-base.telegram","position":[-2000,1000],"webhookId":"2d9b0a49-b46f-4794-9f4b-f406a213e74a","parameters":{"fileId":"={{ $json.image_file_id }}","resource":"file"},"credentials":{"telegramApi":{"id":"EDuT6lIMLHRxdqqN","name":"Telegram account"}},"typeVersion":1.2},{"id":"ffdf119a-cfa1-408a-aaca-458691f8d56b","name":"Edit Fields1","type":"n8n-nodes-base.set","position":[-1100,860],"parameters":{"options":{},"assignments":{"assignments":[{"id":"b37b48ba-8fef-4e6c-bbca-73e6c2e1e0a8","name":"text","type":"string","value":"={{ $json.caption }}\n\n{{ $json.content }}"}]}},"typeVersion":3.4},{"id":"2b750b39-c72a-46ae-8e3f-0060181d2a51","name":"Sticky Note13","type":"n8n-nodes-base.stickyNote","position":[-2220,80],"parameters":{"color":4,"width":753,"height":669,"content":"# Secure User"},"typeVersion":1},{"id":"18fcbf54-301e-449b-bb67-7f63753ac4c5","name":"Sticky Note14","type":"n8n-nodes-base.stickyNote","position":[-1720,60],"parameters":{"color":3,"width":273,"height":269,"content":"# Error\n"},"typeVersion":1},{"id":"8d7824b1-92d0-4907-8468-1d04e7d40d6c","name":"Postgres Chat Memory","type":"@n8n/n8n-nodes-langchain.memoryPostgresChat","position":[-20,540],"parameters":{"sessionKey":"={{ $('Listen for Telegram Events').item.json.body.message.from.id }}","sessionIdType":"customKey","contextWindowLength":50},"credentials":{"postgres":{"id":"aVzWyCraiN3kiV5K","name":"Postgres account"}},"typeVersion":1.3},{"id":"f21c0dfa-d16a-461d-9ff3-8b9932e8abb6","name":"Save Note Tool","type":"n8n-nodes-base.baserowTool","position":[560,600],"parameters":{"tableId":640,"fieldsUi":{"fieldValues":[{"fieldId":6025,"fieldValue":"={{ $fromAI('notes', `note to be created`, 'string') }}"},{"fieldId":6027,"fieldValue":"={{ $fromAI('date-added', 'date created', 'string') }}"}]},"operation":"create","databaseId":122,"descriptionType":"manual","toolDescription":"Save Notes"},"credentials":{"baserowApi":{"id":"1YeHyTi4fmB007co","name":"Baserow account"}},"typeVersion":1},{"id":"242ff3e7-3421-4bc4-a877-0164cee7cd69","name":"Save Memory","type":"n8n-nodes-base.baserowTool","position":[240,600],"parameters":{"tableId":639,"fieldsUi":{"fieldValues":[{"fieldId":6022,"fieldValue":"={{ $fromAI('memory', 'memory to be created', 'string') }}"},{"fieldId":6024,"fieldValue":"={{ $fromAI('date-added', 'date created', 'string') }}"}]},"operation":"create","databaseId":122,"descriptionType":"manual","toolDescription":"Save Long Term Memories"},"credentials":{"baserowApi":{"id":"1YeHyTi4fmB007co","name":"Baserow account"}},"typeVersion":1},{"id":"f681f671-7759-46ba-b674-5b8b0e385d09","name":"Listen for Telegram Events","type":"n8n-nodes-base.webhook","position":[-2380,240],"webhookId":"097f36f3-1574-44f9-815f-58387e3b20bf","parameters":{"path":"gram","options":{"binaryPropertyName":"data"},"httpMethod":"POST"},"typeVersion":2},{"id":"959a8a01-0fb9-4bc9-9997-cc49b3a81216","name":"Validation","type":"n8n-nodes-base.set","position":[-2100,240],"parameters":{"options":{},"assignments":{"assignments":[{"id":"0cea6da1-652a-4c1e-94c3-30608ced90f8","name":"first_name","type":"string","value":"[Your First Name on Telegram]"},{"id":"b90280c6-3e36-49ca-9e7e-e15c42d256cc","name":"last_name","type":"string","value":"[Your Last Name on Telegram]"},{"id":"f6d86283-16ca-447e-8427-7d3d190babc0","name":"id","type":"number","value":1122334455}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"7903c22c-26f2-4e89-9e27-ee945e225b0e","name":"Check User & Chat ID","type":"n8n-nodes-base.if","position":[-1920,240],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"5fe3c0d8-bd61-4943-b152-9e6315134520","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $('Listen for Telegram Events').item.json.body.message.chat.first_name }}","rightValue":"={{ $json.first_name }}"},{"id":"98a0ea91-0567-459c-bbce-06abc14a49ce","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $('Listen for Telegram Events').item.json.body.message.chat.last_name }}","rightValue":"={{ $json.last_name }}"},{"id":"18a96c1f-f2a0-4a2a-b789-606763df4423","operator":{"type":"number","operation":"equals"},"leftValue":"={{ $('Listen for Telegram Events').item.json.body.message.chat.id }}","rightValue":"={{ $json.id }}"}]},"looseTypeValidation":"="},"typeVersion":2.2},{"id":"262c2621-5499-4481-ad94-97650b0f9714","name":"Sticky Note15","type":"n8n-nodes-base.stickyNote","position":[-2460,160],"parameters":{"color":6,"width":273,"height":269,"content":"# Start Here"},"typeVersion":1},{"id":"1cc31571-7d01-4cac-81a0-8cb6691ef1ed","name":"Error message","type":"n8n-nodes-base.telegram","position":[-1640,160],"webhookId":"b3b41cd7-40d9-47dc-817a-291733213c8b","parameters":{"text":"=Unable to process your message.","chatId":"={{ $json.body.message.chat.id }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"EDuT6lIMLHRxdqqN","name":"Telegram account"}},"typeVersion":1.2},{"id":"72b0fd9e-a82c-455b-a1d7-face4a9d55b4","name":"Baserow Retrieve Memories","type":"n8n-nodes-base.baserow","position":[-780,220],"parameters":{"tableId":639,"returnAll":true,"databaseId":122,"additionalOptions":{}},"credentials":{"baserowApi":{"id":"1YeHyTi4fmB007co","name":"Baserow account"}},"typeVersion":1},{"id":"40618bf6-657a-4b8a-818b-90b5e7aecbd5","name":"Baserow Retrieve Notes","type":"n8n-nodes-base.baserow","position":[-780,620],"parameters":{"tableId":640,"returnAll":true,"databaseId":122,"additionalOptions":{}},"credentials":{"baserowApi":{"id":"1YeHyTi4fmB007co","name":"Baserow account"}},"typeVersion":1},{"id":"87bfdbe7-bf2f-40d8-8fb5-c0c0015d8a10","name":"Window Memory (Easy Mode)","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[-140,640],"parameters":{"sessionKey":"={{ $('Listen for Telegram Events').item.json.body.message.from.id }}","sessionIdType":"customKey","contextWindowLength":50},"typeVersion":1.3},{"id":"02f650e9-3d8d-4622-9cd9-16154d4d27c5","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[300,820],"parameters":{"width":280,"height":520,"content":"## Baserow Set-up:\n- Create a new Workspace called \"Memories and Notes\"\n- Create a table within the new workspace called \"Memory Table\"\n- Within the \"Memory Table\" table, create two fields\n- First field is called \"Memory\" (select \"long text\" as the field type)\n- Second field is called \"Date Added\" (select 'US' date format, and check include time\n\n## Notes Setup:\n- For the notes table we can simply \"Duplicate\" the \"Memory Table\" table that we just created\n- Rename the table to \"Notes Table\" \n- Rename the first from \"Memory\" to \"Notes\"\n- **Make sure time and date are on and set correctly in \"Date Added\" field.**"},"typeVersion":1},{"id":"26efbccd-7605-4308-85d2-c91cdd4897ad","name":"Sticky Note16","type":"n8n-nodes-base.stickyNote","position":[580,840],"parameters":{"color":6,"width":720,"height":1180,"content":"## Baserow Memory Table Setup:\n![Baserow example 1](https://i.imgur.com/hXADtza.png)\n## Name first field \"Memory\" and set to \"Long Text\":\n![Baserow example 2](https://i.imgur.com/AJG0jO6.png)\n## Name second field \"Date Added\" and set to 'US' date format\n![Baserow example 2](https://i.imgur.com/z8AJWfB.png)\n"},"typeVersion":1},{"id":"d30c8a6a-4668-49f9-8555-0f827d8157c0","name":"Sticky Note17","type":"n8n-nodes-base.stickyNote","position":[1300,860],"parameters":{"color":5,"width":540,"height":1120,"content":"## Tool node Setup Example:\n![Baserow example 2](https://i.imgur.com/DQ6jolu.png)"},"typeVersion":1},{"id":"54dce9dd-f06c-4e61-9a96-b691fe76dfa3","name":"Sticky Note18","type":"n8n-nodes-base.stickyNote","position":[-2120,400],"parameters":{"width":150,"height":80,"content":"## *Setup validation"},"typeVersion":1},{"id":"9166bd3d-2f21-4f19-b787-ccf9be5b5acc","name":"Sticky Note19","type":"n8n-nodes-base.stickyNote","position":[-120,140],"parameters":{"width":200,"height":120,"content":"## *Setup Prompt\n"},"typeVersion":1}],"active":false,"settings":{"executionOrder":"v1"},"versionId":"755d754f-9577-41b2-ae5c-1f0918389fc6","connections":{"Merge":{"main":[[{"node":"Aggregate","type":"main","index":0}]]},"Merge1":{"main":[[{"node":"Edit Fields1","type":"main","index":0}]]},"caption":{"main":[[{"node":"Merge1","type":"main","index":0}]]},"Aggregate":{"main":[[{"node":"AI Tools Agent","type":"main","index":0}]]},"Get Image":{"main":[[{"node":"Extract from File to Base64","type":"main","index":0}]]},"Validation":{"main":[[{"node":"Check User & Chat ID","type":"main","index":0}]]},"Edit Fields":{"main":[[{"node":"Baserow Retrieve Memories","type":"main","index":0},{"node":"Baserow Retrieve Notes","type":"main","index":0}]]},"Save Memory":{"ai_tool":[[{"node":"AI Tools Agent","type":"ai_tool","index":0}]]},"gpt-4o-mini":{"ai_languageModel":[[{"node":"AI Tools Agent","type":"ai_languageModel","index":0}]]},"Edit Fields1":{"main":[[{"node":"Baserow Retrieve Memories","type":"main","index":0},{"node":"Baserow Retrieve Notes","type":"main","index":0}]]},"Analyze Image":{"main":[[{"node":"Merge1","type":"main","index":1}]]},"Image Schema1":{"main":[[{"node":"Get Image","type":"main","index":0},{"node":"caption","type":"main","index":0}]]},"AI Tools Agent":{"main":[[{"node":"Telegram Response","type":"main","index":0},{"node":"Chat Response","type":"main","index":0}]]},"Get Audio File":{"main":[[{"node":"Transcribe Recording","type":"main","index":0}]]},"Message Router":{"main":[[{"node":"Get Audio File","type":"main","index":0}],[{"node":"Edit Fields","type":"main","index":0}],[{"node":"Image Schema1","type":"main","index":0}],[{"node":"Error message","type":"main","index":0}]]},"Save Note Tool":{"ai_tool":[[{"node":"AI Tools Agent","type":"ai_tool","index":0}]]},"Check User & Chat ID":{"main":[[{"node":"Message Router","type":"main","index":0}],[{"node":"Error message","type":"main","index":0}]]},"Postgres Chat Memory":{"ai_memory":[[{"node":"AI Tools Agent","type":"ai_memory","index":0}]]},"Transcribe Recording":{"main":[[{"node":"Baserow Retrieve Memories","type":"main","index":0},{"node":"Baserow Retrieve Notes","type":"main","index":0}]]},"Convert to Image File":{"main":[[{"node":"Analyze Image","type":"main","index":0}]]},"Baserow Retrieve Notes":{"main":[[{"node":"Merge","type":"main","index":1}]]},"Baserow Retrieve Memories":{"main":[[{"node":"Merge","type":"main","index":0}]]},"Listen for Telegram Events":{"main":[[{"node":"Validation","type":"main","index":0}]]},"Extract from File to Base64":{"main":[[{"node":"Convert to Image File","type":"main","index":0}]]}}}


