# templates

name: AI-Powered Restaurant Order Chatbot with GPT-4o for POS Integration
author_name: Kumar Shivam
author_username: shivam840708
categories: []
created_at: 2025-05-08T15:20:19.166Z
updated_at: 2025-05-08T15:20:19.166Z
url: https://n8n.io/workflows/3942
scraped_at: 2025-06-19 22:49:00
description:
  This workflow automates the restaurant POS (Point of Sale) data management process, facilitating seamless order handling, customer tracking, inventory management, and sales reporting. It retrieves order details, processes payment information, updates inventory, and generates real-time sales reports, all integrated into a centralized system that improves restaurant operations.

  The workflow integrates various systems, including a POS terminal to gather order data, payment gateways to process transactions, inventory management tools to update stock, and reporting tools like Google Sheets or an internal database for generating sales and performance reports.

  Who Needs Restaurant POS Automation?
  This POS automation workflow is ideal for restaurant owners, managers, and staff looking to streamline their operations:

  Restaurant Owners – Automate order processing, track sales, and monitor inventory to ensure smooth operations.

  Managers – Access real-time sales data and performance reports to make informed decisions.

  Staff – Reduce manual work, focusing on providing better customer service while the system handles orders and payments.

  Inventory Teams – Automatically update inventory levels based on orders and ingredient usage.

  If you need a reliable and automated POS solution to manage restaurant orders, payments, inventory, and reporting, this workflow minimizes human error, boosts efficiency, and saves valuable time.

  Why Use This Workflow?

  End-to-End Automation – Automates everything from order input to inventory updates and sales reporting.

  Seamless Integration – Connects POS, payment systems, inventory management, and reporting tools for smooth data flow.(if needed)

  Real-Time Data – Provides up-to-the-minute reports on sales, stock levels, and order statuses.

  Scalable & Efficient – Supports multiple locations, multiple users, and high order volumes.

  Step-by-Step: How This Workflow Manages POS Data

  Collect Orders – Retrieves order details from the POS system, including customer information, ordered items, and payment details.

  Update Inventory – Decreases inventory levels based on sold items, ensuring stock counts are always accurate.

  Generate Reports – Compiles sales, revenue, and inventory data into real-time reports and stores them in Google Sheets or an internal database.

  Track Customer Data – Keeps a log of customer details and order history for better service and marketing insights.

  Customization: Tailor to Your Needs

  Multiple POS Systems – Adapt the workflow to work with different POS systems or terminals based on your restaurant setup.

  Custom Reporting – Modify the reporting format or include specific sales metrics (e.g., daily totals, best-selling items, employee performance).

  Inventory Management – Adjust inventory updates to include alerts when stock reaches critical levels or needs reordering.

  Integration with Accounting Software – Connect with platforms like QuickBooks for automated financial tracking.

  🔑 Prerequisites

  POS System Integration – Ensure the POS system can export order data in a compatible format.

  Payment Gateway API – Set up the necessary API keys for payment processing (e.g., Stripe, PayPal).

  Inventory Management Tools – Use inventory software or databases that can automatically update stock levels.

  Reporting Tools – Use Google Sheets or an internal database to store and generate sales and inventory reports.

  🚀 Installation & Setup

  Configure Credentials

  Set up API credentials for payment gateways and inventory management tools.

  Import Workflow

  Import the workflow into your automation platform (e.g., n8n, Zapier).

  Link POS system, payment gateway, and inventory management systems.

  Test & Run

  Process a test order to ensure that data flows correctly through each step.

  Verify that inventory updates and reports are generated as expected.

  ⚠ Important

  Data Privacy – Ensure compliance with data protection regulations (e.g., GDPR, PCI DSS) when handling customer payment and order data.

  System Downtime – Monitor system performance to ensure that the workflow runs without disruptions during peak hours.

  Summary
  This restaurant POS automation workflow integrates order management, payment processing, inventory updates, and real-time reporting, enabling efficient restaurant operations. Whether you are running a single location or a chain of restaurants, this solution streamlines daily tasks, reduces errors, and provides valuable insights, saving time and improving customer satisfaction. 🚀

nodes_used:
  ["n8n-nodes-base.googleSheets","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.informationExtractor"]

workflow_json:
  {"meta":{"instanceId":"d73282515b90623d4a8783919a2d772c706425d649e1512792f37ac51e07e4a8"},"nodes":[{"id":"62b3c7cb-1993-44f1-8b86-38a34ca1d029","name":"Information Extractor","type":"@n8n/n8n-nodes-langchain.informationExtractor","position":[-200,500],"parameters":{"text":"={{ $json.query }}","options":{},"schemaType":"fromJson","jsonSchemaExample":"{\n  \"name\": \"Information Extractor\",\n  \"type\": \"n8n-nodes-base.informationExtractor\",\n  \"parameters\": {\n    \"extract\": [\n      {\n        \"name\": \"items\",\n        \"pattern\": \"(latte|coffee|tea|cappuccino)\"\n      },\n      {\n        \"name\": \"quantity\",\n        \"pattern\": \"\\\\d+\"\n      },\n      {\n        \"name\": \"table\",\n        \"pattern\": \"table number (\\\\d+)\"\n      }\n    ]\n  }\n}\n"},"typeVersion":1},{"id":"75883f27-af58-4791-9e1a-a70b83e1cead","name":"OpenAI Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-180,740],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"OizdHUANhz9NIHyd","name":"OpenAi account"}},"typeVersion":1.2},{"id":"aeefdd4b-bf7d-4824-97d8-0afc356fb7d6","name":"If","type":"n8n-nodes-base.if","position":[120,540],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"8a5dda0c-a567-4305-83a3-68d6fb573dd3","operator":{"type":"array","operation":"empty","singleValue":true},"leftValue":"={{ $json.output.parameters.extract }}","rightValue":""}]}},"typeVersion":2.2},{"id":"9e3f8a1b-ccd8-4f4d-91cb-b99cc46f412f","name":"Google Sheets","type":"n8n-nodes-base.googleSheets","position":[840,420],"parameters":{"columns":{"value":{"Item":"={{ $json.item }}","Quantity":"={{ $json.quantity }}","Table No":"={{ $json.table }}","Timestamp":"={{ $now }}"},"schema":[{"id":"Timestamp","type":"string","display":true,"required":false,"displayName":"Timestamp","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Table No","type":"string","display":true,"required":false,"displayName":"Table No","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Item","type":"string","display":true,"required":false,"displayName":"Item","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Quantity","type":"string","display":true,"required":false,"displayName":"Quantity","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/16fXaxEcfnq_-oif9tp94-3uTeHSFWoSnuBPNTljuW-k/edit#gid=0","cachedResultName":"Order log"},"documentId":{"__rl":true,"mode":"url","value":"https://docs.google.com/spreadsheets/d/16fXaxEcfnq_-oif9tp94-3uTeHSFWoSnuBPNTljuW-k/edit?usp=sharing"}},"credentials":{"googleSheetsOAuth2Api":{"id":"0RSJGMBcFzxY9GkS","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"4cc1818f-1585-42e1-a111-7b55557aebcb","name":"Code","type":"n8n-nodes-base.code","position":[380,560],"parameters":{"language":"python","pythonCode":"# Input from n8n\ninput_data = items\n\n# Get the extracted list\nextract_data = input_data[0].get('json', {}).get('output', {}).get('parameters', {}).get('extract', [])\n\n# Prepare variables\norder_items = []\ntable_number = None\n\n# Separate entries by type\nitems_list = []\nquantities = []\n\n# Parse all entries\nfor entry in extract_data:\n    if entry['name'] == 'table number':\n        table_number = entry['pattern']\n    elif entry['name'] == 'item':\n        items_list.append(entry['pattern'])\n    elif entry['name'] == 'quantity':\n        quantities.append(int(entry['pattern']))\n\n# Pair items and quantities\nfor i in range(len(items_list)):\n    item_data = {\n        'item': items_list[i],\n        'quantity': quantities[i] if i < len(quantities) else None,\n        'table': table_number\n    }\n    order_items.append(item_data)\n\n# Set final output\noutput = [{'json': item} for item in order_items]\n\nreturn output"},"typeVersion":2},{"id":"a92d2745-148b-4e2a-b8f7-82d3993ff34f","name":"Loop Over Items","type":"n8n-nodes-base.splitInBatches","position":[620,500],"parameters":{"options":{}},"typeVersion":3},{"id":"aea89e6c-37a9-4859-adc8-b7e449701503","name":"Replace Me","type":"n8n-nodes-base.noOp","position":[800,660],"parameters":{},"typeVersion":1},{"id":"b31dba52-b27e-4267-be32-a7730b4d08a8","name":"No Operation, do nothing","type":"n8n-nodes-base.noOp","position":[440,400],"parameters":{},"typeVersion":1},{"id":"d7f9a381-6bc2-44d0-81ac-6e0fbe77d70a","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-260,220],"parameters":{"color":3,"width":340,"height":680,"content":"## JSON PARSER\n\n1.converts the textual data final order like\nitem name \nquantity \nand table name in a json.\n\n2.if the data doesn't include the above it returns null."},"typeVersion":1},{"id":"acc7a528-f767-4576-b08d-6fc386f57648","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[100,220],"parameters":{"color":2,"width":460,"height":680,"content":"## Refine/Split the jsons into multiple items\n\nIf the data from previous item is not null the custom code block splits the data into multiple json items in a list."},"typeVersion":1},{"id":"857a3102-f5e1-4db5-afb4-154544414701","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[580,220],"parameters":{"color":4,"width":440,"height":680,"content":"## Send each item as a record in Google sheet\n\n\n**Each item is looped over and produce a batch of 1 item and appended as row in sheet with timestamp.\n"},"typeVersion":1},{"id":"a1ff2b0f-0b48-4ea2-8121-4e2d72197ef7","name":"Triggered on Restaurant Chat workflow","type":"n8n-nodes-base.executeWorkflowTrigger","position":[-440,500],"parameters":{"inputSource":"passthrough"},"typeVersion":1.1},{"id":"8689b773-a1c4-4de4-a66e-fab8c9eb6244","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-140,-280],"webhookId":"d931c4a7-02f5-4359-918f-7ad3fae7b144","parameters":{"public":true,"options":{}},"typeVersion":1.1},{"id":"de310ce2-3868-4a0f-aa9b-38253e75dbda","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[100,-260],"parameters":{"options":{"systemMessage":"\n\nYou are a polite and efficient restaurant assistant.\n\nYour job is to take customer orders, verify the order details, correct any mistakes, and confirm the order.\n\nFollow these steps:\n\nGreeting and Asking for the Order\n\nIf the customer greets you (e.g., \"Hello\", \"Hi\", \"Good evening\"), respond with:\n\n\"Hello! How can I assist you today? What would you like to order?\"\n\nOrder Parsing and Understanding\n\nAccept orders in flexible formats, such as:\n\n\"1 latte, 2 coffee, table number 5\"\n\n\"latte 2, pepsi 1, table 3\"\n\n\"1 cappucino\"\n\n\"1 tea table no 4\"\n\nYour goal is to extract the following:\n\nItem names (e.g., latte, coffee, chocolate, tea, pepsi)\n\nQuantities (must be numeric)\n\nTable number (must be numeric)\n\nVerify and Handle Missing or Incorrect Information\n\nFor each item in the order:\n\nIf the item name is missing, respond:\n\"Sorry, the item name is missing. What would you like to order?\"\n\nIf the quantity is missing, respond:\n\"How many [item] would you like?\"\n\nIf the table number is missing, respond:\n\"Could you please provide a table number?\"\n\nIf there are spelling mistakes in the item name, suggest corrections. Example:\n\"Did you mean chocolate instead of chocolat? Please confirm.\"\n\nUse fuzzy matching to detect common variations and typos.\n\nFinal Confirmation\n\nOnce all necessary details are collected, present an order summary like this:\n\nHere’s your order summary:\n\n1 latte\n\n2 coffee\n\nTable number: 5\nShall I confirm this order?\n\nOn Confirmation: Use the Tool\n\nWhen the user confirms, use the tool ConfirmOrder to send the final confirmation message as plain text in this format:\n\nThank you for confirming! Your order will be prepared shortly. Enjoy your time with us!\n\nOrder details are following:\nitem quantity\nlatte 1\ncoffee 2\n\nAdded to table number 5\n\nEnsure numeric values (quantities and table numbers) are correctly extracted, even if they appear at the start or end. Always confirm with the user if there is any uncertainty.\n\n\n\n\n\n\n\n\n"}},"typeVersion":1.9},{"id":"9dda45ee-0a92-448c-8a7e-8daa99282cda","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-20,20],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{"responseFormat":"text"}},"credentials":{"openAiApi":{"id":"OizdHUANhz9NIHyd","name":"OpenAi account"}},"typeVersion":1.2},{"id":"0c0189d5-8fb4-4679-b2e2-221a3e2a4c88","name":"Call n8n Workflow Tool","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[360,20],"parameters":{"workflowId":{"__rl":true,"mode":"list","value":"wgaJ0eJQtYA8oKSC","cachedResultName":"Restaurant POS workflow"},"description":"This tool sends the text output generated by the AI Agent node to another n8n workflow for additional handling or automation.","workflowInputs":{"value":{},"schema":[],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false}},"notesInFlow":false,"typeVersion":2.2},{"id":"9292db7f-6ffc-486e-b31a-bcbd6ef7ab98","name":"Last 5 conversations Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[140,40],"parameters":{},"typeVersion":1.3},{"id":"2782d5b6-d33b-4c89-ac79-90bf380f0828","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[60,-380],"parameters":{"width":340,"height":300,"content":"## Restaurant Order Chat bot\n** It chats with the user and refines the order for the pos system in another workflow."},"typeVersion":1},{"id":"7c298718-e9e3-40d3-a612-94c578bd3100","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[500,-20],"parameters":{"color":5,"content":"## Call the subworkflow\nit passes the data to the subworkflow for further process\n"},"typeVersion":1}],"pinData":{},"connections":{"If":{"main":[[{"node":"No Operation, do nothing","type":"main","index":0}],[{"node":"Code","type":"main","index":0}]]},"Code":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"AI Agent":{"main":[[]]},"Replace Me":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Loop Over Items":{"main":[[{"node":"Google Sheets","type":"main","index":0}],[{"node":"Replace Me","type":"main","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"OpenAI Chat Model1":{"ai_languageModel":[[{"node":"Information Extractor","type":"ai_languageModel","index":0}]]},"Information Extractor":{"main":[[{"node":"If","type":"main","index":0}]]},"Call n8n Workflow Tool":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"When chat message received":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Last 5 conversations Memory":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"Triggered on Restaurant Chat workflow":{"main":[[{"node":"Information Extractor","type":"main","index":0}]]}}}


name: AI Personal Assistant with GPT-4o, RAG & Voice for WhatsApp using Supabase
author_name: Amanda Benks
author_username: amanda
categories: []
created_at: 2025-05-08T20:10:41.254Z
updated_at: 2025-05-08T20:10:41.254Z
url: https://n8n.io/workflows/3947
scraped_at: 2025-06-19 22:50:16
description:
  🧠 Intelligent AI Assistant with RAG & Voice for WhatsApp – Built with GPT-4o & Supabase

  📌 About this workflow and its creator

  Hi! I’m Amanda, a creator of intelligent automations using n8n and Make. I’ve been building AI-powered workflows for over 2 years, always focused on usability and innovation. This one here is very special to me – a truly advanced AI assistant that reads, listens, interprets and responds like a real human 🤖✨

  This ready-to-use workflow acts as a powerful AI personal assistant capable of understanding messages via voice, text, documents, or even images. It supports full multi-channel operation (WhatsApp via Evolution API, Instagram, Facebook, and more), and includes advanced RAG capabilities using Supabase + GPT-4o. It’s designed to be highly extensible, with memory, prompt update tools, and knowledge base management.

  ⚙️ What this workflow does

  💬 Understands user input via text, document, audio or image (voice, OCR, PDF)
  🎤 Transcribes and interprets voice messages using OpenAI Whisper
  🧠 Understands prompts and user commands using GPT-4o via LangChain agent
  🗂️ Searches knowledge base using RAG + Supabase vector DB
  📄 Accepts documents and automatically indexes them for future questions
  🧾 Summarizes documents and stores metadata in Supabase
  🗃️ Offers memory support (PostgreSQL chat memory per user session)
  📧 Sends replies through WhatsApp (Evolution API), Instagram, Facebook, etc.
  📅 Manages schedules (via tool integration with Google Calendar)
  📬 Sends and searches emails (with support tools)
  🛠 Modular and expandable structure (tools for saving knowledge, deleting, updating prompt)

  🔧 Setup Instructions

  n8n Hosting  
     This workflow requires n8n self-hosted (or n8n Cloud with custom credentials + community nodes enabled).

  Create required databases  
     Use the provided SQL queries inside the setar_supabase_tabelas_vectoriais, criar_cerebro, and criar_rag_controle nodes to initialize:
     documents table for RAG
     cerebro table for prompt
     memoria_chat for session memory
     rag_controle for summaries and indexing

  Credentials needed
     OpenAI API (for chat, embeddings and Whisper transcription)
     Redis (for managing message buffer)
     Supabase (for vector store + metadata)
     Postgres (for memory and prompts)
     Evolution API (or other messaging platforms)

  Webhook
     Set the webhook path to receive messages from your Evolution or WhatsApp API provider.

  Configure ‘Set’ node
     In the config node, adjust:
     adminNumero: your personal WhatsApp or admin number
     evolutionApiKey: your private API key
     utilizacaoApenasViaAdmin: toggle if this should only respond to admin numbers

  Tool connections
     Ensure the supporting workflows are also imported and connected for:
     Emails
     Knowledge management
     Calendar events

  📎 Notes

  This workflow uses LangChain agents, OpenAI GPT-4o, Supabase, Redis, and PostgreSQL.
  It includes multiple “sticky notes” inside the workflow with explanations.
  Ideal for businesses, consultants, and developers looking to offer an intelligent and extendable AI chatbot experience.

  🛍 Want to use this on your system?
  ❤️ Buy workflows: https://iloveflows.com  
  ☁️ Use n8n Cloud with my partner link: https://n8n.partnerlinks.io/amanda

nodes_used:
  ["n8n-nodes-base.postgres","n8n-nodes-base.redis","n8n-nodes-base.supabase","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.embeddingsOpenAi","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","@n8n/n8n-nodes-langchain.toolWorkflow","@n8n/n8n-nodes-langchain.vectorStoreSupabase","@n8n/n8n-nodes-langchain.documentDefaultDataLoader","@n8n/n8n-nodes-langchain.openAi","@n8n/n8n-nodes-langchain.memoryPostgresChat","@n8n/n8n-nodes-langchain.toolVectorStore"]

workflow_json:
  {"id":"oztomvXcbguCwH2Q","meta":{"instanceId":"b79da95dcb1b69eebc3470f6fd833d7e53e389c229c716386bdb8e7c291ad2b9"},"name":"🤖 AI Personal Assistant with GPT-4o, Memory & Scheduling for WhatsApp","tags":[{"id":"mhx5MJAkz32rJgeQ","name":"iloveflows.com","createdAt":"2025-05-09T14:28:31.509Z","updatedAt":"2025-05-09T14:28:31.509Z"}],"nodes":[{"id":"d105b0e6-5d38-4389-a348-9f4edbd98043","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[2780,1640],"parameters":{},"typeVersion":1},{"id":"cd236a55-34ea-48b4-853a-5242e42888e2","name":"Convert to File","type":"n8n-nodes-base.convertToFile","position":[0,900],"parameters":{},"typeVersion":1.1,"alwaysOutputData":true},{"id":"68bb9541-283f-4639-b57b-601473d170ac","name":"edit1","type":"n8n-nodes-base.set","position":[540,900],"parameters":{},"typeVersion":3.4,"alwaysOutputData":true},{"id":"8eaa4a55-879f-42bc-86b0-36303804258c","name":"edit2","type":"n8n-nodes-base.set","position":[540,1340],"parameters":{},"typeVersion":3.4},{"id":"3fa2fe0e-43e4-449d-9ab8-ce83f5f0ff77","name":"auth","type":"n8n-nodes-base.if","position":[-560,1160],"parameters":{},"typeVersion":2.2},{"id":"95d88cc9-b66f-45e7-bfb7-3142382c3ed7","name":"Message Delay","type":"n8n-nodes-base.wait","position":[1180,1120],"webhookId":"c0def2c7-50d3-47c5-8a1e-4164f3625242","parameters":{},"typeVersion":1.1},{"id":"c70fc751-b54c-4bb6-a712-a9ec52ed607b","name":"Puxar as Mensagens","type":"n8n-nodes-base.redis","position":[1360,1120],"parameters":{},"typeVersion":1},{"id":"1d798878-7ae1-4ad1-aa1f-67effe3f1aeb","name":"If1","type":"n8n-nodes-base.if","position":[820,1340],"parameters":{},"typeVersion":2},{"id":"46d45920-68a2-410d-97da-2a2978fdabc9","name":"Database","type":"n8n-nodes-base.redis","position":[1360,1320],"parameters":{},"typeVersion":1},{"id":"45bb766b-ead9-4f69-aae1-8cf91de14f44","name":"Lista Mensagens1","type":"n8n-nodes-base.redis","position":[1000,1120],"parameters":{},"typeVersion":1},{"id":"f2ebd4bb-5a56-4048-8768-054ffac6783d","name":"Edit Fields2","type":"n8n-nodes-base.set","position":[1100,1320],"parameters":{},"typeVersion":3.4},{"id":"b5a4820c-0251-4cc2-a318-9252db2873f8","name":"Important Notes","type":"n8n-nodes-base.stickyNote","position":[780,980],"parameters":{"content":""},"typeVersion":1},{"id":"e244cead-b967-4311-940d-2ebc27b78d0b","name":"OpenAI","type":"@n8n/n8n-nodes-langchain.openAi","position":[260,900],"parameters":{},"typeVersion":1.6},{"id":"d6da694b-52f0-492e-8a67-8fcb633d17db","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[-1160,680],"parameters":{"content":""},"typeVersion":1},{"id":"680eaca5-6ea9-4d27-b329-9a45cd6979f9","name":"setar_supabase_tabelas_vectoriais","type":"n8n-nodes-base.postgres","position":[-1080,780],"parameters":{},"typeVersion":2.5},{"id":"2f705e74-bd8a-4737-b4ed-36ae11b43388","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[460,420],"parameters":{},"typeVersion":1},{"id":"4a3927c2-6f9e-4234-9e06-7fcf4c4e8b3b","name":"Embeddings OpenAI1","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[320,400],"parameters":{},"typeVersion":1},{"id":"ba9aded7-9cbc-4fb6-a4eb-47f7c77e84b5","name":"Recursive Character Text Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","position":[500,540],"parameters":{},"typeVersion":1},{"id":"6ee2f34b-e0d8-431b-9bf6-689b01df7068","name":"arquivo_id","type":"n8n-nodes-base.set","position":[0,700],"parameters":{},"typeVersion":3.4},{"id":"c97e06e2-0179-431a-8d5b-87d96b7da4b9","name":"deletar_arquivos_antigos","type":"n8n-nodes-base.supabase","position":[0,20],"parameters":{},"typeVersion":1,"alwaysOutputData":true},{"id":"a1bc0aee-6e48-4ff2-8df0-d3773fcaba50","name":"extrair_pdf","type":"n8n-nodes-base.extractFromFile","position":[0,240],"parameters":{},"typeVersion":1,"alwaysOutputData":true},{"id":"982be2d5-c606-4dc7-afc3-43764bb84761","name":"exportar_texto","type":"n8n-nodes-base.set","position":[160,240],"parameters":{},"typeVersion":3.4},{"id":"dbab42c2-c699-4353-b4d4-a89e2209b673","name":"Embeddings OpenAI","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[3160,1940],"parameters":{},"typeVersion":1},{"id":"7eaad18d-1a77-4109-adef-3d424e7b0ea7","name":"OpenAI Chat Model2","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[3420,1820],"parameters":{},"typeVersion":1},{"id":"6d63b8a6-6713-46b7-9893-d2cefd7e86bb","name":"supabase_vectorstore","type":"@n8n/n8n-nodes-langchain.vectorStoreSupabase","position":[360,240],"parameters":{},"typeVersion":1},{"id":"e9ccd7f3-ca94-4c62-aa4b-63127d1f13c4","name":"agendamentos","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[3740,1760],"parameters":{},"typeVersion":1.2},{"id":"b8ab0a49-5584-4d3b-8b16-d66f653135a3","name":"criar_cerebro","type":"n8n-nodes-base.postgres","position":[-1080,460],"parameters":{},"typeVersion":2.5},{"id":"ca88a0b1-34ee-4bbd-8a18-3eea1afbd311","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-1160,380],"parameters":{"content":""},"typeVersion":1},{"id":"8f22b428-7cc3-4608-810d-ac66bccbc6ec","name":"puxar_prompt","type":"n8n-nodes-base.postgres","position":[1920,1320],"parameters":{},"typeVersion":2.5},{"id":"0fda91cb-760b-4f90-b944-71d359694ef3","name":"Postgres Chat Memory","type":"@n8n/n8n-nodes-langchain.memoryPostgresChat","position":[3160,1540],"parameters":{},"typeVersion":1.1},{"id":"4d78bc5a-023b-4f05-9553-98320b2e86e9","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-860,680],"parameters":{"content":""},"typeVersion":1},{"id":"193f806c-9f1c-4d74-aa64-bfe3db3b47e3","name":"Deletar_todas_as_mensagens1","type":"n8n-nodes-base.postgres","position":[-780,760],"parameters":{},"typeVersion":2.5},{"id":"5adf5cdd-e820-44dd-bc2a-da9d8b18602b","name":"convert_to_file","type":"n8n-nodes-base.convertToFile","position":[500,20],"parameters":{},"typeVersion":1.1},{"id":"2860bd45-7c8d-4c28-bcd5-78d56eeb6e6e","name":"base64","type":"n8n-nodes-base.set","position":[320,20],"parameters":{},"typeVersion":3.4},{"id":"974fbf99-c727-47f2-bc54-b6c56421c08e","name":"tipo_arquivo","type":"n8n-nodes-base.switch","position":[680,20],"parameters":{},"typeVersion":3.2},{"id":"d5ba78ce-c3ef-4ecb-bec2-6728cff76a86","name":"OpenAI Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1180,420],"parameters":{},"typeVersion":1},{"id":"17bd231d-b48b-42dd-ace0-1d4f0d5aae01","name":"Merge Database Data1","type":"n8n-nodes-base.aggregate","position":[720,240],"parameters":{},"typeVersion":1},{"id":"06eaf689-221a-4074-855f-a04b0064b039","name":"resumo","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[1100,240],"parameters":{},"typeVersion":1.4},{"id":"e368d5f5-6cc7-4d05-8a35-72312e72cb55","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[-1160,80],"parameters":{"content":""},"typeVersion":1},{"id":"b9672003-1751-452c-95fb-931fd706bff4","name":"criar_rag_controle","type":"n8n-nodes-base.postgres","position":[-1080,160],"parameters":{},"typeVersion":2.5},{"id":"7c8b7a9e-2ffa-45b5-beea-52f3b49fb94d","name":"atualizar_lista_de_arquivos","type":"n8n-nodes-base.postgres","position":[1420,240],"parameters":{},"typeVersion":2.5},{"id":"5deaf046-639a-4e0c-8ae0-c1605fc724fa","name":"rag_resumos","type":"n8n-nodes-base.postgres","position":[1840,1520],"parameters":{},"typeVersion":2.5,"alwaysOutputData":true},{"id":"0d7ccb57-c1e3-4ba5-8457-1bdb14a95039","name":"Merge Database Data2","type":"n8n-nodes-base.aggregate","position":[2000,1520],"parameters":{},"typeVersion":1,"alwaysOutputData":true},{"id":"8e565942-0eae-4e95-9081-76b64b9debf2","name":"Supabase Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStoreSupabase","position":[3120,1800],"parameters":{},"typeVersion":1},{"id":"ab141574-d985-44ad-99a5-24ae3f1aab74","name":"excluir_rag_arquivo","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[3740,1600],"parameters":{},"typeVersion":1.2},{"id":"10d1de05-dfef-4bba-95d2-00a4123a13ec","name":"emails","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[3940,1760],"parameters":{},"typeVersion":1.2},{"id":"ba175864-3c55-40d2-aa94-4ffa1a633e3a","name":"adicionar_conhecimento","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[3740,1420],"parameters":{},"typeVersion":1.2},{"id":"0baac00a-69b9-40d2-82fa-5d14f6abe055","name":"buscar_conhecimento","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[3940,1420],"parameters":{},"typeVersion":1.2},{"id":"188913c1-2bda-4e38-a3ba-8a3a574a8937","name":"Convert to File1","type":"n8n-nodes-base.convertToFile","position":[180,1120],"parameters":{},"typeVersion":1.1},{"id":"788d471d-9069-4453-b0a2-1f7d02b3bfa1","name":"base","type":"n8n-nodes-base.set","position":[0,1120],"parameters":{},"typeVersion":3.4},{"id":"ed432b2e-591a-41aa-80bc-909d5b1f76a8","name":"Edit Fields","type":"n8n-nodes-base.set","position":[540,1120],"parameters":{},"typeVersion":3.4},{"id":"43cca877-16b3-41bd-b05b-b3e1c152bfd7","name":"mensagem_tipo","type":"n8n-nodes-base.switch","position":[-300,1120],"parameters":{},"typeVersion":3.2,"alwaysOutputData":false},{"id":"89eda5b4-6565-41dc-a281-39a684a30103","name":"OpenAI1","type":"@n8n/n8n-nodes-langchain.openAi","position":[360,1120],"parameters":{},"typeVersion":1.6},{"id":"63c46d57-4c30-4471-9afe-e66c37852a10","name":"Merge","type":"n8n-nodes-base.merge","position":[2200,1340],"parameters":{},"typeVersion":3},{"id":"77360555-fc36-45ff-ae57-81c27078f7ca","name":"Switch","type":"n8n-nodes-base.switch","position":[2760,1340],"parameters":{},"typeVersion":3.2},{"id":"aebffc93-4190-4490-b5e9-2b2e9a97c2fb","name":"atualizar_prompt","type":"n8n-nodes-base.executeWorkflow","position":[3180,1080],"parameters":{},"typeVersion":1.1},{"id":"53a6befd-cea0-47a4-a3b5-dca6b033442c","name":"tratamento","type":"n8n-nodes-base.set","position":[3000,1080],"parameters":{},"typeVersion":3.4},{"id":"5e22a93e-0d5b-478c-be17-06142cf2ccaa","name":"Webhook","type":"n8n-nodes-base.webhook","position":[-1140,1160],"webhookId":"81dd8066-f3ed-462b-a538-3bad57450e37","parameters":{},"typeVersion":2},{"id":"b1667935-b34f-47ad-a1b1-887854b55d15","name":"recepcionista","type":"@n8n/n8n-nodes-langchain.agent","onError":"continueRegularOutput","maxTries":3,"position":[3100,1360],"parameters":{},"retryOnFail":true,"typeVersion":1.6},{"id":"3ec8d76e-d19d-492e-8009-aeca5e71fc3d","name":"classificador_de_intencao","type":"@n8n/n8n-nodes-langchain.agent","position":[2440,1340],"parameters":{},"typeVersion":1.7},{"id":"a48d9f14-b6fe-49cf-9bdd-4daf1c041088","name":"Merge Database Data3","type":"n8n-nodes-base.aggregate","position":[160,20],"parameters":{},"typeVersion":1},{"id":"94e34810-6b0a-49a8-a2b3-70b28088de7f","name":"excluir_conhecimento","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[3940,1600],"parameters":{},"typeVersion":1.3},{"id":"def3ddbe-8317-4240-9a93-4b7bfaf920e6","name":"config","type":"n8n-nodes-base.set","position":[-820,1160],"parameters":{},"typeVersion":3.4},{"id":"8a2f094f-eaa8-4152-9fb3-4c45a93402b8","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-920,1060],"parameters":{"content":""},"typeVersion":1},{"id":"3a2ed709-9091-479c-9f7f-e6d82e8566f5","name":"mensagem_cliente","type":"n8n-nodes-base.set","position":[1640,1320],"parameters":{},"typeVersion":3.4},{"id":"7e662537-681f-497f-aad1-4827db08e4bc","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-60,-80],"parameters":{"content":""},"typeVersion":1},{"id":"1dc6da1b-f750-4033-97b3-eb8c7652bcd1","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1600,1200],"parameters":{"content":""},"typeVersion":1},{"id":"b9e4d7a5-0fdf-465b-acf8-f3b160502f38","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[920,140],"parameters":{"content":""},"typeVersion":1},{"id":"d7d56279-4734-4b53-a05e-399dd4874b20","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[3620,1280],"parameters":{"content":""},"typeVersion":1},{"id":"0ce9550d-7880-4aa6-a538-fa8657186980","name":"mensagem_cliente_inicial","type":"n8n-nodes-base.set","position":[820,1120],"parameters":{},"typeVersion":3.4},{"id":"ae823123-3b4c-4ae7-b47f-70933e1fdfd3","name":"deletar_arquivo","type":"n8n-nodes-base.postgres","position":[920,240],"parameters":{},"typeVersion":2.5,"alwaysOutputData":true},{"id":"01cc8857-474a-4649-a2a4-35041b45b7dd","name":"Postgres Chat Memory1","type":"@n8n/n8n-nodes-langchain.memoryPostgresChat","position":[2520,1540],"parameters":{},"typeVersion":1.3},{"id":"88844d8e-2d75-4b8e-a86b-1b569d3dc98e","name":"deletar_conhecimento","type":"n8n-nodes-base.postgres","position":[-780,460],"parameters":{},"typeVersion":2.5},{"id":"754dc315-dd63-4f64-b3e3-3d7669246f02","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[-860,380],"parameters":{"content":""},"typeVersion":1},{"id":"8c89dc7b-6abe-4a9e-b0e9-f491c716181d","name":"RAG","type":"@n8n/n8n-nodes-langchain.toolVectorStore","position":[3260,1660],"parameters":{},"typeVersion":1},{"id":"27542401-fc46-415f-99c6-c116d485a50b","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-1180,-140],"parameters":{"content":""},"typeVersion":1}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"c8521f52-c7a6-4674-b2f8-9bc21b924506","connections":{"If1":{"main":[[{"node":"Edit Fields2","type":"main","index":0}]]},"RAG":{"ai_tool":[[{"node":"recepcionista","type":"ai_tool","index":0}]]},"auth":{"main":[[{"node":"mensagem_tipo","type":"main","index":0}]]},"base":{"main":[[{"node":"Convert to File1","type":"main","index":0}]]},"Merge":{"main":[[{"node":"classificador_de_intencao","type":"main","index":0}]]},"edit1":{"main":[[{"node":"mensagem_cliente_inicial","type":"main","index":0}]]},"edit2":{"main":[[{"node":"mensagem_cliente_inicial","type":"main","index":0}]]},"OpenAI":{"main":[[{"node":"edit1","type":"main","index":0}]]},"Switch":{"main":[[{"node":"tratamento","type":"main","index":0}],[{"node":"recepcionista","type":"main","index":0}]]},"base64":{"main":[[{"node":"convert_to_file","type":"main","index":0}]]},"config":{"main":[[{"node":"auth","type":"main","index":0}]]},"emails":{"ai_tool":[[{"node":"recepcionista","type":"ai_tool","index":0}]]},"resumo":{"main":[[{"node":"atualizar_lista_de_arquivos","type":"main","index":0}]]},"OpenAI1":{"main":[[{"node":"Edit Fields","type":"main","index":0}]]},"Webhook":{"main":[[{"node":"config","type":"main","index":0}]]},"arquivo_id":{"main":[[{"node":"deletar_arquivos_antigos","type":"main","index":0}]]},"tratamento":{"main":[[{"node":"atualizar_prompt","type":"main","index":0}]]},"Edit Fields":{"main":[[{"node":"mensagem_cliente_inicial","type":"main","index":0}]]},"extrair_pdf":{"main":[[{"node":"exportar_texto","type":"main","index":0}]]},"agendamentos":{"ai_tool":[[{"node":"recepcionista","type":"ai_tool","index":0}]]},"puxar_prompt":{"main":[[{"node":"Merge","type":"main","index":0}]]},"tipo_arquivo":{"main":[[{"node":"extrair_pdf","type":"main","index":0}]]},"mensagem_tipo":{"main":[[{"node":"arquivo_id","type":"main","index":0}],[{"node":"Convert to File","type":"main","index":0}],[{"node":"base","type":"main","index":0}],[{"node":"edit2","type":"main","index":0}]]},"exportar_texto":{"main":[[{"node":"supabase_vectorstore","type":"main","index":0}]]},"Convert to File":{"main":[[{"node":"OpenAI","type":"main","index":0}]]},"convert_to_file":{"main":[[{"node":"tipo_arquivo","type":"main","index":0}]]},"deletar_arquivo":{"main":[[{"node":"resumo","type":"main","index":0}]]},"Convert to File1":{"main":[[{"node":"OpenAI1","type":"main","index":0}]]},"mensagem_cliente":{"main":[[{"node":"puxar_prompt","type":"main","index":0},{"node":"rag_resumos","type":"main","index":0}]]},"Embeddings OpenAI":{"ai_embedding":[[{"node":"Supabase Vector Store","type":"ai_embedding","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"recepcionista","type":"ai_languageModel","index":0},{"node":"classificador_de_intencao","type":"ai_languageModel","index":0}]]},"Embeddings OpenAI1":{"ai_embedding":[[{"node":"supabase_vectorstore","type":"ai_embedding","index":0}]]},"OpenAI Chat Model1":{"ai_languageModel":[[{"node":"resumo","type":"ai_languageModel","index":0}]]},"OpenAI Chat Model2":{"ai_languageModel":[[{"node":"RAG","type":"ai_languageModel","index":0}]]},"Puxar as Mensagens":{"main":[[{"node":"If1","type":"main","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"supabase_vectorstore","type":"ai_document","index":0}]]},"buscar_conhecimento":{"ai_tool":[[{"node":"recepcionista","type":"ai_tool","index":0}]]},"excluir_rag_arquivo":{"ai_tool":[[{"node":"recepcionista","type":"ai_tool","index":0}]]},"Merge Database Data2":{"main":[[{"node":"Merge","type":"main","index":1}]]},"Postgres Chat Memory":{"ai_memory":[[{"node":"recepcionista","type":"ai_memory","index":0}]]},"excluir_conhecimento":{"ai_tool":[[{"node":"recepcionista","type":"ai_tool","index":0}]]},"Postgres Chat Memory1":{"ai_memory":[[{"node":"classificador_de_intencao","type":"ai_memory","index":0}]]},"Supabase Vector Store":{"ai_vectorStore":[[{"node":"RAG","type":"ai_vectorStore","index":0}]]},"adicionar_conhecimento":{"ai_tool":[[{"node":"recepcionista","type":"ai_tool","index":0}]]},"mensagem_cliente_inicial":{"main":[[{"node":"Lista Mensagens1","type":"main","index":0}]]},"classificador_de_intencao":{"main":[[{"node":"Switch","type":"main","index":0}]]},"Recursive Character Text Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader","type":"ai_textSplitter","index":0}]]}}}


name: Generate Logos and Images with Consistent Visual Styles using Imagen 3.0
author_name: Jimleuk
author_username: jimleuk
nodes_used: ["n8n-nodes-base.httpRequest","n8n-nodes-base.gmail","n8n-nodes-base.html"]
categories: []
created_at: 2025-05-09T08:58:19.404Z
updated_at: 2025-05-09T08:58:19.404Z
url: https://n8n.io/workflows/3954
scraped_at: 2025-06-19 22:48:52
description:
  This n8n template allows you to use AI to generate logos or images which mimic visual styles of other logos or images. The model used to generate the images is Google's Imagen 3.0.

  With this template, users will be able to automate design and marketing tasks such as creating variants of existing designs, remixing existing assets to validate different styles and explore a range of designs which would have been otherwise too expensive and time-consming previously.

  How it works
  A form trigger is used to capture the source image to reference styles from and a prompt for the target image to generate.
  The source image is passed to Gemini 2.0 to be analysed and its visual style and tone extracted as a detailed description.
  This visual style description is then combined with the user's initial target image prompt. This final prompt is given to Imagen 3.0 to generate the images.
  A quick webpage is put together with the generated images to present back to the user.
  If the user provided an email address, a copy of this HTML page will be sent.

  How to use
  Ensure the workflow is live to share the form publicly.
  The source image must be accessible to your n8n instance - either a public image of the internet or within your network.
  For best results, select a source image which has strong visual identity as these will allow the LLM to better describe it.
  For your prompt, refer to the imagen prompt guide found here: https://ai.google.dev/gemini-api/docs/image-generation#imagen-prompt-guide

  Requirements
  Gemini for LLM and Imagen model.
  Cloudinary for image CDN.
  Gmail for email sending.

  Customising this workflow
  Feel free to swap any of these out for tools and services you prefer.
  Want to fully automate? Switch the form trigger for a webhook trigger!

workflow_json:
  {"meta":{"instanceId":"408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9","templateCredsSetupCompleted":true},"nodes":[{"id":"ed993205-977a-43cd-8d0b-4faef216d766","name":"Split Out","type":"n8n-nodes-base.splitOut","position":[360,-120],"parameters":{"options":{},"fieldToSplitOut":"predictions"},"typeVersion":1},{"id":"67f2bb16-ee38-4bc8-9cc7-50a44614cc3b","name":"Imagen 3.0","type":"n8n-nodes-base.httpRequest","position":[140,-120],"parameters":{"url":"https://generativelanguage.googleapis.com/v1beta/models/imagen-3.0-generate-002:predict","method":"POST","options":{},"jsonBody":"={{\n{\n  \"instances\": [\n    {\n      \"prompt\": [\n        $json.candidates[0].content.parts[0].text,\n       `Generate the following image: ${$('Variables').first().json.targetPrompt}`\n      ].join(' ')\n    }\n  ],\n  \"parameters\": {\n    \"sampleCount\": $('Variables').first().json.numberSamples.toNumber()\n  }\n}\n}}","sendBody":true,"specifyBody":"json","authentication":"predefinedCredentialType","nodeCredentialType":"googlePalmApi"},"credentials":{"googlePalmApi":{"id":"dSxo6ns5wn658r8N","name":"Google Gemini(PaLM) Api account"}},"typeVersion":4.2},{"id":"b1730c97-8c5c-48a5-90cf-7940f6c9e2d0","name":"Variables","type":"n8n-nodes-base.set","position":[-940,-120],"parameters":{"options":{},"assignments":{"assignments":[{"id":"7616f991-76d0-4dd0-9385-f08ed14e8dfa","name":"sourceStyleUrl","type":"string","value":"={{ $json.SourceImage }}"},{"id":"126cb06e-4d69-4163-ba76-c694103bf5bb","name":"targetPrompt","type":"string","value":"={{ $json.TargetPrompt }}"},{"id":"055d247b-586d-4bb8-a319-262c241df48c","name":"numberSamples","type":"string","value":"={{\n(function(numSamples) {\n  if (!numSamples) return 1;\n  if (numSamples < 0) return 1;\n  if (numSamples > 4) return 4;\n  return numSamples;\n}($json['Number of Images']))\n}}"},{"id":"77a27e0e-24f4-4358-8cdc-84552be6c0b5","name":"email","type":"string","value":"={{ $json['Your Email (Optional)'] }}"}]}},"typeVersion":3.4},{"id":"5c26062c-74cf-4140-8dcb-8688c8daec67","name":"Download Image","type":"n8n-nodes-base.httpRequest","position":[-620,-120],"parameters":{"url":"={{ $json.sourceStyleUrl }}","options":{}},"typeVersion":4.2},{"id":"20744adb-cdf5-4558-b6e6-4206d7c1f356","name":"On form submission","type":"n8n-nodes-base.formTrigger","position":[-1400,-120],"webhookId":"51f74db1-ffb4-491f-83b0-a44a7124be12","parameters":{"options":{"path":"style-copy-with-imagen3","ignoreBots":true,"buttonLabel":"Generate!","appendAttribution":true},"formTitle":"Style Copy with Imagen 3.0","formFields":{"values":[{"fieldLabel":"SourceImage","placeholder":"The image URL to copy the style from","requiredField":true},{"fieldLabel":"TargetPrompt","placeholder":"The new image to generate","requiredField":true},{"fieldType":"number","fieldLabel":"Number of Images","placeholder":"Default 1. Max. 4 images"},{"fieldType":"email","fieldLabel":"Your Email (Optional)","placeholder":"The results will be sent to this email"}]},"responseMode":"lastNode","formDescription":"Use this form to generate an image using another image as a style reference."},"typeVersion":2.2},{"id":"917db247-1be3-4814-a96d-145957aa5db3","name":"Form Validation","type":"n8n-nodes-base.if","position":[-1180,-120],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"1b440b81-06c9-4133-bfd2-8ec07c7c3734","operator":{"type":"boolean","operation":"true","singleValue":true},"leftValue":"={{ $json.SourceImage.isUrl() }}","rightValue":""}]}},"typeVersion":2.2},{"id":"65a8b617-318c-429a-b37e-45ead00dbb7e","name":"Retry Form","type":"n8n-nodes-base.form","position":[-940,60],"webhookId":"0b4c88ed-d28b-4df4-abe6-4579e17c672d","parameters":{"options":{"formTitle":"Retry Submission","buttonLabel":"Generate!","formDescription":"Please enter a URL for the source image."},"formFields":{"values":[{"fieldLabel":"SourceImage","placeholder":"The image URL to copy the style from","requiredField":true},{"fieldLabel":"TargetPrompt","placeholder":"The new image to generate","requiredField":true},{"fieldType":"number","fieldLabel":"Number of Images","placeholder":"Max. 4 images"},{"fieldLabel":"Your Email (Optional)","placeholder":"The results will be sent to this email"}]},"limitWaitTime":true},"typeVersion":1},{"id":"8a0e8dae-9f6f-488e-9977-fd89e885f30e","name":"Upload to Cloudinary","type":"n8n-nodes-base.httpRequest","position":[880,-120],"parameters":{"url":"https://api.cloudinary.com/v1_1/daglih2g8/image/upload","method":"POST","options":{},"sendBody":true,"sendQuery":true,"contentType":"multipart-form-data","authentication":"genericCredentialType","bodyParameters":{"parameters":[{"name":"file","parameterType":"formBinaryData","inputDataFieldName":"data"}]},"genericAuthType":"httpQueryAuth","queryParameters":{"parameters":[{"name":"upload_preset","value":"n8n-workflows-preset"}]}},"credentials":{"httpQueryAuth":{"id":"sT9jeKzZiLJ3bVPz","name":"Cloudinary API"}},"typeVersion":4.2},{"id":"525725ea-effe-410b-8f39-ad01ae755d1a","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1480,-340],"parameters":{"color":7,"width":760,"height":640,"content":"## 1. Ask for Source Style and Target Image\n[Learn more about the Form Trigger](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.formtrigger/)\n\nWe'll use a form interface for this template which allows the users to specify an image whose style we'll use as reference and a prompt to generate the target image. Form validation loop can be achieved by combining another form node with the IF node."},"typeVersion":1},{"id":"ba9d4bdc-b695-4acf-9593-2ce979053744","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-700,-340],"parameters":{"color":7,"width":720,"height":440,"content":"## 2. Visual Style Description using Gemini 2.0\n[Read more about Gemini Image Understanding](https://ai.google.dev/gemini-api/docs/image-understanding)\n\nThe trick to copying the style of an image is to get a multimodal LLM to describe it in detail. Using Gemini's image understanding capabilities, it can do a pretty good job to provide the comprehensive description we need."},"typeVersion":1},{"id":"455f7956-6e39-4d84-af7e-d5908d4e5307","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[40,-340],"parameters":{"color":7,"width":720,"height":440,"content":"## 3. Image Generation using Imagen 3.0\n[Read more about Imagen Image Generation](https://ai.google.dev/gemini-api/docs/image-generation#imagen)\n\nTo generate the image, we'll be using Google's Imagen 3.0 model. We'll combine the visual style description generated in the previous Gemini model with the user's target image prompt and pass this to Imagen to do its magic! The result is something very close to style transfer which produces quite convincing and impressive results."},"typeVersion":1},{"id":"0c1d5a7f-9102-4558-a830-ed558f72c086","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[780,-340],"parameters":{"color":7,"width":980,"height":600,"content":"## 4. Render Results to HTML Page\n[Learn more about the HTML node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.html)\n\nFinally for presentation, we'll render the generated images as a webpage for easier viewing using the HTML node. This page can then be sent to the user's email if provided and downloaded as a file once we land on the form ending node."},"typeVersion":1},{"id":"ccc1ff65-0416-4dae-9557-ba2f98c5ac80","name":"Convert to File1","type":"n8n-nodes-base.convertToFile","position":[1320,60],"parameters":{"options":{"encoding":"utf8","fileName":"={{ $('Variables').item.json.targetPrompt.toSnakeCase().urlEncode() }}.html"},"operation":"toText","sourceProperty":"html"},"typeVersion":1.1},{"id":"0252d373-3678-4851-819d-d36efb40dfb2","name":"Generate HTML","type":"n8n-nodes-base.html","position":[1080,-120],"parameters":{"html":"<h1>\n  {{ $('Variables').item.json.targetPrompt.toSentenceCase() }}\n</h1>\n<div class=\"gallery\">\n{{\n$input.all()\n  .chunk(2)\n  .map(row =>\n    `<div class=\"gallery-row\">\n      ${row.map(item =>\n        `<a href=\"${item.json.url}\" target=\"_blank\">\n          <img src=\"${item.json.url}\" width=\"320px\" height=\"240px\"  />\n        </a>`).join('')}\n    </div>`\n  ).join('')\n}}\n</div>\n<div class=\"fineprint\">\n  Generated by Imagen 3.0 (imagen-3.0-generate-002) @ {{ $now.format('d MMM yyyy') }}.\n</div>\n<div class=\"fineprint\">\n  <h3>Style Prompt</h3>\n  <div style=\"display:flex;gap: 10px;\">\n    <div>\n      <img\n        src=\"{{ $('Download Image').item.json.sourceStyleUrl }}\"\n        width=\"100px\"\n        height=\"auto\"\n      />\n    </div>\n    <div>\n      {{ $('Gemini 2.0').first().json.candidates[0].content.parts[0].text }}\n    </div>\n  </div>\n</div>\n<style>\n  body { padding: 32px 64px; font-family: sans-serif; background-color: #fffaf2; }\n  h1 { max-width: 640px; }\n  .gallery { display: inline-block; padding: 5px; border: 1px solid #ccc; background-color: white; margin-bottom: 32px;}\n  .gallery-row { display: flex; }\n  .gallery-row img { padding: 5px; background-color: white }\n  .gallery-row img:hover { background-color: orange; } \n  .fineprint { font-size: 0.7rem; max-width: 480px; text-align: justify;}\n  .fineprint h3 { font-size: 0.8rem; }\n</style>"},"executeOnce":true,"typeVersion":1.2},{"id":"b712bd74-8615-4080-aad2-dc0b0df0b07e","name":"Convert to File","type":"n8n-nodes-base.convertToFile","position":[580,-120],"parameters":{"options":{"fileName":"={{ $execution.id }}_{{ $itemIndex }}.{{ $json.mimeType.split('/')[1] }}","mimeType":"={{ $json.mimeType }}"},"operation":"toBinary","sourceProperty":"bytesBase64Encoded"},"typeVersion":1.1},{"id":"ee3e168a-038c-4524-93fc-ced5d4956fa1","name":"Form Ending","type":"n8n-nodes-base.form","position":[1540,60],"webhookId":"c4bacbac-0347-4c35-9333-3704630b45ef","parameters":{"options":{"formTitle":"Generation Complete"},"operation":"completion","respondWith":"returnBinary","completionTitle":"Image Generation Successful","completionMessage":"Download has started.\nOpen the HTML file to view results."},"executeOnce":true,"typeVersion":1},{"id":"c4b1648a-c7d9-46cd-af28-527f9b169ab6","name":"Has Email?","type":"n8n-nodes-base.if","position":[1320,-120],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"07d04523-f81a-4efa-b46a-cb640bcc608a","operator":{"type":"string","operation":"notEmpty","singleValue":true},"leftValue":"={{ $('Variables').item.json.email }}","rightValue":""}]}},"typeVersion":2.2},{"id":"bc0a8188-27ff-4834-9c7a-8760531f4252","name":"Send Results to Email","type":"n8n-nodes-base.gmail","position":[1540,-120],"webhookId":"de5684ed-6aa4-4c29-aac3-62e21c54c6f0","parameters":{"sendTo":"={{ $('Variables').first().json.email }}","message":"={{ $json.html }}","options":{},"subject":"=#{{$execution.id}} - Image Generated Successfully!"},"credentials":{"gmailOAuth2":{"id":"Sf5Gfl9NiFTNXFWb","name":"Gmail account"}},"typeVersion":2.1},{"id":"f18ab53b-d8e2-4625-a8f6-8b97959a15d1","name":"Image to Base64","type":"n8n-nodes-base.extractFromFile","position":[-400,-120],"parameters":{"options":{},"operation":"binaryToPropery"},"typeVersion":1},{"id":"ac6c1353-035c-4045-aed9-46285b757b98","name":"Gemini 2.0","type":"n8n-nodes-base.httpRequest","position":[-180,-120],"parameters":{"url":"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent","method":"POST","options":{},"jsonBody":"={\n    \"contents\": [{\n      \"parts\": [\n        {\n          \"inline_data\": {\n            \"mime_type\":\"{{ $('Download Image').item.binary.data.mimeType }}\",\n            \"data\": \"{{ $json.data }}\"\n          }\n        },\n        {\"text\": \"Describe the visual style of this image. Do not include any character names or IP in the description. Include names of any famous artists associated with this style if known.\"}\n      ]\n    }]\n  }","sendBody":true,"specifyBody":"json","authentication":"predefinedCredentialType","nodeCredentialType":"googlePalmApi"},"credentials":{"googlePalmApi":{"id":"dSxo6ns5wn658r8N","name":"Google Gemini(PaLM) Api account"}},"typeVersion":4.2},{"id":"fae8c5f0-9d6f-4e45-8f7a-82f361bf9b1b","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-1920,-840],"parameters":{"width":400,"height":1140,"content":"## Try It Out!\n### This n8n template allows you to use AI to generate logos or images which mimic visual styles of other logos or images. The model used to generate the images is Google's Imagen 3.0.\n\nWith this template, users will be able to automate design and marketing tasks such as creating variants of existing designs, remixing existing assets to validate different styles and explore a range of designs which would have been otherwise too expensive and time-consming previously.\n\n### How it works\n* A form trigger is used to capture the source image to reference styles from and a prompt for the target image to generate.\n* The source image is passed to Gemini 2.0 to be analysed and its visual style and tone extracted as a detailed description.\n* This visual style description is then combined with the user's initial target image prompt. This final prompt is given to Imagen 3.0 to generate the images.\n* A quick webpage is put together with the generated images to present back to the user.\n* If the user provided an email address, a copy of this HTML page will be sent.\n\n### How to use\n* Ensure the workflow is live to share the form publicly.\n* The source image must be accessible to your n8n instance - either a public image of the internet or within your network.\n\n### Requirements\n* Gemini for LLM and Imagen model.\n* Cloudinary for image CDN.\n* Gmail for email sending.\n\n### Customising this workflow\n* Feel free to swap any of these out for tools and services you prefer.\n* Want to fully automate? Switch the form trigger for a webhook trigger!\n\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}],"pinData":{},"connections":{"Split Out":{"main":[[{"node":"Convert to File","type":"main","index":0}]]},"Variables":{"main":[[{"node":"Download Image","type":"main","index":0}]]},"Gemini 2.0":{"main":[[{"node":"Imagen 3.0","type":"main","index":0}]]},"Has Email?":{"main":[[{"node":"Send Results to Email","type":"main","index":0}]]},"Imagen 3.0":{"main":[[{"node":"Split Out","type":"main","index":0}]]},"Retry Form":{"main":[[{"node":"Form Validation","type":"main","index":0}]]},"Generate HTML":{"main":[[{"node":"Convert to File1","type":"main","index":0},{"node":"Has Email?","type":"main","index":0}]]},"Download Image":{"main":[[{"node":"Image to Base64","type":"main","index":0}]]},"Convert to File":{"main":[[{"node":"Upload to Cloudinary","type":"main","index":0}]]},"Form Validation":{"main":[[{"node":"Variables","type":"main","index":0}],[{"node":"Retry Form","type":"main","index":0}]]},"Image to Base64":{"main":[[{"node":"Gemini 2.0","type":"main","index":0}]]},"Convert to File1":{"main":[[{"node":"Form Ending","type":"main","index":0}]]},"On form submission":{"main":[[{"node":"Form Validation","type":"main","index":0}]]},"Upload to Cloudinary":{"main":[[{"node":"Generate HTML","type":"main","index":0}]]},"Send Results to Email":{"main":[[]]}}}


name: Automate New Customer Onboarding with HubSpot, Google Calendar, and AI-Powered Gmail
author_name: PollupAI
author_username: zeerobug
categories: []
created_at: 2025-05-09T10:11:20.532Z
updated_at: 2025-05-09T10:11:20.532Z
url: https://n8n.io/workflows/3958
scraped_at: 2025-06-19 22:50:29
description:
  This n8n workflow streamlines the onboarding process for new customers by automating personalized email communication, calendar scheduling, and contact assignment in HubSpot. It is perfect for businesses looking to ensure a smooth and personalized onboarding experience for new clients.

  🧑‍💼 Who is this for?

  Customer success teams who need to onboard new clients efficiently.
  Sales teams who want to ensure smooth transitions from prospect to customer.
  Small businesses that want to automate customer onboarding without complex systems.

  🧩 What problem is this workflow solving?

  This workflow reduces the manual effort involved in onboarding new customers by:

  Automatically sending personalized welcome emails.
  Scheduling a welcome meeting using a calendar tool.
  Assigning the customer to a Customer Success Manager (CSM) in HubSpot.

  ⚙️ What this workflow does

  Trigger via Webhook or HubSpot:
     The workflow can be triggered either by a webhook (direct API call) or a HubSpot trigger (e.g., when a new contact is created).

  HubSpot Connection:
     Retrieves the list of HubSpot owners (users with contact access).
     Identifies the owner of the new contact.

  Calendar Management:
     Utilizes a Calendar Agent to schedule a welcome meeting with the new customer.
     The Calendar Agent can create, update, or delete events as needed.

  Personalized Email Creation:
     Uses an AI-powered Email Writer (OpenAI) to generate a personalized welcome email.
     Transforms the email text into HTML for a polished format.

  Email Sending via Gmail:
     Sends the personalized email to the customer using Gmail.
     Sets the new contact’s owner in HubSpot for further communication tracking.

  🛠️ Setup

  Webhook Setup in n8n:
  	Create a new workflow and add a Webhook node.
  	Set the Webhook URL path (e.g., /webhook-customer-onboarding).
  	Make sure the workflow is active.

   Webhook Setup in HubSpot:
  	Go to HubSpot Developer Account.
  	Navigate to Settings &gt; Integrations &gt; Webhooks.
  	Create a new webhook and set the URL as the n8n Webhook URL.
  	Choose POST as the request method.
  	Test the webhook to ensure it triggers the workflow in n8n.

   Calendar Agent Configuration:
  	The Calendar Agent can be configured to create, update, or delete events.
  	Connect it to your calendar tool (Google Calendar, Outlook, etc.).
  	Customize the calendar event details (title, description, time).

   Email Writer Setup:
  	Customize the AI prompt in the Email Writer node to match your brand’s voice.
  	Adjust the email text format for your specific needs.

   Gmail Integration:
  	Connect your Gmail account in n8n.
  	Set the recipient email to the new customer’s email address.

  ✏️ How to customize this workflow to your needs

  Modify the AI-Powered Email**:
    Adjust the email prompt for the AI model to create a different welcome message.
    Change the email format or add custom variables (e.g., customer name, service details).

  Customize Calendar Settings**:
    Set default time slots for welcome meetings.
    Specify which calendar to use for scheduling.

  Add Additional Steps**:
    Extend the workflow to automatically assign the customer to a specific HubSpot list.
    Add a follow-up email or survey after the welcome meeting.

  This workflow is perfect for businesses seeking an efficient and personalized onboarding process, ensuring new customers feel welcomed and supported from day one.

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.hubspot","n8n-nodes-base.gmail","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.outputParserStructured","@n8n/n8n-nodes-langchain.toolWorkflow"]

workflow_json:
  {"nodes":[{"id":"b9256d00-9dff-432a-a678-e71a4074b26c","name":"Webhook","type":"n8n-nodes-base.webhook","position":[-20,-160],"webhookId":"06d29616-8fa9-42cf-8b5f-abe856083c75","parameters":{"path":"06d29616-8fa9-42cf-8b5f-abe856083c75","options":{},"httpMethod":"POST"},"typeVersion":2},{"id":"2726dd28-5366-4c0e-ad16-bae6dc2cbc0b","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-880,-200],"parameters":{"color":4,"width":320,"height":440,"content":"## What does it do?\nObjective:\n\nStreamline the onboarding process for new customers, ensuring they receive all necessary resources and support.\nTrigger: Set a webhook trigger or a CRM trigger (like HubSpot or Salesforce) for when a new customer is added.\n\nSend Welcome Email: Use the Gmail or SMTP node to send a personalized welcome email to the customer.\n\nSchedule a Welcome Call: Use the Calendar node (Google Calendar) to automatically create a calendar event for a welcome call.\n\nAssign a CSM: Use the CRM node (like HubSpot) to assign the new customer to a dedicated CSM."},"typeVersion":1},{"id":"680bdd4e-f382-4d20-8197-a7d65454ce36","name":"Try Again","type":"n8n-nodes-base.set","position":[1000,500],"parameters":{"options":{},"assignments":{"assignments":[{"id":"7ab380a2-a8d3-421c-ab4e-748ea8fb7904","name":"response","type":"string","value":"Unable to perform task. Please try again."}]}},"typeVersion":3.4},{"id":"1ab48997-7533-4572-86d5-980af557d09d","name":"Success","type":"n8n-nodes-base.set","position":[1000,300],"parameters":{"options":{},"assignments":{"assignments":[{"id":"39c2f302-03be-4464-a17a-d7cc481d6d44","name":"=response","type":"string","value":"={{$json.output}}"}]}},"typeVersion":3.4},{"id":"4cb493a1-1eff-42ca-9c51-8f070fe3e9ba","name":"Calendar Agent","type":"@n8n/n8n-nodes-langchain.agent","onError":"continueErrorOutput","position":[412,400],"parameters":{"text":"={{ $json.query }}","options":{"systemMessage":"=# Overview\nYou are a calendar assistant. Your responsibilities include creating, getting, and deleting events in the user's calendar.\nIf no date is proposed, find the next available slot using \"Get Events\" and create an event using \"Create Event with Attendee\"\n\n**Calendar Management Tools**  \n   - Use \"Create Event with Attendee\" when an event includes a participant.     \n   - Use \"Get Events\" to fetch calendar schedules when requested.\n   - Use \"Delete Event\" to delete an event. You must use \"Get Events\" first to get the ID of the event to delete.\n   - Use \"Update Event\" to update an event. You must use \"Get Events\" first to get the ID of the event to update.\n\n## Final Notes\nHere is the current date/time: {{ $now }}\nIf a duration for an event isn't specified, assume it will be one hour."},"promptType":"define"},"typeVersion":1.6},{"id":"8c088b37-1005-4bc4-bdf5-0558ccb0c873","name":"Create Event with Attendee","type":"n8n-nodes-base.googleCalendarTool","position":[320,620],"parameters":{"end":"={{ $fromAI(\"eventEnd\") }}","start":"={{ $fromAI(\"eventStart\") }}","calendar":{"__rl":true,"mode":"id","value":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Calendar', ``, 'string') }}","__regex":"(^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)"},"additionalFields":{"summary":"={{ $fromAI(\"eventTitle\") }}","attendees":["={{ $fromAI(\"eventAttendeeEmail\") }}"]}},"credentials":{"googleCalendarOAuth2Api":{"id":"90bjjmYqtg3hnvFM","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"91a0e49a-888f-4511-94e7-e0166ce7dd58","name":"Create Event","type":"n8n-nodes-base.googleCalendarTool","position":[440,620],"parameters":{"end":"={{ $fromAI(\"eventEnd\") }}","start":"={{ $fromAI(\"eventStart\") }}","calendar":{"__rl":true,"mode":"id","value":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Calendar', ``, 'string') }}","__regex":"(^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)"},"additionalFields":{"summary":"={{ $fromAI(\"eventTitle\") }}","attendees":[]}},"credentials":{"googleCalendarOAuth2Api":{"id":"90bjjmYqtg3hnvFM","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"8cfb90e5-6108-4003-b048-271650d4bc6c","name":"Get Events","type":"n8n-nodes-base.googleCalendarTool","position":[560,620],"parameters":{"options":{},"timeMax":"={{ $fromAI(\"dayBefore\",\"today plus 7 days\") }}","timeMin":"={{ $fromAI(\"dayAfter\",\"today\") }}","calendar":{"__rl":true,"mode":"id","value":"={{ $fromAI('Calendar', `sender's email`, 'string') }}"},"operation":"getAll"},"credentials":{"googleCalendarOAuth2Api":{"id":"90bjjmYqtg3hnvFM","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"c5cc3550-7d9a-43c9-8434-e1ab78f7f596","name":"Delete Event","type":"n8n-nodes-base.googleCalendarTool","position":[680,620],"parameters":{"eventId":"={{ $fromAI(\"eventID\") }}","options":{},"calendar":{"__rl":true,"mode":"id","value":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Calendar', ``, 'string') }}","__regex":"(^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)"},"operation":"delete"},"credentials":{"googleCalendarOAuth2Api":{"id":"90bjjmYqtg3hnvFM","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"7ce45da8-dc24-4634-9f48-3864165885cd","name":"Update Event","type":"n8n-nodes-base.googleCalendarTool","position":[800,620],"parameters":{"eventId":"={{ $fromAI(\"eventID\") }}","calendar":{"__rl":true,"mode":"id","value":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Calendar', ``, 'string') }}","__regex":"(^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)"},"operation":"update","updateFields":{"end":"={{ $fromAI(\"endTime\") }}","start":"={{ $fromAI(\"startTime\") }}"}},"credentials":{"googleCalendarOAuth2Api":{"id":"90bjjmYqtg3hnvFM","name":"Google Calendar account"}},"typeVersion":1.3},{"id":"b46f24a4-719c-414e-94d9-ecfb1e7dfe39","name":"When Executed by Another Workflow","type":"n8n-nodes-base.executeWorkflowTrigger","position":[200,400],"parameters":{"inputSource":"passthrough"},"typeVersion":1.1},{"id":"aedbe138-ed51-4300-881b-6b58928f5bb4","name":"OpenAI Chat Model2","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1520,160],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"1IOLtYX7aTspCAN8","name":"OpenAI Pollup"}},"typeVersion":1.2},{"id":"a540ae6b-e1ee-4d91-988e-e60bae743377","name":"calendarAgent","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[1640,160],"parameters":{"workflowId":{"__rl":true,"mode":"id","value":"={{ $workflow.id}}","cachedResultName":"={{ $workflow.id}}"},"description":"Call this tool for any calendar action.","workflowInputs":{"value":{},"schema":[],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false}},"typeVersion":2.2},{"id":"64979b9f-a29a-4c53-b87a-cec84e7ba1fe","name":"Structured Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[1760,160],"parameters":{"jsonSchemaExample":"{\n\t\"subject\": \"\",\n\t\"body\": \"\"\n}"},"typeVersion":1.2},{"id":"359d7296-a8e9-494c-b519-cca62c0805df","name":"Get list of owners","type":"n8n-nodes-base.httpRequest","position":[420,-60],"parameters":{"url":"https://api.hubapi.com/crm/v3/owners","options":{},"authentication":"predefinedCredentialType","nodeCredentialType":"hubspotOAuth2Api"},"credentials":{"hubspotOAuth2Api":{"id":"qubiIFrowxvUdpu6","name":"HubSpot account for node"}},"typeVersion":4.2},{"id":"e8aab719-a5d9-4168-9c68-eea32c7d3ef4","name":"Split Out owners","type":"n8n-nodes-base.splitOut","position":[640,-60],"parameters":{"options":{},"fieldToSplitOut":"results"},"typeVersion":1},{"id":"5e44ea67-e2f9-4cea-a030-c452b8bb482f","name":"Get current owner","type":"n8n-nodes-base.filter","position":[860,-60],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"7c6aec6e-66a9-4739-8a59-28f2ab1c4a26","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.email }}","rightValue":"={{ $('Enter your company data here').item.json.sender_email }}"}]}},"typeVersion":2.2},{"id":"c03bd58c-7a42-4966-96e8-45928f745475","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-540,-200],"parameters":{"color":5,"width":680,"height":1340,"content":"## How to Set a Webhook in n8n and HubSpot\n\n## 1. Set Up a Webhook in n8n\n\n### Step 1: Create a New Workflow\n- Go to your **n8n dashboard**.\n- Click on **\"New Workflow.\"**\n\n### Step 2: Add the Webhook Node\n- Click on the **“+”** icon to add a new node.\n- Search for **“Webhook”** and select it.\n- Set the **Webhook Method** (usually POST).\n- Define the **Webhook URL path**, for example, `/hubspot-webhook`.\n- Set the **\"Response Mode\"** (e.g., \"On Received\").\n- Save the workflow.\n\n### Step 3: Set Webhook URL\n- Copy the **Webhook URL** generated by n8n. It should look something like:https://your-n8n-domain/webhook/hubspot-webhook\n\n- Ensure the workflow is **active**.\n\n---\n\n## 2. Set Up a Webhook in HubSpot\n\n### Step 1: Log in to HubSpot\n- Go to **HubSpot Developer Account** (required for webhook setup).\n- Navigate to **\"Settings\" > \"Integrations\" > \"Webhooks.\"**\n\n### Step 2: Create a New Webhook Subscription\n- Click **“Create Webhook”** or **“Add Webhook”** if this is your first one.\n- Select the **events** you want to track (e.g., contact creation, form submission).\n- Set the **Webhook URL** as the n8n Webhook URL you copied earlier.\n- Choose **“POST”** as the request method.\n- Set the **Authentication** if needed (you can set a secret or use OAuth).\n\n### Step 3: Test the Webhook\n- Use the **“Test Webhook”** feature in HubSpot to send a test request.\n- Switch to n8n and ensure the webhook is triggering properly.\n\n---\n\n## 3. Process the Data in n8n\n- After the webhook is triggered in n8n, you will see the data sent by HubSpot.\n- You can now add additional nodes to **process the data** (e.g., save to database, send email, perform actions in another app).\n\n---\n\n## 4. Make the Workflow Active\n- Once you are done configuring, make sure the workflow is **set to “Active.”**\n- This will allow it to receive live data from HubSpot."},"typeVersion":1},{"id":"3861fa49-909d-4591-a1b8-d7bdd20e6560","name":"HubSpot Trigger","type":"n8n-nodes-base.hubspotTrigger","position":[-20,40],"webhookId":"632f3fc8-b921-4697-ba12-037d5c7f8971","parameters":{"eventsUi":{"eventValues":[{}]},"additionalFields":{}},"credentials":{"hubspotDeveloperApi":{"id":"DVrqcbIPANwtlVSg","name":"HubSpot Developer account for trigger"}},"typeVersion":1},{"id":"9051cc3d-06be-4238-998e-7cb938313d24","name":"Enter your company data here","type":"n8n-nodes-base.set","position":[200,-60],"parameters":{"options":{},"assignments":{"assignments":[{"id":"11a8b9e9-a7ed-454a-9aef-a9137c0e17ea","name":"company_name","type":"string","value":"Pollup Data Services"},{"id":"f2dcfe2e-3145-4a30-9731-0a8d02c7aa9a","name":"sender_name","type":"string","value":"Thomas Vié"},{"id":"18b5c0bd-4e75-4b98-92fc-5fca90a8b680","name":"sender_email","type":"string","value":"zeerobug@gmail.com"},{"id":"2c8de3ed-57dc-455b-bfa5-87a0d8d046d2","name":"company_activity","type":"string","value":"Whether it’s automating recurring tasks, analysing data faster, or personalising customer interactions, we build bespoke AI agents to help your workforce work smarter."}]}},"notesInFlow":true,"typeVersion":3.4},{"id":"5260ec73-0733-47d1-af03-66ead128820e","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[160,-200],"parameters":{"color":4,"width":400,"height":320,"content":"## Set your data and your company's \nThe sender_email you set here has to be the same as the one you use in hubspot "},"typeVersion":1},{"id":"78e301c7-3146-4bd9-9546-9f8c5b46cac7","name":"If a contact is created","type":"n8n-nodes-base.if","position":[1080,-60],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"b70f4699-008f-4924-8e69-af4fa69422a5","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $('Webhook').item.json.body[0].subscriptionType }}","rightValue":"contact.creation"}]}},"typeVersion":2.2},{"id":"b575fed7-da03-412d-aa00-fcf0edc85ae2","name":"Get all info about the contact","type":"n8n-nodes-base.hubspot","position":[1300,-60],"parameters":{"contactId":{"__rl":true,"mode":"id","value":"={{ $('Webhook').item.json.body[0].objectId }}"},"operation":"get","authentication":"oAuth2","additionalFields":{}},"credentials":{"hubspotOAuth2Api":{"id":"qubiIFrowxvUdpu6","name":"HubSpot account for node"}},"typeVersion":2.1},{"id":"956a02eb-970b-49bd-b1a5-3eebf7acb852","name":"Write a personalized message","type":"@n8n/n8n-nodes-langchain.agent","position":[1552,-60],"parameters":{"text":"=Your task is to write a personalized Welcome email to a recipient.\nWrite also to indicate him that he will receive shortly an invitation for a meeting to resolve his doubts. Use for that the calendarAgent.\nUse the \"Sender's calendar ID\" as the Calendar. And the \"Recipient email\" as an attendee\n\n## Tools\n- calendarAgent: Use this tool to take action in calendar. Send it a query like \"Schedule a meeting with attendee 'Recipient email' on 'Sender's calendar ID' calendar.\"\n\n## Rules\n- Some actions require you to look up contact information first. For the following actions, you must get contact information and send that to the agent who needs it:\n- creating calendar event with attendee, create it as son as there is some free slot\n\nreturn the message as a json like this one:{\"subject\":\"Subject of the message\",\"body\":\"Body of the message\"}\n\n## Use the variables below\nSender's name:  {{ $('Enter your company data here').item.json.sender_name }}\nSender's email: {{ $('Enter your company data here').item.json.sender_email }}\nSender's company name: {{ $('Enter your company data here').item.json.company_name }}\nSender's company activity: {{ $('Enter your company data here').item.json.company_activity }}\nSender's calendar ID: zeerobug@gmail.com\nRecipient first name: {{ $json.properties.firstname.value }}\nRecipient last name: {{ $json.properties.lastname }}\nRecipient email: {{ $json.properties.email.value }}","options":{"systemMessage":"=# Overview\nYou are a professional Customer Success Manager.\n"},"promptType":"define","hasOutputParser":true},"typeVersion":1.9},{"id":"6d392f67-5940-43ed-ac8d-d27f8dab91ed","name":"Send the message","type":"n8n-nodes-base.gmail","position":[2180,-60],"webhookId":"d1d18d77-71ad-4eab-91c6-08b6a9f5d736","parameters":{"sendTo":"={{ $('Get all info about the contact').item.json.properties.email.value }}","message":"={{ $json.data }}","options":{"bccList":"thomas@pollup.net"},"subject":"={{ $json.output.subject }}"},"credentials":{"gmailOAuth2":{"id":"DLjspol9TLgpGaXa","name":"Gmail account 2"}},"typeVersion":2.1},{"id":"1928e760-4ca1-443c-9de0-211b3c3c88b8","name":"Set owner to contact","type":"n8n-nodes-base.hubspot","position":[2400,-60],"parameters":{"email":"={{ $('Get all info about the contact').item.json.properties.email.value }}","options":{},"authentication":"oAuth2","additionalFields":{"contactOwner":"={{ $('Get current owner').item.json.id }}"}},"credentials":{"hubspotOAuth2Api":{"id":"qubiIFrowxvUdpu6","name":"HubSpot account for node"}},"typeVersion":2.1},{"id":"727e52cc-ba62-4f1e-b7b3-c8cd17ef1f42","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[160,220],"parameters":{"color":4,"width":1080,"height":560,"content":"## Calendar tool\nThis part has been borrowed from the excellent [Nate Herk](https://www.youtube.com/@nateherk) youtube channel"},"typeVersion":1},{"id":"e605ec3f-ecbe-47c7-a46b-d20ded665c55","name":"Transforms markdown to HTML","type":"n8n-nodes-base.markdown","position":[1960,-60],"parameters":{"mode":"markdownToHtml","options":{},"markdown":"={{ $json.output.body }}"},"typeVersion":1},{"id":"ac43422a-3642-424c-a95a-902652705dbc","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1460,-220],"parameters":{"color":4,"width":440,"height":540,"content":"## Email writer\n- This agent writes a personalized Email\n- Uses the calendar Agent tool to create an appointmenton an empty slot.\nFeel free to personalize the prompt"},"typeVersion":1},{"id":"c0e5511a-a84f-4603-9c23-3d5266f761c1","name":"OpenAI Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[200,620],"parameters":{"model":"gpt-4o","options":{}},"credentials":{"openAiApi":{"id":"1IOLtYX7aTspCAN8","name":"OpenAI Pollup"}},"typeVersion":1},{"id":"c195ad96-7b04-4b01-a3a5-cb0df3c5cb26","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-880,260],"parameters":{"width":320,"height":260,"content":"## Contact me\n- If you need any modification to this workflow\n- if you need some help with this workflow\n- Or if you need any workflow in n8n, Make, or Langchain / Langgraph\n\nWrite to me: [thomas@pollup.net](mailto:thomas@pollup.net)\n\n**Take a look at my others workflows [here](https://n8n.io/creators/zeerobug/)**\n\n"},"typeVersion":1}],"connections":{"Webhook":{"main":[[{"node":"Enter your company data here","type":"main","index":0}]]},"Get Events":{"ai_tool":[[{"node":"Calendar Agent","type":"ai_tool","index":0}]]},"Create Event":{"ai_tool":[[{"node":"Calendar Agent","type":"ai_tool","index":0}]]},"Delete Event":{"ai_tool":[[{"node":"Calendar Agent","type":"ai_tool","index":0}]]},"OpenAI Model":{"ai_languageModel":[[{"node":"Calendar Agent","type":"ai_languageModel","index":0}]]},"Update Event":{"ai_tool":[[{"node":"Calendar Agent","type":"ai_tool","index":0}]]},"calendarAgent":{"ai_tool":[[{"node":"Write a personalized message","type":"ai_tool","index":0}]]},"Calendar Agent":{"main":[[{"node":"Success","type":"main","index":0}],[{"node":"Try Again","type":"main","index":0}]]},"HubSpot Trigger":{"main":[[{"node":"Enter your company data here","type":"main","index":0}]]},"Send the message":{"main":[[{"node":"Set owner to contact","type":"main","index":0}]]},"Split Out owners":{"main":[[{"node":"Get current owner","type":"main","index":0}]]},"Get current owner":{"main":[[{"node":"If a contact is created","type":"main","index":0}]]},"Get list of owners":{"main":[[{"node":"Split Out owners","type":"main","index":0}]]},"OpenAI Chat Model2":{"ai_languageModel":[[{"node":"Write a personalized message","type":"ai_languageModel","index":0}]]},"If a contact is created":{"main":[[{"node":"Get all info about the contact","type":"main","index":0}]]},"Structured Output Parser":{"ai_outputParser":[[{"node":"Write a personalized message","type":"ai_outputParser","index":0}]]},"Create Event with Attendee":{"ai_tool":[[{"node":"Calendar Agent","type":"ai_tool","index":0}]]},"Transforms markdown to HTML":{"main":[[{"node":"Send the message","type":"main","index":0}]]},"Enter your company data here":{"main":[[{"node":"Get list of owners","type":"main","index":0}]]},"Write a personalized message":{"main":[[{"node":"Transforms markdown to HTML","type":"main","index":0}]]},"Get all info about the contact":{"main":[[{"node":"Write a personalized message","type":"main","index":0}]]},"When Executed by Another Workflow":{"main":[[{"node":"Calendar Agent","type":"main","index":0}]]}}}


name: Automated Financial Tracker: Telegram Invoices to Notion with Gemini AI Reports
author_name: Rizqi Pratama Ramadhani
author_username: rizqiramadhani
categories: []
created_at: 2025-05-09T11:57:48.753Z
updated_at: 2025-05-09T11:57:48.753Z
url: https://n8n.io/workflows/3960
scraped_at: 2025-06-19 22:50:12
description:
  Automated Financial Tracker: Telegram Invoices to Notion with AI Summaries & Reports

  Tired of manually logging every expense? Streamline your financial tracking with this powerful n8n workflow!

  Snap a photo of your invoice in Telegram, and let AI (powered by Google Gemini) automatically extract the details, record them in your Notion database, and even send you a quick summary. Plus, get scheduled weekly reports with charts to visualize your spending. Automate your finances, save time, and gain better insights with this easy-to-use template!

  Transform your expense tracking from a chore into an automated breeze. Try it out!

  Overview:

  This workflow revolutionizes how you track your finances by automating the entire process from invoice capture to reporting. Simply send a photo of an invoice or receipt to a designated Telegram chat, and this workflow will:

  Extract Data with AI: Utilize Google Gemini's capabilities to perform OCR on the image, understand the content, and extract key details like item name, quantity, price, total, date, and even attempt to categorize the expense.
  Store in Notion: Automatically log each extracted transaction into a structured Notion database.
  Instant Feedback: Send a summary of the processed transaction back to your Telegram chat.
  Scheduled Reporting: Generate and send a visual summary of your expenses (e.g., weekly spending by category) as a chart to your preferred Telegram chat or group.

  This workflow is perfect for individuals, freelancers, or small teams looking to effortlessly manage their expenses without manual data entry.

  Key Features & Benefits:

  Effortless Expense Logging:** Just send a picture – no more typing!
  AI-Powered Data Extraction:** Leverages Google Gemini for intelligent invoice processing.
  Centralized Data in Notion:** Keep all your financial records neatly organized in a Notion database.
  Automated Categorization:** AI helps in categorizing your expenses (e.g., Food & Beverage, Transportation).
  Instant Summaries:** Get immediate confirmation and a summary of what was recorded.
  Visual Reporting:** Receive scheduled charts (e.g., bar charts of spending by category) directly in Telegram.
  Customizable:** Easily adapt the workflow to your specific needs, categories, and reporting preferences.
  Time-Saving:** Drastically reduces the time spent on manual financial administration.

  How It Works (Workflow Breakdown):

  The workflow is divided into two main parts:

  Part 1: Real-time Invoice Processing & Logging (## Auto Notes Transaction with Telegram and Notion database)

  Telegram Trigger (Telegram Trigger | When recive photo): Activates when a new photo is sent to the configured Telegram chat.
  Get Photo Info (Get Info Photo from telegram chat): Retrieves the details of the received photo.
  Get Image Info (Get Image Info): Prepares the image data.
  AI Data Extraction (Google Gemini Chat Model & Basic LLM Chain):
      The image data is sent to the Google Gemini Chat Model.
      A specific prompt instructs the AI to extract details (date, ID, name, quantity, price, total, category, tax) in a JSON array format and provide a summary message. The categories include Food & Beverage, Transportation, Utilities, Shopping, Healthcare, Entertainment, Housing, and Education.
  Parse AI Output (Parse To your object | Table): Structures the AI's JSON output for easier handling.
  Split Transactions (Split Out | data transaction): If an invoice contains multiple items, this node splits them into individual records.
  Record to Notion (Record To Notion Database): Each transaction item is added as a new page/entry in your specified Notion database, mapping fields like Name, Quantity, Price, Total, Category, Date, and Tax.
  Send Telegram Summary (Sendback to chat and give summarize text): The summary message generated by the AI is sent back to the original Telegram chat.

  Part 2: Scheduled Financial Reporting (## Schedule report to send on chanel or private message)

  Schedule Trigger (Schedule Trigger | for send chart report): Runs at a predefined interval (e.g., every week) to generate reports.
  Get Recent Data from Notion (Get Recent Data from Notions): Fetches transaction data from the Notion database for a specific period (e.g., the past week).
  Summarize Data (Summarize Transaction Data): Aggregates the data, for example, by summing up the 'total' amount for each 'category'.
  Prepare Chart Data (Convert Data to JSON chart payload): Transforms the summarized data into a JSON format suitable for generating a chart (e.g., labels for categories, data for spending amounts).
  Generate Chart (Generate Chart): Uses the QuickChart node to create a visual chart (e.g., a bar chart) from the prepared data.
  Send Chart to Telegram (Send Chart Image to Group or Private Chat): Sends the generated chart image to a specified Telegram chat ID or group.

  Nodes Used (Key Nodes):

  Telegram Trigger & Telegram Node:** For receiving images and sending messages/images.
  Google Gemini Chat Model (Langchain):** For AI-powered OCR and data extraction from invoices.
  Basic LLM Chain (Langchain):** To interact with the language model using specific prompts.
  Output Parser Structured (Langchain):** To structure the output from the language model.
  Notion Node:** For reading from and writing to your Notion databases.
  Schedule Trigger:** To automate the reporting process.
  Summarize Node:** To aggregate data for reports.
  Code Node:** Used here to format data for the chart.
  QuickChart Node:** For generating charts.
  SplitOut Node:** To process multiple items from a single invoice.

  Setup Instructions:

  Credentials:
      Telegram: Create a Telegram bot and get its API token. You'll also need the Chat ID where you'll send invoices and where reports should be sent.
      Google Gemini (PaLM) API: You'll need an API key for Google Gemini.
      Notion: Create a Notion integration and get the API key. Create a Notion database with properties corresponding to the data you want to save (e.g., Name (Title), Quantity (Number), Price (Number), Total (Number), Category (Select), Date (Text or Date), Tax (Number)). Share this database with your Notion integration.
  Configure Telegram Trigger:
      Add your Telegram Bot API token.
      When you first activate the workflow or test the trigger, send /start to your bot in the chat you want to use for sending invoices. n8n will then capture the Chat ID.
  Configure Google Gemini Node (Google Gemini Chat Model):
      Select or add your Google Gemini API credentials.
      Review the prompt in the Basic LLM Chain node and adjust if necessary (e.g., date format, categories).
  Configure Notion Nodes:
      Record To Notion Database:
          Select or add your Notion API credentials.
          Select your target Notion Database ID.
          Map the properties from the workflow (e.g., ={{ $json.name }}) to your Notion database columns.
      Get Recent Data from Notions:
          Select or add your Notion API credentials.
          Select your target Notion Database ID.
          Adjust the filter if needed (default is "past_week").
  Configure Telegram Node for Reports (Send Chart Image to Group or Private Chat):
      Select or add your Telegram Bot API token.
      Enter the Chat ID for the group or private chat where you want to receive the reports.
  Configure Schedule Trigger (Schedule Trigger | for send chart report):
      Set your desired schedule (e.g., every Monday at 9 AM).
  Test: Send an image of an invoice to your Telegram bot and check if the data appears in Notion and if you receive a summary message. Wait for the scheduled report or manually trigger it to test the reporting functionality.

  Sticky Note Text for Your n8n Template:

  (These are suggestions. You would place these directly into the sticky notes within your n8n workflow editor.)

  Existing High-Level Sticky Notes:

  ## Auto Notes Transaction with Telegram and Notion database
  ## Schedule report to send on chanel or private message

  Specific Sticky Notes to Add:

  On Telegram Trigger | When recive photo:**
          📸 INVOICE INPUT 📸
      Bot listens here for photos of your receipts/invoices.
      Ensure your Telegram Bot API token is set in credentials.
      Near Google Gemini Chat Model & Basic LLM Chain:**
          🤖 AI MAGIC HAPPENS HERE 🧠
      Image is sent to Google Gemini for data extraction.
      Check 'Basic LLM Chain' to customize the AI prompt (e.g., categories, output format).
      Requires Google Gemini API credentials.
      On Parse To your object | Table:**
          ✨ STRUCTURING AI DATA ✨
      Converts the AI's text output into a usable JSON object.
      Check the schema if you modify the AI prompt significantly.
      On Record To Notion Database:**
          📝 SAVING TO NOTION 📝
      Extracted transaction data is saved here.
      Configure with your Notion API key & Database ID.
      Map fields correctly to your database columns!
      On Sendback to chat and give summarize text:**
          💬 TRANSACTION SUMMARY 💬
      Sends a confirmation message back to the user in Telegram
      with a summary of the recorded expense.
      On Schedule Trigger | for send chart report:**
          🗓️ REPORTING SCHEDULE 🗓️
      Set how often you want to receive your spending report (e.g., weekly, monthly).
      On Get Recent Data from Notions:**
          📊 FETCHING DATA FOR REPORT 📊
      Retrieves transactions from Notion for the report period.
      Default: "Past Week". Adjust filter as needed.
      Requires Notion API credentials & Database ID.
      On Summarize Transaction Data:**
          ➕ SUMMARIZING SPENDING ➕
      Aggregates your expenses, usually by category,
      to prepare for the chart.
      On Convert Data to JSON chart payload (Code Node):**
          🎨 PREPARING CHART DATA 🎨
      This Code node formats the summarized data
      into the JSON structure needed by QuickChart.
      On Generate Chart (QuickChart Node):**
          📈 GENERATING VISUAL REPORT 📈
      Creates the actual chart image based on your spending data.
      You can customize chart type (bar, pie, etc.) here.
      On Send Chart Image to Group or Private Chat:**
          📤 SENDING REPORT TO TELEGRAM 📤
      Delivers the generated chart to your chosen Telegram chat/group.
      Set the correct Chat ID and Bot API token.
      General Sticky Note (Place where relevant):**
          🔑 CREDENTIALS NEEDED 🔑
      Remember to set up API keys/tokens for:
      Telegram
      Google Gemini
      Notion
      General Sticky Note (Place where relevant):**
          💡 CUSTOMIZE ME! 💡
      Adjust AI prompts for better accuracy.
      Change Notion database structure.
      Modify report frequency and content.
      `

nodes_used:
  ["n8n-nodes-base.editImage","n8n-nodes-base.telegram","n8n-nodes-base.notion","n8n-nodes-base.code","n8n-nodes-base.quickChart","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.outputParserStructured","@n8n/n8n-nodes-langchain.lmChatGoogleGemini"]

workflow_json:
  {"id":"3BkxvtCbF6hHGUgM","meta":{"instanceId":"d847dccbed2cefba539a228a44c266869b59eafbd4f307c4928a1149fb542a9e","templateCredsSetupCompleted":true},"name":"N8N Financial Tracker Telegram Invoices to Notion with AI Summaries & Reports","tags":[{"id":"OXcPKHaINFSvU1ux","name":"Money","createdAt":"2025-05-09T11:02:15.929Z","updatedAt":"2025-05-09T11:02:15.929Z"},{"id":"witgF3iHQ0sAlkjG","name":"experimental","createdAt":"2025-05-09T11:02:15.933Z","updatedAt":"2025-05-09T11:02:15.933Z"}],"nodes":[{"id":"3792ae58-807f-4e83-a219-25c17c8b4048","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[680,380],"parameters":{"options":{},"modelName":"models/gemini-2.5-flash-preview-04-17"},"credentials":{"googlePalmApi":{"id":"haEP6ehKtsSUjFmK","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"943f87e2-a1ac-4f7e-999b-8ea261259e5a","name":"Basic LLM Chain","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[640,220],"parameters":{"text":"=ini ada base64 invoice rangkumkan Pengeluaran dari invoice tersebut Nama Barang jumlah dan Pengeluaran masing masing barang dan total, outputnya jangan panjang panjang saya cukup berikan \n\ndate: DD-MM-YYYY ( Jika dari OCR tidak ada tanggal ambil tanggal hari ini )\nid:\nname:\n qty: \nprice:\n total:\ncategory:\ntax : (jika di total berbeda dengan item brati ada pajak nya hitungkan juga pajaknya masukan kesini)\n\nuntuk pilihan categorynya : Food & Beverage / Transportation / Utilities / Shopping / Healthcare / Entertaiment / Housing / Education\n\ndalam bentuk JSON array object, berikan juga key message summary untuk rangkuman, berikan rangkauman singkat total pengeluaran dan barang apa saja yang dibeli serta jumlah nya berikan juga pajaknya","messages":{"messageValues":[{"type":"HumanMessagePromptTemplate","messageType":"imageBinary"}]},"promptType":"define","hasOutputParser":true},"typeVersion":1.4},{"id":"247b78cb-c3f6-4f31-8559-0fff70de9ba9","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[0,0],"parameters":{"width":1703,"height":580,"content":"## Automated Financial Tracker: Telegram Invoices to Notion with AI Summaries & Reports\n"},"typeVersion":1},{"id":"e20045c2-a8ef-43d6-b619-6825f605e183","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[0,620],"parameters":{"color":5,"width":1706,"height":527,"content":"## Schedule report to send on chanel or private message\n"},"typeVersion":1},{"id":"ed8d6544-af9e-416a-b1f3-624ca108427f","name":"Schedule Trigger | for send chart report","type":"n8n-nodes-base.scheduleTrigger","position":[80,880],"parameters":{"rule":{"interval":[{}]}},"typeVersion":1.2},{"id":"22ad7ea1-9404-48bd-9d0f-0c58b8b66e3d","name":"Get Recent Data from Notions","type":"n8n-nodes-base.notion","position":[400,940],"parameters":{"filters":{"conditions":[{"key":"Created time|created_time","condition":"past_week"}]},"options":{},"resource":"databasePage","operation":"getAll","returnAll":true,"databaseId":{"__rl":true,"mode":"list","value":"1d858554-d218-807c-936c-d06c8a8ec769","cachedResultUrl":"https://www.notion.so/1d858554d218807c936cd06c8a8ec769","cachedResultName":"Pengeluaran Rizqi Dini"},"filterType":"manual"},"credentials":{"notionApi":{"id":"AhjWhO7Jpc5x7xKG","name":"Notion account"}},"typeVersion":2.2},{"id":"34310645-52da-4f9c-96a2-0a01d0a640f9","name":"Summarize Transaction Data","type":"n8n-nodes-base.summarize","position":[760,920],"parameters":{"options":{},"fieldsToSplitBy":"property_category","fieldsToSummarize":{"values":[{"field":"property_total","aggregation":"sum"}]}},"typeVersion":1},{"id":"80a374cb-00cf-46b1-9505-709be1c550da","name":"Generate Chart","type":"n8n-nodes-base.quickChart","position":[1200,900],"parameters":{"data":"={{ $json.chart.data.datasets[0].data }}","labelsMode":"array","labelsArray":"={{ $json.chart.data.labels }}","chartOptions":{},"datasetOptions":{}},"typeVersion":1},{"id":"6b7c67ee-b205-42f5-9441-eb2ecee4a503","name":"Send Chart Image to Group or Private Chat","type":"n8n-nodes-base.telegram","position":[1460,760],"webhookId":"66cce6e1-819c-487b-b8ad-3f02aebd40cb","parameters":{"chatId":"-1001957001324","operation":"sendPhoto","binaryData":true,"additionalFields":{"fileName":"chart","message_thread_id":571}},"credentials":{"telegramApi":{"id":"J8yRVYmsnH74HuaD","name":"Telegram account"}},"typeVersion":1.2},{"id":"06afd5ea-77b2-468d-b12b-1386d37a3ee6","name":"Convert Data to JSON chart payload","type":"n8n-nodes-base.code","position":[1080,900],"parameters":{"jsCode":"const labels = [];\nconst values = [];\n\nfor (const item of items) {\n  labels.push(item.json.property_category);\n  values.push(item.json.sum_property_total);\n}\n\nreturn [\n  {\n    json: {\n      chart: {\n        type: 'bar',\n        data: {\n          labels,\n          datasets: [\n            {\n              label: 'Spending by Category',\n              data: values,\n              backgroundColor: 'rgba(54, 162, 235, 0.6)',\n              borderColor: 'rgba(54, 162, 235, 1)',\n              borderWidth: 1\n            }\n          ]\n        },\n        options: {\n          plugins: {\n            title: {\n              display: true,\n              text: 'Spending Summary by Category'\n            }\n          },\n          scales: {\n            y: {\n              beginAtZero: true\n            }\n          }\n        }\n      }\n    }\n  }\n];"},"typeVersion":2},{"id":"4ad8c9c9-fbec-46ce-943d-447ca687e031","name":"Telegram Trigger | When recive photo","type":"n8n-nodes-base.telegramTrigger","position":[160,160],"webhookId":"cac4ce91-ed1f-42ea-aebe-97ac3612aea6","parameters":{"updates":["message"],"additionalFields":{}},"credentials":{"telegramApi":{"id":"J8yRVYmsnH74HuaD","name":"Telegram account"}},"typeVersion":1.1},{"id":"5231929f-2d7d-43ff-b9ae-141374926131","name":"Get Image Info","type":"n8n-nodes-base.editImage","position":[460,160],"parameters":{"operation":"information"},"typeVersion":1},{"id":"c8dcc6a1-2367-4049-9a8b-d8a04299ee72","name":"Parse To your object | Table","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[1040,460],"parameters":{"schemaType":"manual","inputSchema":"{\n  \"type\": \"object\",\n  \"properties\": {\n    \"message\": {\n      \"type\": \"string\"\n    },\n    \"summary\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\"date\": { \"type\": \"date\" },\n          \"id\": { \"type\": \"integer\" },\n          \"name\": { \"type\": \"string\" },\n          \"qty\": { \"type\": \"integer\" },\n          \"price\": { \"type\": \"number\" },\n          \"tax\": { \"type\": \"number\" },\n          \"total\": { \"type\": \"number\" },\"category\": { \"type\": \"string\" }\n        },\n        \"required\": [\"id\", \"name\", \"qty\", \"price\", \"total\",\"category\"]\n      }\n    }\n  },\n  \"required\": [\"message\", \"summary\"]\n}\n"},"typeVersion":1.2},{"id":"bc098a26-4e55-4908-880c-e5f27737a941","name":"Split Out | data transaction","type":"n8n-nodes-base.splitOut","position":[1120,40],"parameters":{"options":{},"fieldToSplitOut":"output.summary"},"typeVersion":1},{"id":"2a42bc4b-a5c7-433e-91e4-aa5531570f73","name":"Sendback to chat and give summarize text","type":"n8n-nodes-base.telegram","position":[1480,400],"webhookId":"f90475fa-69cd-4e19-bc93-bffdceae8324","parameters":{"text":"={{ $json.output.message }}","chatId":"={{ $('Telegram Trigger | When recive photo').item.json.message.chat.id }}","additionalFields":{"appendAttribution":false}},"credentials":{"telegramApi":{"id":"J8yRVYmsnH74HuaD","name":"Telegram account"}},"typeVersion":1.2},{"id":"bfc5c52e-313d-4257-bdfa-c542b687a853","name":"Record To Notion Database","type":"n8n-nodes-base.notion","position":[1580,120],"parameters":{"options":{},"resource":"databasePage","databaseId":{"__rl":true,"mode":"list","value":"1d858554-d218-807c-936c-d06c8a8ec769","cachedResultUrl":"https://www.notion.so/1d858554d218807c936cd06c8a8ec769","cachedResultName":"Pengeluaran Rizqi Dini"},"propertiesUi":{"propertyValues":[{"key":"Name|title","title":"={{ $json.name }}"},{"key":"Quantity|number","numberValue":"={{ $json.qty }}"},{"key":"Price|number","numberValue":"={{ $json.price }}"},{"key":"Total|number","numberValue":"={{ $json.total }}"},{"key":"Category|select","selectValue":"={{ $json.category }}"},{"key":"Date|rich_text","textContent":"={{ $json.date }}"},{"key":"Tax|number","numberValue":"={{ $json.tax }}"}]}},"credentials":{"notionApi":{"id":"AhjWhO7Jpc5x7xKG","name":"Notion account"}},"typeVersion":2.2},{"id":"f514554b-eb9e-47e2-ad6b-0b13036beaf4","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[40,60],"parameters":{"color":3,"width":340,"height":280,"content":"📸 INVOICE INPUT 📸\nBot listens here for photos of your receipts/invoices.\nEnsure your Telegram Bot API token is set in credentials."},"typeVersion":1},{"id":"53fc4c77-3f16-4cb8-82e8-f4810af1f569","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[600,60],"parameters":{"color":5,"width":360,"height":460,"content":"🤖 AI MAGIC HAPPENS HERE 🧠\n- Image is sent to Google Gemini for data extraction.\n- Check 'Basic LLM Chain' to customize the AI prompt (e.g., categories, output format).\n- Requires Google Gemini API credentials."},"typeVersion":1},{"id":"c6fb1193-7cc9-4f45-8a5f-20af41cdf3c8","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[980,340],"parameters":{"color":5,"width":280,"height":200,"content":"✨ STRUCTURING AI DATA ✨\nConverts the AI's text output into a usable JSON object.\nCheck the schema if you modify the AI prompt significantly."},"typeVersion":1},{"id":"79a4e9ba-d1ea-4cfc-870c-145bae80c9b4","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1320,0],"parameters":{"color":2,"width":380,"height":240,"content":"📝 SAVING TO NOTION 📝\n- Extracted transaction data is saved here.\n- Configure with your Notion API key & Database ID.\n- Map fields correctly to your database columns!"},"typeVersion":1},{"id":"9406306b-9f3d-4877-a888-1f5e16a431c1","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[20,760],"parameters":{"height":280,"content":"REPORTING SCHEDULE 🗓️\nSet how often you want to receive your spending report (e.g., weekly, monthly)."},"typeVersion":1},{"id":"1b6c8a28-b0f0-44fb-be02-21725d950716","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[320,760],"parameters":{"color":2,"width":280,"height":380,"content":"📊 FETCHING DATA FOR REPORT 📊\n- Retrieves transactions from Notion for the report period.\n- Default: \"Past Week\". Adjust filter as needed.\n- Requires Notion API credentials & Database ID."},"typeVersion":1},{"id":"4612006e-04a9-4ad5-9f05-d49ec13f31cf","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[660,740],"parameters":{"width":320,"height":360,"content":"➕ SUMMARIZING SPENDING ➕\nAggregates your expenses, usually by category,\nto prepare for the chart."},"typeVersion":1},{"id":"103132cf-37a6-455f-b19f-14d3e17af912","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[1040,740],"parameters":{"width":300,"height":340,"content":"📈 GENERATING VISUAL REPORT 📈\nCreates the actual chart image based on your spending data.\nYou can customize chart type (bar, pie, etc.) here."},"typeVersion":1},{"id":"24324366-33e5-4097-ab36-aac31cef0006","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[1380,640],"parameters":{"color":6,"width":300,"height":300,"content":"📤 SENDING REPORT TO TELEGRAM 📤\n- Delivers the generated chart to your chosen Telegram chat/group.\n- Set the correct Chat ID and Bot API token."},"typeVersion":1},{"id":"e9fc1140-411b-411a-87a6-bbe9718ba3b3","name":"Sticky Note11","type":"n8n-nodes-base.stickyNote","position":[1320,280],"parameters":{"color":6,"width":300,"height":280,"content":"💬 TRANSACTION SUMMARY 💬\nSends a confirmation message back to the user in Telegram\nwith a summary of the recorded expense."},"typeVersion":1},{"id":"013fd587-3504-44b8-97e1-09cad47a0089","name":"Sticky Note12","type":"n8n-nodes-base.stickyNote","position":[40,360],"parameters":{"color":7,"width":460,"height":240,"content":"  🔑 CREDENTIALS NEEDED 🔑\n  Remember to set up API keys/tokens for:\n  - Telegram\n  - Google Gemini\n  - Notion\n\n  💡 CUSTOMIZE ME! 💡\n  - Adjust AI prompts for better accuracy.\n  - Change Notion database structure.\n  - Modify report frequency and content.\n"},"typeVersion":1},{"id":"8f6f0fdb-d3be-4464-a7db-ea4d642a4f55","name":"Telegram","type":"n8n-nodes-base.telegram","position":[320,160],"webhookId":"6e801e0b-72d1-42a9-ac47-61ac113a01d2","parameters":{"fileId":"={{ $json.message.photo[3].file_id }}","resource":"file"},"credentials":{"telegramApi":{"id":"J8yRVYmsnH74HuaD","name":"Telegram account"}},"typeVersion":1.2}],"active":true,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"a192c50c-4a77-44ee-b98a-f18d4ced2cb1","connections":{"Telegram":{"main":[[{"node":"Get Image Info","type":"main","index":0}]]},"Generate Chart":{"main":[[{"node":"Send Chart Image to Group or Private Chat","type":"main","index":0}]]},"Get Image Info":{"main":[[{"node":"Basic LLM Chain","type":"main","index":0}]]},"Basic LLM Chain":{"main":[[{"node":"Split Out | data transaction","type":"main","index":0},{"node":"Sendback to chat and give summarize text","type":"main","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"Basic LLM Chain","type":"ai_languageModel","index":0}]]},"Summarize Transaction Data":{"main":[[{"node":"Convert Data to JSON chart payload","type":"main","index":0}]]},"Get Recent Data from Notions":{"main":[[{"node":"Summarize Transaction Data","type":"main","index":0}]]},"Parse To your object | Table":{"ai_outputParser":[[{"node":"Basic LLM Chain","type":"ai_outputParser","index":0}]]},"Split Out | data transaction":{"main":[[{"node":"Record To Notion Database","type":"main","index":0}]]},"Convert Data to JSON chart payload":{"main":[[{"node":"Generate Chart","type":"main","index":0}]]},"Telegram Trigger | When recive photo":{"main":[[{"node":"Telegram","type":"main","index":0}]]},"Schedule Trigger | for send chart report":{"main":[[{"node":"Get Recent Data from Notions","type":"main","index":0}]]}}}


name: Summarise Slack Channel Activity for Weekly Reports with AI
author_name: Jimleuk
author_username: jimleuk
categories: []
created_at: 2025-05-10T08:37:45.163Z
updated_at: 2025-05-10T08:37:45.163Z
url: https://n8n.io/workflows/3969
scraped_at: 2025-06-19 22:49:14
description:
  This n8n template lets you summarize team member activity on Slack for the past week and generates a report.

  For remote teams, chat is a crucial communication tool to ensure work gets done but with so many conversations happening at once and in multiple threads, ideas, information and decisions usually live in the moment and get lost just as quickly - and all together forgotten by the weekend!

  Using this template, this doesn't have to be the case. Have AI crawl through last week's activity, summarize all threads and generate a casual and snappy report to bring the team back into focus for the current week. A project manager's dream!

  How it works
  A scheduled trigger is set to run every Monday at 6am to gather all team channel messages within the last week.
  Each message thread are grouped by user and data mined for replies.
  Combined, an AI analyses the raw messages to pull out interesting observations and highlights.
  The summarized threads of the user are then combined together and passed to another AI agent to generate a higher level overview of their week. These are referred to as the individual reports.
  Next, all individual reports are summarized together into a team weekly report. This allows understanding of group and similar activities.
  Finally, the team weekly report is posted back to the channel. The timing is important as it should be the first message of the week and ready for the team to glance over coffee.

  How to use
  Ideally works best per project and where most of the comms happens on a single channel. Avoid combining channels and instead duplicate this workflow for more channels.
  You may need to filter for specific team members if you want specific team updates.
  Customise the report to suit your organisation, team or the channel. You may prefer to be more formal if clients or external stakeholders are also present.

  Requirements
  Slack for chat platform
  Gemini for LLM (or switch for other models)

  Customising this workflow
  If the slack channel is busy enough already, consider posting the final report to email.
  Pull in project metrics to include in your report. As extra context, it may be interesting to tie the messages to production performance.
  Use an AI Agent to query for knowledgebase or tickets relevant to the messages. This may be useful for attaching links or references to add context.
  Channel not so busy or way too busy for 1 week? Play with the scheduled trigger and set an interval which works for your team. 

nodes_used:
  ["n8n-nodes-base.slack","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.lmChatGoogleGemini"]

workflow_json:
  {"meta":{"instanceId":"408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9","templateCredsSetupCompleted":true},"nodes":[{"id":"f4322829-1799-4954-a75a-b40e95f41c10","name":"Get Last Week's Messages","type":"n8n-nodes-base.slack","position":[-2200,-160],"webhookId":"8078218a-7edc-4e0b-9b4d-9860bd309877","parameters":{"filters":{"oldest":"={{ $now.minus('1', 'week') }}","inclusive":false},"resource":"channel","channelId":{"__rl":true,"mode":"list","value":"C06RS1WPUQ6","cachedResultName":"general"},"operation":"history","returnAll":true},"credentials":{"slackApi":{"id":"VfK3js0YdqBdQLGP","name":"Slack account"}},"typeVersion":2.3},{"id":"f0e89c19-ee1f-4a4d-8176-c222c18e0514","name":"Simplify Message","type":"n8n-nodes-base.set","position":[-1320,380],"parameters":{"options":{},"assignments":{"assignments":[{"id":"547e8934-e6f2-47f0-b8a0-c60bd9d8a0c3","name":"ts","type":"string","value":"={{ $json.ts }}"},{"id":"22473b44-b1d9-4b85-b0d9-1a54c5511ff4","name":"userId","type":"string","value":"={{ $('Get User').first().json.id }}"},{"id":"2059b147-8b12-42c9-bee8-488dc11a0bf7","name":"userName","type":"string","value":"={{ $('Get User').first().json.name }}"},{"id":"34440ea6-ee99-4cd4-9e1c-cf561d335180","name":"type","type":"string","value":"={{ $json.type }}"},{"id":"ff1155c5-43e1-4e0e-82a8-9e013a7f1db1","name":"text","type":"string","value":"={{ $json.text.replace(/(<@[^>]+>)/ig, '').trim() }}"}]}},"typeVersion":3.4},{"id":"1293a7cf-1467-432f-b7ed-606146618808","name":"Group By User","type":"n8n-nodes-base.code","position":[-2000,-160],"parameters":{"jsCode":"const keyByUser = $input.all()\n  .map(item => item.json)\n  .reduce((acc, message) => {\n    return {\n      ...acc,\n      [message.user]: Array.isArray(acc[message.user])\n        ?  acc[message.user].concat(message)\n        : [message]\n    }\n  }, {});\n\nreturn {\n  data: Object\n    .keys(keyByUser)\n    .map(key => keyByUser[key])\n};"},"typeVersion":2},{"id":"681a2368-9688-4ebd-bb88-f48c7ccb3e54","name":"Split Out","type":"n8n-nodes-base.splitOut","position":[-1800,-160],"parameters":{"options":{},"fieldToSplitOut":"data"},"typeVersion":1},{"id":"38a5e6b0-ba4a-4aaa-93f2-ec2a73e5e1af","name":"Messages to Items","type":"n8n-nodes-base.code","position":[-1540,380],"parameters":{"jsCode":"return Object.values($('Switch').first().json.data)"},"typeVersion":2},{"id":"066e40ef-91d7-4db0-95bb-2027c9251a23","name":"Get User","type":"n8n-nodes-base.slack","position":[-1760,380],"webhookId":"042e9c13-5038-433a-98dc-8b6d83c015de","parameters":{"user":{"__rl":true,"mode":"id","value":"={{ $json.data['0'].user }}"},"resource":"user"},"credentials":{"slackApi":{"id":"VfK3js0YdqBdQLGP","name":"Slack account"}},"typeVersion":2.3},{"id":"c5d0b4d1-94eb-4e14-9985-85d384d6d96f","name":"Aggregate","type":"n8n-nodes-base.aggregate","position":[-1100,380],"parameters":{"options":{},"aggregate":"aggregateAllItemData","destinationFieldName":"messages"},"typeVersion":1},{"id":"47537a27-90d9-4edc-b9f4-66205bc4a4c2","name":"Split Out1","type":"n8n-nodes-base.splitOut","position":[-1760,780],"parameters":{"options":{},"fieldToSplitOut":"data.messages"},"typeVersion":1},{"id":"6fdd0fc0-c563-46a3-afb2-48853d3e6cef","name":"Get Thread","type":"n8n-nodes-base.slack","position":[-1100,780],"webhookId":"c3ef27dc-2648-4f91-b329-89a7fa833797","parameters":{"ts":"={{ $json.ts }}","filters":{},"resource":"channel","channelId":{"__rl":true,"mode":"list","value":"C06RS1WPUQ6","cachedResultName":"general"},"operation":"replies"},"credentials":{"slackApi":{"id":"VfK3js0YdqBdQLGP","name":"Slack account"}},"typeVersion":2.3},{"id":"0fc6664f-9076-4525-acaa-0f5009de2611","name":"Aggregate1","type":"n8n-nodes-base.aggregate","position":[-440,860],"parameters":{"options":{},"aggregate":"aggregateAllItemData","destinationFieldName":"replies"},"typeVersion":1},{"id":"caf963e5-3d5b-42d8-88ce-1fb5bf03a528","name":"Simplify Thread Comments","type":"n8n-nodes-base.set","position":[-660,780],"parameters":{"options":{},"assignments":{"assignments":[{"id":"82bc8cbe-c606-4717-b29d-2d8acc149271","name":"ts","type":"string","value":"={{ $json.ts }}"},{"id":"8fcc957d-aa9f-47df-99e8-560228fde30f","name":"userId","type":"string","value":"={{ $json.user }}"},{"id":"e6c6deb3-c3ba-4452-be7c-1a0c42c5dc2c","name":"userName","type":"string","value":""},{"id":"31d1206d-ecbd-48d3-a00a-845fd53d1cfa","name":"type","type":"string","value":"={{ $json.type }}"},{"id":"da126e6c-8dfc-41aa-991a-231b3cb3004b","name":"text","type":"string","value":"={{ $json.text }}"}]}},"typeVersion":3.4},{"id":"aab0ae1c-50da-49e5-a373-c32b39108041","name":"Filter","type":"n8n-nodes-base.filter","position":[-880,780],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"a6d43072-380e-40f2-985b-faeffdaffdce","operator":{"type":"string","operation":"notEquals"},"leftValue":"={{ $('Split Out1').item.json.ts }}","rightValue":"={{ $json.ts }}"}]}},"typeVersion":2.2,"alwaysOutputData":true},{"id":"35cdb470-a9eb-4544-999c-5360dda0f1a3","name":"Message Ref","type":"n8n-nodes-base.noOp","position":[-1320,780],"parameters":{},"typeVersion":1},{"id":"95500787-7965-4951-a729-615feb636021","name":"Split Out2","type":"n8n-nodes-base.splitOut","position":[-1320,1080],"parameters":{"options":{},"fieldToSplitOut":"replyUsers"},"typeVersion":1},{"id":"250d61cc-120d-4c0c-8220-f9a68a90b667","name":"Map Reply UserIds","type":"n8n-nodes-base.set","position":[-1760,1160],"parameters":{"options":{},"assignments":{"assignments":[{"id":"dda6e3d8-0097-4621-9619-07cf39e93018","name":"replyUsers","type":"array","value":"={{\n$json.data.messages\n  .flatMap(item => item.replies.flatMap(reply => reply.userId))\n  .compact()\n  .unique()\n}}"}]}},"typeVersion":3.4},{"id":"3358736b-fc6e-4e18-9a58-4ffc59308055","name":"Get Reply Users","type":"n8n-nodes-base.slack","position":[-1100,1080],"webhookId":"c9ad7c7e-2c48-4c24-9255-e04ab26252ab","parameters":{"user":{"__rl":true,"mode":"id","value":"={{ $json.replyUsers }}"},"resource":"user"},"credentials":{"slackApi":{"id":"VfK3js0YdqBdQLGP","name":"Slack account"}},"typeVersion":2.3},{"id":"e98acd0f-f1e3-47f4-ae9c-7259462cf231","name":"Google Gemini Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[-120,1380],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"dSxo6ns5wn658r8N","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"0ffb9b87-43db-4417-8c37-384a33cbb830","name":"Summarise Threads","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[-220,1160],"parameters":{"text":"=## Message\n{{ $json.userName }} (<@{{ $json.userId }}>) says at {{ new DateTime(parseFloat($json.ts)*1000).format('d MMM HH:mma') }}:\n> {{ $json.text }}\n\n## {{ ($json.replies ?? []).compact().length }} Replies\n{{\n($json.replies ?? [])\n  .compact()\n    .map(reply => ({\n      ...reply,\n      userName: $('Reply Users').item.json.data\n        .find(user => user.id === reply.userId)?.name\n    }))\n    .map(reply =>\n      `* ${new DateTime(parseFloat($json.ts)*1000).format('d MMM HH:mma')}, ${reply.userName} (<@${reply.userId}>) replies: ${reply.text}`\n)\n    .join('\\n')\n  \n}}","messages":{"messageValues":[{"message":"=Summarize the topic of the slack message and the resulting conversation from the replies (if any). Highlight any achievements, accomplishments, attempts or challenges mentioned."}]},"promptType":"define"},"typeVersion":1.6},{"id":"678a48ec-acb1-4c42-b8c9-d4cd762e4a2a","name":"Aggregate2","type":"n8n-nodes-base.aggregate","position":[160,1160],"parameters":{"options":{},"aggregate":"aggregateAllItemData"},"typeVersion":1},{"id":"ab39b117-e1bd-495f-a92d-fb79973b3601","name":"Aggregate Reply Users","type":"n8n-nodes-base.aggregate","position":[-880,1080],"parameters":{"options":{},"aggregate":"aggregateAllItemData"},"typeVersion":1},{"id":"c71b7ca6-8245-4262-b2f1-abea511390d6","name":"Reply Users","type":"n8n-nodes-base.set","position":[-660,1160],"parameters":{"options":{},"assignments":{"assignments":[{"id":"9f721cde-2d36-40ee-b7d8-a920695157a9","name":"data","type":"array","value":"={{ $json.data ?? [] }}"}]}},"typeVersion":3.4},{"id":"4b2c452b-4e68-4536-aa58-a85fd586c606","name":"Google Gemini Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[-460,0],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"dSxo6ns5wn658r8N","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"d65b4f27-52ab-4c29-8692-ee2835fddd17","name":"Loop Over Items","type":"n8n-nodes-base.splitInBatches","position":[-1540,780],"parameters":{"options":{}},"typeVersion":3},{"id":"cfb55c7f-a89d-4ce4-8709-31e5e119c6ee","name":"Aggregate3","type":"n8n-nodes-base.set","position":[-1320,580],"parameters":{"mode":"raw","options":{},"jsonOutput":"={{\n{\n  ...$('Split Out1').item.json,\n  replies: $json.replies.filter(reply => reply.ts)\n}\n}}\n"},"typeVersion":3.4},{"id":"8b70e30c-99d5-4086-85aa-e6cfcc7f14e7","name":"Aggregate4","type":"n8n-nodes-base.aggregate","position":[-1100,580],"parameters":{"options":{},"aggregate":"aggregateAllItemData"},"typeVersion":1},{"id":"1cef5853-d301-49cb-9f58-c1a9128b8b33","name":"When Executed by Another Workflow","type":"n8n-nodes-base.executeWorkflowTrigger","position":[-2200,780],"parameters":{"workflowInputs":{"values":[{"name":"action"},{"name":"data","type":"object"}]}},"typeVersion":1.1},{"id":"b30c2433-3bfe-480f-a4bd-8c41900802a2","name":"Switch","type":"n8n-nodes-base.switch","position":[-1980,780],"parameters":{"rules":{"values":[{"outputKey":"users","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"fa924990-9f6e-40c4-aaec-50d4f5927414","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.action }}","rightValue":"users"}]},"renameOutput":true},{"outputKey":"message_replies","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"26ce01b2-9e5b-43e8-926d-9d726c9ca74d","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.action }}","rightValue":"message_replies"}]},"renameOutput":true},{"outputKey":"message_summarize","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"45fd7264-6ac3-4bbd-8a91-c4cfb33b4545","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.action }}","rightValue":"message_summarize"}]},"renameOutput":true}]},"options":{}},"typeVersion":3.2},{"id":"b05735c3-4beb-4a80-8297-85e952e81270","name":"Map Users to Messages","type":"n8n-nodes-base.executeWorkflow","position":[-1520,-160],"parameters":{"mode":"each","options":{},"workflowId":{"__rl":true,"mode":"id","value":"={{ $workflow.id }}"},"workflowInputs":{"value":{"data":"={{ $json }}","action":"users"},"schema":[{"id":"action","type":"string","display":true,"required":false,"displayName":"action","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":"28ed52b2-b0c3-4f19-b394-347c8ff9e323","name":"Get User Info","type":"n8n-nodes-base.set","position":[-880,380],"parameters":{"options":{},"assignments":{"assignments":[{"id":"17344879-1e10-4738-8db0-6e0daddea920","name":"user","type":"object","value":"={{\n{\n  id: $('Get User').item.json.id,\n  team_id: $('Get User').item.json.team_id,\n  name: $('Get User').item.json.name,\n  is_bot: $('Get User').item.json.is_bot\n}\n}}"}]},"includeOtherFields":true},"typeVersion":3.4},{"id":"bbd7c77e-2405-4e63-ae38-f064beafab9c","name":"Fetch Message Replies","type":"n8n-nodes-base.executeWorkflow","position":[-1300,-160],"parameters":{"mode":"each","options":{},"workflowId":{"__rl":true,"mode":"id","value":"={{ $workflow.id }}"},"workflowInputs":{"value":{"data":"={{ $json }}","action":"message_replies"},"schema":[{"id":"action","type":"string","display":true,"removed":false,"required":false,"displayName":"action","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":"edf34e72-04b4-4fed-a3af-42dec1c7ed17","name":"Has ReplyUsers?","type":"n8n-nodes-base.if","position":[-1540,1160],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"813d9fea-9de0-4151-aa45-d38a42f808b8","operator":{"type":"array","operation":"notEmpty","singleValue":true},"leftValue":"={{ $json.replyUsers }}","rightValue":""}]}},"typeVersion":2.2},{"id":"dc9c6cf0-c627-4311-9160-62204e9b67e0","name":"Messages to Items1","type":"n8n-nodes-base.code","position":[-440,1160],"parameters":{"jsCode":"return $('Switch').first().json.data.messages"},"typeVersion":2},{"id":"0b830a49-c77e-41f3-8d70-47a26bfe0a0e","name":"Aggregate Results","type":"n8n-nodes-base.set","position":[-760,-160],"parameters":{"mode":"raw","options":{},"jsonOutput":"={{\n{\n  ...$('Map Users to Messages').item.json,\n  messages: $('Fetch Message Replies').item.json.data\n  .map((message,idx) => ({\n    ...message,\n    summary: $json.data[idx].text,\n  }))\n}\n}}"},"typeVersion":3.4},{"id":"b0c66c7f-0fed-465c-8933-7b803c9b3b64","name":"Team Member Weekly Report Agent","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[-560,-160],"parameters":{"text":"={{\n$json.messages\n  .map((message,idx) =>\n    `${message.userName} (<@${message.userId}>) posted on ${new Date(parseFloat(message.ts) * 1000).format('d MMM')}:\\n> \\\"${message.text}\\\".\\nThe summary of this thread is as follows:\\n${message.summary.replaceAll('\\n', ' ')}`\n  )\n  .join('\\n---\\n')\n}}","messages":{"messageValues":[{"message":"=Your are energetic assistant who produces weekly mini-reports on team members by analysing their slack messages from last week and posts these reports on the following Monday.\nThere has already been some work done to collect and summarise each thread made by the user within the last week.\nYour task is to summarize all the threads by this user and any interactions with other users involved and produce a mini report to share with other team members.\nFocus on wins and challenges.\nAim to motivate and call out any outstanding concerns where appropriate.\nWelcome any new team members who may have joined and say good bye to those who may have left."}]},"promptType":"define"},"typeVersion":1.6},{"id":"e4a487ae-8d71-4fe6-a760-7a0fb95a8fac","name":"Merge with Results","type":"n8n-nodes-base.set","position":[-60,-160],"parameters":{"mode":"raw","options":{},"jsonOutput":"={{\n{\n  ...$('Aggregate Results').item.json,\n  report: $json.text,\n}\n}}"},"typeVersion":3.4},{"id":"06736a5c-7450-406a-ad3a-08a368d1addf","name":"Team Weekly Report Agent","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[160,-160],"parameters":{"text":"={{\n$input.all()\n  .map(item => item.json)\n  .map(item =>\n`user: ${item.user.name} <@${item.user.id}>\nmessage count: ${item.messages.length}\nreport: ${item.report.replaceAll('\\n', ' ')}`\n  ).join('\\n---\\n')\n}}","messages":{"messageValues":[{"message":"=Your are energetic assistant who produces a team-wide weekly report from all activity of all team members in the prior last week and posts this single report on the following Monday.\nThere has already been some work done to collect individual reports from team members.\nYour task is generate a report covering the team to prepare and motivate them for the upcoming week.\nFocus on wins and challenges if available.\nLook out for similar activities between members and make a connection if possible.\nAim to motivate and call out any outstanding concerns where appropriate.\nWelcome any new team members who may have joined and say good bye to those who may have left."}]},"promptType":"define"},"executeOnce":true,"typeVersion":1.6},{"id":"eef36957-9bf0-4be3-95a8-73bbefdc0c85","name":"Google Gemini Chat Model2","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[240,0],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"dSxo6ns5wn658r8N","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"bfa5c99f-cd8f-4d34-9e6d-9ed476c87d22","name":"Post Report in Team Channel","type":"n8n-nodes-base.slack","position":[820,-160],"webhookId":"3613b3ca-fc98-427f-8903-a5996ff7552e","parameters":{"text":"={{ $json.text }}","select":"channel","channelId":{"__rl":true,"mode":"list","value":"C06RS1WPUQ6","cachedResultName":"general"},"otherOptions":{}},"credentials":{"slackApi":{"id":"VfK3js0YdqBdQLGP","name":"Slack account"}},"typeVersion":2.3},{"id":"b9a11c72-de41-4a45-85a0-672cf54ef152","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-2460,-440],"parameters":{"color":7,"width":820,"height":520,"content":"## 1. Fetch All Activity from Last Week\n[Learn more about the Slack node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.slack)\n\nWe'll start by fetching all activity in our team channel over the last 7 days and group them  by the message author. We can do this using the Slack node with a DateTime filter. This will give us the raw data to pick apart and analyse for reporting purposes."},"typeVersion":1},{"id":"8afc048f-ce06-46c3-916f-cbcf14bcfe2b","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-1620,-440],"parameters":{"color":7,"width":760,"height":520,"content":"## 2. Summarise Messages Threads & Conversations\n[Learn more about the Execute Workflow node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow)\n\nWe'll do some more data mining by fetching all replies for each of these top level channel messages. By doing so, we get the full context of the conversation and can hopefully pick up some decisions, discoveries or concerns to add to our report. This data mining does require juggling a lot of \"items\" which becomes hard to manage so we'll use subworkflows to simplify this work.\n\nOnce the data mining is complete, we can summarize each thread with AI and ensure we're capturing only the significant events which are report-worthy."},"typeVersion":1},{"id":"c9a7358c-fbe7-435a-b435-d7b07599bdc6","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-840,-440],"parameters":{"color":7,"width":660,"height":620,"content":"## 3. Generate Activity Reports for Each Team Member\n[Learn more about the Basic LLM node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainllm)\n\nWith our summarized threads which are grouped per user, we can aggregate them and give them to the AI again to generate a weekly report for the team member. This could include their wins, challenges, learnings or decisions - it really is up to you as to what the report looks like.\n\nA fun part of this output is getting to decide the tone of voice and delivery of the report. Don't be a bore and consider adding some personality and flair!"},"typeVersion":1},{"id":"add32ef0-b515-44e6-a234-0a0fa77f4e84","name":"Summarize Message Threads","type":"n8n-nodes-base.executeWorkflow","position":[-1080,-160],"parameters":{"mode":"each","options":{},"workflowId":{"__rl":true,"mode":"id","value":"={{ $workflow.id }}"},"workflowInputs":{"value":{"data":"={{\n{\n  ...$('Map Users to Messages').item.json,\n  messages: $json.data\n}\n}}","action":"message_summarize"},"schema":[{"id":"action","type":"string","display":true,"removed":false,"required":false,"displayName":"action","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":"17f2f45e-2c95-4b3c-b6db-a2881ae88964","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-160,-440],"parameters":{"color":7,"width":680,"height":620,"content":"## 4. Generate Final Report for Whole Team\n[Learn more about the Basic LLM node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainllm)\n\nIn this step, we go one level higher and aggregate all individual team member reports together into a big team report. In this way, the overview can group similar activities and generalise activities in a broader sense. The message output will also be shorter which some may find easier to digest."},"typeVersion":1},{"id":"18cc7fa7-603c-4165-97c6-80d72fd4a9a6","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[540,-440],"parameters":{"color":7,"width":680,"height":620,"content":"## 5. Post Report on Team Channel (on Monday Morning!)\n[Learn more about the Slack node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.slack)\n\nFinally, we can post the weekly report in the team channel. This is a great way to automate quick recaps for the team after the weekend break, get others back on track if they've been away or update client team who may pop in now and again to collaborate."},"typeVersion":1},{"id":"9cd8bdd6-5fc7-4e44-bcd0-058bc5d11335","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-2460,360],"parameters":{"color":7,"width":560,"height":340,"content":"## 5. SubWorkflows\n[Read more about Execute Workflow Trigger](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflowtrigger)\n\nIncorporating Subworkflows into your main workflow is an advanced technique and sometimes necessary if you're working with a lot of nested items or loops.\n\nIn this scenario, we perform quite a few lookups to get the data we need; users, messages and replies, which in template terms would require many loop nodes to string together. However, when you nest loops nodes within loop nodes, item reference becomes difficult to keep track of.\n\nUsing subworkflows, we can break down each loop into a separate execution which handles items and item references in a simpler, linear way. The result is predictable data flow throughout our template. "},"typeVersion":1},{"id":"6f6fc730-5fc8-4dcc-b86d-e3b2f0e792a0","name":"Monday @ 6am","type":"n8n-nodes-base.scheduleTrigger","position":[-2400,-160],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"0 6 * * 1"}]}},"typeVersion":1.2},{"id":"ab94557c-debb-425c-ac83-62e39e43d28b","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-2940,-1380],"parameters":{"width":420,"height":1460,"content":"## Try It Out!\n### This n8n template lets you summarize individual team member activity on slack for the past week and generates a report.\n\nFor remote teams, chat is a crucial communication tool to ensure work gets done but with so many conversations happening at once and in multiple threads, ideas, information and decisions usually live in the moment and get lost just as quickly - and all together forgotten by the weekend!\n\nUsing this template, this doesn't have to be the case. Have AI crawl through last week's activity, summarize all threads and generate a casual and snappy report to bring the team back into focus for the current week. A project manager's dream!\n\n### How it works\n* A scheduled trigger is set to run every Monday at 6am to gather all team channel messages within the last week.\n* Each message thread are grouped by user and data mined for replies.\n* Combined, an AI analyses the raw messages to pull out interesting observations and highlights.\n* The summarized threads of the user are then combined together and passed to another AI agent to generate a higher level overview of their week. These are referred to as the individual reports.\n* Next, all individual reports are summarized together into a team weekly report. This allows understanding of group and similar activities.\n* Finally, the team weekly report is posted back to the channel. The timing is important as it should be the first message of the week and ready for the team to glance over coffee.\n\n### How to use\n* Ideally works best per project and where most of the comms happens on a single channel. Avoid combining channels and instead duplicate this workflow for more channels.\n* You may need to filter for specific team members if you want specific team updates.\n* Customise the report to suit your organisation, team or the channel. You may prefer to be more formal if clients or external stakeholders are also present.\n\n### Requirements\n* Slack for chat platform\n* Gemini for LLM\n\n### Customising this workflow\n* If the slack channel is busy enough already, consider posting the final report to email.\n* Pull in project metrics to include in your report. As extra context, it may be interesting to tie the messages to production performance.\n* Use an AI Agent to query for knowledgebase or tickets relevant to the messages. This may be useful for attaching links or references to add context.\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}],"pinData":{},"connections":{"Filter":{"main":[[{"node":"Simplify Thread Comments","type":"main","index":0}]]},"Switch":{"main":[[{"node":"Get User","type":"main","index":0}],[{"node":"Split Out1","type":"main","index":0}],[{"node":"Map Reply UserIds","type":"main","index":0}]]},"Get User":{"main":[[{"node":"Messages to Items","type":"main","index":0}]]},"Aggregate":{"main":[[{"node":"Get User Info","type":"main","index":0}]]},"Split Out":{"main":[[{"node":"Map Users to Messages","type":"main","index":0}]]},"Aggregate1":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Aggregate2":{"main":[[]]},"Aggregate3":{"main":[[{"node":"Aggregate4","type":"main","index":0}]]},"Aggregate4":{"main":[[]]},"Get Thread":{"main":[[{"node":"Filter","type":"main","index":0}]]},"Split Out1":{"main":[[{"node":"Loop Over Items","type":"main","index":0}]]},"Split Out2":{"main":[[{"node":"Get Reply Users","type":"main","index":0}]]},"Message Ref":{"main":[[{"node":"Get Thread","type":"main","index":0}]]},"Reply Users":{"main":[[{"node":"Messages to Items1","type":"main","index":0}]]},"Monday @ 6am":{"main":[[{"node":"Get Last Week's Messages","type":"main","index":0}]]},"Group By User":{"main":[[{"node":"Split Out","type":"main","index":0}]]},"Get Reply Users":{"main":[[{"node":"Aggregate Reply Users","type":"main","index":0}]]},"Has ReplyUsers?":{"main":[[{"node":"Split Out2","type":"main","index":0}],[{"node":"Reply Users","type":"main","index":0}]]},"Loop Over Items":{"main":[[{"node":"Aggregate3","type":"main","index":0}],[{"node":"Message Ref","type":"main","index":0}]]},"Simplify Message":{"main":[[{"node":"Aggregate","type":"main","index":0}]]},"Aggregate Results":{"main":[[{"node":"Team Member Weekly Report Agent","type":"main","index":0}]]},"Map Reply UserIds":{"main":[[{"node":"Has ReplyUsers?","type":"main","index":0}]]},"Messages to Items":{"main":[[{"node":"Simplify Message","type":"main","index":0}]]},"Summarise Threads":{"main":[[{"node":"Aggregate2","type":"main","index":0}]]},"Merge with Results":{"main":[[{"node":"Team Weekly Report Agent","type":"main","index":0}]]},"Messages to Items1":{"main":[[{"node":"Summarise Threads","type":"main","index":0}]]},"Aggregate Reply Users":{"main":[[{"node":"Reply Users","type":"main","index":0}]]},"Fetch Message Replies":{"main":[[{"node":"Summarize Message Threads","type":"main","index":0}]]},"Map Users to Messages":{"main":[[{"node":"Fetch Message Replies","type":"main","index":0}]]},"Get Last Week's Messages":{"main":[[{"node":"Group By User","type":"main","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"Summarise Threads","type":"ai_languageModel","index":0}]]},"Simplify Thread Comments":{"main":[[{"node":"Aggregate1","type":"main","index":0}]]},"Team Weekly Report Agent":{"main":[[{"node":"Post Report in Team Channel","type":"main","index":0}]]},"Google Gemini Chat Model1":{"ai_languageModel":[[{"node":"Team Member Weekly Report Agent","type":"ai_languageModel","index":0}]]},"Google Gemini Chat Model2":{"ai_languageModel":[[{"node":"Team Weekly Report Agent","type":"ai_languageModel","index":0}]]},"Summarize Message Threads":{"main":[[{"node":"Aggregate Results","type":"main","index":0}]]},"Team Member Weekly Report Agent":{"main":[[{"node":"Merge with Results","type":"main","index":0}]]},"When Executed by Another Workflow":{"main":[[{"node":"Switch","type":"main","index":0}]]}}}


name: Summarise MS Teams Channel Activity for Weekly Reports with AI
author_name: Jimleuk
author_username: jimleuk
categories: []
created_at: 2025-05-10T15:05:32.396Z
updated_at: 2025-05-10T15:05:32.396Z
url: https://n8n.io/workflows/3971
scraped_at: 2025-06-19 22:50:23
description:
  This n8n template lets you summarize individual team member activity on MS Teams for the past week and generates a report.

  For remote teams, chat is a crucial communication tool to ensure work gets done but with so many conversations happening at once and in multiple threads, ideas, information and decisions usually live in the moment and get lost just as quickly - and all together forgotten by the weekend!

  Using this template, this doesn't have to be the case. Have AI crawl through last week's activity, summarize all messages and replies and generate a casual and snappy report to bring the team back into focus for the current week. A project manager's dream!

  How it works
  A scheduled trigger is set to run every Monday at 6am to gather all team channel messages within the last week.
  Messages are grouped by user.
  AI analyses the raw messages and replies to pull out interesting observations and highlights. This is referred to as the individual reports.
  All individual reports are then combined and summarized together into what becomes the team weekly report. This allows understanding of group and similar activities.
  Finally, the team weekly report is posted back to the channel. The timing is important as it should be the first message of the week and ready for the team to glance over coffee.

  How to use
  Ideally works best per project and where most of the comms happens on a single channel. Avoid combining channels and instead duplicate this workflow for more channels.
  You may need to filter for specific team members if you want specific team updates.
  Customise the report to suit your organisation, team or the channel. You may prefer to be more formal if clients or external stakeholders are also present.

  Requirements
  MS Teams for chat platform
  OpenAI for LLM

  Customising this workflow
  If the teams channel is busy enough already, consider posting the final report to email.
  Pull in project metrics to include in your report. As extra context, it may be interesting to tie the messages to production performance.
  Use an AI Agent to query for knowledgebase or tickets relevant to the messages. This may be useful for attaching links or references to add context.

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

workflow_json:
  {"meta":{"instanceId":"408f9fb9940c3cb18ffdef0e0150fe342d6e655c3a9fac21f0f644e8bedabcd9","templateCredsSetupCompleted":true},"nodes":[{"id":"ee39f797-6f6f-4a62-9cf1-0c95b47baf23","name":"Schedule Trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-160,0],"parameters":{"rule":{"interval":[{}]}},"typeVersion":1.2},{"id":"c1b9fadc-586b-4edf-a19a-6995479d4de5","name":"Fetch Latest Channel Messages","type":"n8n-nodes-base.microsoftTeams","position":[60,0],"webhookId":"b36a534a-1bca-4c3d-ab25-777ca98fba1a","parameters":{"teamId":{"__rl":true,"mode":"id","value":"=fc62d6a3-eaba-430f-b451-3c3107751ba0"},"resource":"channelMessage","channelId":{"__rl":true,"mode":"id","value":"=19:NQuQMYvvtC9DcTEQs1Vul1Nm1xIXnRmznAwov7MuNZ81@thread.tacv2"},"operation":"getAll"},"credentials":{"microsoftTeamsOAuth2Api":{"id":"AUH9lDgO5KTl2J6q","name":"Microsoft Teams account"}},"typeVersion":2},{"id":"1be03962-5028-47a8-8deb-3c59c121df01","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[920,140],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4.1-mini","cachedResultName":"gpt-4.1-mini"},"options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1.2},{"id":"04a75b1c-685f-4264-ade7-cb2778fc7d4f","name":"Team Member Weekly Report Agent","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[820,0],"parameters":{"text":"=## User\nDisplayName: {{ $json.user.displayName }}\n\n## Messages\n{{\nArray.from($json.messages)\n.map(msg => {\n  return [\n    `Type: Message`,\n    `Posted: ${msg.createdDateTime}`,\n    `Message: ${msg.body.content.replaceAll('\\n', ' ')}`,\n    msg.parent ? `In Reply To: ${msg.parent.from.user.displayName} said \"${msg.parent.body.content.replace('\\n', ' ')}\"` : ''\n  ].join('\\n')\n}).join('---\\n')\n}}","messages":{"messageValues":[{"message":"=Your are energetic assistant who produces weekly mini-reports on team members by analysing their slack messages from last week and posts these reports on the following Monday.\nThere has already been some work done to collect and summarise each thread made by the user within the last week.\nYour task is to summarize all the threads by this user and any interactions with other users involved and produce a mini report to share with other team members.\nFocus on wins and challenges.\nAim to motivate and call out any outstanding concerns where appropriate.\nWelcome any new team members who may have joined and say good bye to those who may have left."}]},"promptType":"define"},"typeVersion":1.6},{"id":"919347aa-cd48-42ff-9504-dd66c5b18caa","name":"Merge Report With User Data","type":"n8n-nodes-base.set","position":[1200,0],"parameters":{"mode":"raw","options":{},"jsonOutput":"={{\n{\n  ...$('Groups to Items').item.json,\n  report: $json.text\n}\n}}"},"typeVersion":3.4},{"id":"67c23cf0-9af6-4a89-94c0-7a3e01230b2f","name":"OpenAI Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[1820,140],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4.1-mini","cachedResultName":"gpt-4.1-mini"},"options":{}},"credentials":{"openAiApi":{"id":"8gccIjcuf3gvaoEr","name":"OpenAi account"}},"typeVersion":1.2},{"id":"65111f1b-42c7-4657-9512-e740d75bdbdc","name":"Reports to Single List","type":"n8n-nodes-base.aggregate","position":[1500,0],"parameters":{"options":{},"aggregate":"aggregateAllItemData"},"typeVersion":1},{"id":"82a90342-cc4d-4d80-9ff6-83cab22861f4","name":"Team Weekly Report Agent","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[1720,0],"parameters":{"text":"={{\n$input.first().json.data\n  .map(item =>\n`user: ${item.user.displayName} <${item.user.id}>\nmessage count: ${item.messages.length}\nreport: ${item.report.replaceAll('\\n', ' ')}`\n  )\n  .join('\\n---\\n')\n}}","messages":{"messageValues":[{"message":"=Your are energetic assistant who produces a team-wide weekly report from all activity of all team members in the prior last week and posts this single report on the following Monday.\nThere has already been some work done to collect individual reports from team members.\nYour task is generate a report covering the team to prepare and motivate them for the upcoming week.\nFocus on wins and challenges if available.\nLook out for similar activities between members and make a connection if possible.\nAim to motivate and call out any outstanding concerns where appropriate.\nWelcome any new team members who may have joined and say good bye to those who may have left.\nFormat the report as markdown.\nDo not sign off on the report."}]},"promptType":"define"},"typeVersion":1.6},{"id":"464a925f-eb06-4b59-a262-ca336506de15","name":"Markdown to HTML","type":"n8n-nodes-base.markdown","position":[2300,0],"parameters":{"mode":"markdownToHtml","options":{},"markdown":"={{ $json.text }}","destinationKey":"html"},"typeVersion":1},{"id":"ecb047a7-5d52-4e87-8d0e-c9c17489cddc","name":"Send Report to Channel","type":"n8n-nodes-base.microsoftTeams","position":[2540,0],"webhookId":"b36a534a-1bca-4c3d-ab25-777ca98fba1a","parameters":{"teamId":{"__rl":true,"mode":"id","value":"=fc62d6a3-eaba-430f-b451-3c3107751ba0","__regex":"^([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})"},"message":"={{ $json.html }}","options":{"includeLinkToWorkflow":false},"resource":"channelMessage","channelId":{"__rl":true,"mode":"id","value":"=19:NQuQMYvvtC9DcTEQs1Vul1Nm1xIXnRmznAwov7MuNZ81@thread.tacv2"},"contentType":"html"},"credentials":{"microsoftTeamsOAuth2Api":{"id":"AUH9lDgO5KTl2J6q","name":"Microsoft Teams account"}},"typeVersion":2},{"id":"e1d371c8-9069-4a33-a450-78055769931b","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-220,-240],"parameters":{"color":7,"width":700,"height":540,"content":"## 1. Fetch All Channel Messages from Last Week\n[Learn more about the MS Teams node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.microsoftteams)\n\nWe'll start by fetching all activity in our team channel over the last 7 days and group them  by the message author. We can do this using the MS Teams node. This will give us the raw data to pick apart and analyse for reporting purposes."},"typeVersion":1},{"id":"77aff845-5226-4023-a2da-afb2021a08ed","name":"Group Messages By UserId","type":"n8n-nodes-base.code","position":[280,0],"parameters":{"jsCode":"const messages = $input.all().map(item => item.json);\n\nconst groupByUserId = messages.reduce((acc,msg) => {\n  return {\n    ...acc,\n    [msg.from.user.id]: acc[msg.from.user.id]\n      ? acc[msg.from.user.id].concat(msg)\n      : [msg]\n  }\n}, {});\n\nconst output = Object.keys(groupByUserId).map(userId => {\n  const userMessages = groupByUserId[userId];\n  for (let i=0,j=userMessages.length;i<j;i++) {\n    if (userMessages[i].replyToId) {\n      userMessages[i].parent = messages.find(msg => msg.id === userMessages[i].replyToId);\n    }\n  }\n  return {\n    user: userMessages[0].from.user,\n    messages: userMessages\n  };\n});\n\nreturn { output };"},"typeVersion":2},{"id":"ee415463-a7e2-43dd-abfa-4050cc230452","name":"Groups to Items","type":"n8n-nodes-base.splitOut","position":[600,0],"parameters":{"options":{},"fieldToSplitOut":"output"},"typeVersion":1},{"id":"8d4c7621-3c04-4fbe-bbee-b7dade2ab837","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[520,-240],"parameters":{"color":7,"width":860,"height":540,"content":"## 2. Generate Activity Reports for Each Team Member\n[Learn more about the Basic LLM node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainllm)\n\nWith our summarized threads which are grouped per user, we can aggregate them and give them to the AI again to generate a weekly report for the team member. This could include their wins, challenges, learnings or decisions - it really is up to you as to what the report looks like. A fun part of this output is getting to decide the tone of voice and delivery of the report. Don't be a bore and consider adding some personality and flair!"},"typeVersion":1},{"id":"22f3e375-201d-4a66-b1e0-592bbeb12eac","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[1420,-240],"parameters":{"color":7,"width":680,"height":540,"content":"## 3. Generate Final Report for Whole Team\n[Learn more about the Basic LLM node](https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainllm)\n\nIn this step, we go one level higher and aggregate all individual team member reports together into a big team report. In this way, the overview can group similar activities and generalise activities in a broader sense. The message output will also be shorter which some may find easier to digest."},"typeVersion":1},{"id":"873c2510-cf01-464b-b84e-936bd1c4d7a7","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[2140,-240],"parameters":{"color":7,"width":680,"height":540,"content":"## 4. Post Report on Team Channel (on Monday Morning!)\n[Learn more about the Markdown node](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.markdown)\n\nFinally, we can post the weekly report in the team channel. This is a great way to automate quick recaps for the team after the weekend break, get others back on track if they've been away or update client team who may pop in now and again to collaborate."},"typeVersion":1},{"id":"4882c210-fec8-4b8e-b114-0b6d889ed917","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-680,-960],"parameters":{"width":420,"height":1400,"content":"## Try It Out!\n### This n8n template lets you summarize individual team member activity on MS Teams for the past week and generates a report.\n\nFor remote teams, chat is a crucial communication tool to ensure work gets done but with so many conversations happening at once and in multiple threads, ideas, information and decisions usually live in the moment and get lost just as quickly - and all together forgotten by the weekend!\n\nUsing this template, this doesn't have to be the case. Have AI crawl through last week's activity, summarize all messages and replies and generate a casual and snappy report to bring the team back into focus for the current week. A project manager's dream!\n\n### How it works\n* A scheduled trigger is set to run every Monday at 6am to gather all team channel messages within the last week.\n* Messages are grouped by user.\n* AI analyses the raw messages and replies to pull out interesting observations and highlights. This is referred to as the individual reports.\n* All individual reports are then combined and summarized together into what becomes the team weekly report. This allows understanding of group and similar activities.\n* Finally, the team weekly report is posted back to the channel. The timing is important as it should be the first message of the week and ready for the team to glance over coffee.\n\n### How to use\n* Ideally works best per project and where most of the comms happens on a single channel. Avoid combining channels and instead duplicate this workflow for more channels.\n* You may need to filter for specific team members if you want specific team updates.\n* Customise the report to suit your organisation, team or the channel. You may prefer to be more formal if clients or external stakeholders are also present.\n\n### Requirements\n* MS Teams for chat platform\n* OpenAI for LLM\n\n### Customising this workflow\n* If the teams channel is busy enough already, consider posting the final report to email.\n* Pull in project metrics to include in your report. As extra context, it may be interesting to tie the messages to production performance.\n* Use an AI Agent to query for knowledgebase or tickets relevant to the messages. This may be useful for attaching links or references to add context.\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}],"pinData":{},"connections":{"Groups to Items":{"main":[[{"node":"Team Member Weekly Report Agent","type":"main","index":0}]]},"Markdown to HTML":{"main":[[{"node":"Send Report to Channel","type":"main","index":0}]]},"Schedule Trigger":{"main":[[{"node":"Fetch Latest Channel Messages","type":"main","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"Team Member Weekly Report Agent","type":"ai_languageModel","index":0}]]},"OpenAI Chat Model1":{"ai_languageModel":[[{"node":"Team Weekly Report Agent","type":"ai_languageModel","index":0}]]},"Reports to Single List":{"main":[[{"node":"Team Weekly Report Agent","type":"main","index":0}]]},"Group Messages By UserId":{"main":[[{"node":"Groups to Items","type":"main","index":0}]]},"Team Weekly Report Agent":{"main":[[{"node":"Markdown to HTML","type":"main","index":0}]]},"Merge Report With User Data":{"main":[[{"node":"Reports to Single List","type":"main","index":0}]]},"Fetch Latest Channel Messages":{"main":[[{"node":"Group Messages By UserId","type":"main","index":0}]]},"Team Member Weekly Report Agent":{"main":[[{"node":"Merge Report With User Data","type":"main","index":0}]]}}}


name: Personalized AI Tech Newsletter Using RSS, OpenAI and Gmail
author_name: Miha
author_username: miha
categories: []
created_at: 2025-05-11T19:47:23.634Z
updated_at: 2025-05-11T19:47:23.634Z
url: https://n8n.io/workflows/3986
scraped_at: 2025-06-19 22:48:43
description:
  Combine Tech News in a Personalized Weekly Newsletter

  This n8n template automates the collection, storage, and summarization of technology news from top sites, turning it into a concise, personalized weekly newsletter.

  If you like staying informed but want to reduce daily distractions, this workflow is perfect for you. It leverages RSS feeds, vector databases, and LLMs to read and curate tech content on your behalf—so you only receive what truly matters.

  How it works

  A daily scheduled trigger fetches articles from multiple popular tech RSS feeds like Wired, TechCrunch, and The Verge.
  Fetched articles are:

    Normalized to extract titles, summaries, and publish dates.
    Converted to vector embeddings via OpenAI and stored in memory for fast semantic querying.
  A weekly scheduled trigger activates the AI summarization flow:

    The AI is provided with your interests (e.g., AI, games, gadgets) and the desired number of items (e.g., 15).
    It queries the vector store to retrieve relevant articles and summarizes the most newsworthy stories.
    The summary is converted into a clean, email-friendly format and sent to your inbox.

  How to use

  Connect your OpenAI and Gmail accounts to n8n.
  Customize the list of RSS feeds in the “Set Tech News RSS Feeds” node.
  Update your interests and number of desired news items in the “Your Topics of Interest” node.
  Activate the workflow and let the automation run on schedule.

  Requirements

  OpenAI** credentials for embeddings and summarization
  Gmail** (or another email service) for sending the newsletter

  Customizing this workflow

  Want to use different sources? Swap in your own RSS feeds, or use an API-based news aggregator.
  Replace the in-memory vector store with Pinecone, Weaviate, or another persistent vector DB for longer-term storage.
  Adjust the agent's summarization style to suit internal updates, industry-specific briefings, or even entertainment recaps.
  Prefer chat over email? Replace the email node with a Telegram bot to receive your personalized tech newsletter directly in a Telegram chat.

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

workflow_json:
  {"id":"ni6SfqC3kthAlPtX","meta":{"instanceId":"a2eaba9e45ad7aab18b25cf863df1e910fb6dd3b85279bde97d9bae4a72f6862","templateCredsSetupCompleted":true},"name":"Personalized AI Tech Newsletter Using RSS, OpenAI and Gmail","tags":[],"nodes":[{"id":"5cc6bfe1-dbaa-4196-ac52-27e3d5b7e91d","name":"Split Out","type":"n8n-nodes-base.splitOut","position":[420,-300],"parameters":{},"typeVersion":1},{"id":"c696de41-aeb1-4e2c-9e7e-8b04f7800bdb","name":"Embeddings OpenAI","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[960,-100],"parameters":{},"typeVersion":1.2},{"id":"4b127a8f-14b3-4a0e-86f6-3157c59bc09c","name":"Default Data Loader","type":"@n8n/n8n-nodes-langchain.documentDefaultDataLoader","position":[1120,-140],"parameters":{},"typeVersion":1},{"id":"c32d87cd-28ee-4b28-ad53-43320169b6df","name":"Recursive Character Text Splitter","type":"@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter","position":[1260,0],"parameters":{},"typeVersion":1},{"id":"c912148b-1142-4713-9769-1588ff308c62","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[400,520],"parameters":{},"typeVersion":1.2},{"id":"ba7aef6b-efec-4c35-a9d6-b2b8afb6b6c4","name":"Get Articles Daily","type":"n8n-nodes-base.scheduleTrigger","position":[-20,-300],"parameters":{},"typeVersion":1.2},{"id":"0827bf1b-1322-4e4a-8c5b-0da90382b202","name":"Send Weekly Summary","type":"n8n-nodes-base.scheduleTrigger","position":[-40,360],"parameters":{},"typeVersion":1.2},{"id":"b1625ec0-fd2f-4098-ba79-1f522123cb86","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-100,-460],"parameters":{"content":""},"typeVersion":1},{"id":"7edbdba1-43ac-4754-91ae-d506ee38e8ff","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-100,200],"parameters":{"content":""},"typeVersion":1},{"id":"e166715b-f579-4d22-bf2f-9318e4e86f2a","name":"News reader AI","type":"@n8n/n8n-nodes-langchain.agent","position":[420,300],"parameters":{},"typeVersion":1.9},{"id":"c88c6c60-493e-41cf-b08d-3eef48e7cbc4","name":"Send Newsletter","type":"n8n-nodes-base.gmail","position":[1020,360],"webhookId":"0de8b6e8-8611-48a9-ba25-1d023698f577","parameters":{},"typeVersion":2.1},{"id":"8e303102-f68c-4cf8-a2bb-4538830610e6","name":"Convert Response to an Email-Friendly Format","type":"n8n-nodes-base.markdown","position":[780,300],"parameters":{},"typeVersion":1},{"id":"3f90c79c-a04d-4537-b426-33900acfcb8a","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[120,300],"parameters":{"content":""},"typeVersion":1},{"id":"de315b7c-065c-45a7-be50-5d7a4eedeeaf","name":"Your topics of interest","type":"n8n-nodes-base.set","position":[180,360],"parameters":{},"typeVersion":3.4},{"id":"8a1d6ac3-6fda-4916-a021-3d5db7d413e0","name":"Store News Articles","type":"@n8n/n8n-nodes-langchain.vectorStoreInMemory","position":[1080,-300],"parameters":{},"typeVersion":1.1},{"id":"b7fd5c59-3ed7-4706-bdd7-a62c62cd65af","name":"Set Tech News RSS Feeds","type":"n8n-nodes-base.set","position":[200,-300],"parameters":{},"typeVersion":3.4},{"id":"77f5f3bc-8ecd-481a-a570-6e49e4fda01b","name":"Read RSS News Feeds","type":"n8n-nodes-base.rssFeedRead","position":[640,-300],"parameters":{},"typeVersion":1.1},{"id":"540f55b3-10d1-4f7e-bbdf-793ae6524fd7","name":"Get News Articles","type":"@n8n/n8n-nodes-langchain.vectorStoreInMemory","position":[540,500],"parameters":{},"typeVersion":1.1},{"id":"f5e37288-ef4c-41ea-87bd-1e9ee1e9ab0f","name":"Embeddings OpenAI2","type":"@n8n/n8n-nodes-langchain.embeddingsOpenAi","position":[740,620],"parameters":{},"typeVersion":1.2},{"id":"f6e050de-8dc1-41dd-a18f-225a2f5f68ad","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[140,-360],"parameters":{"content":""},"typeVersion":1},{"id":"4d773ce7-cbca-4568-bd40-0f9914e835bb","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-580,-460],"parameters":{"content":""},"typeVersion":1},{"id":"796c2a13-c168-4bc9-b79b-fc80c31274c1","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[900,580],"parameters":{"content":""},"typeVersion":1},{"id":"4bd264b8-b088-413d-b44b-dae3b7cc3e77","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[960,300],"parameters":{"content":""},"typeVersion":1},{"id":"6d2b402d-22e0-4cc5-a070-8b4169f18a99","name":"Set and Normalize Fields","type":"n8n-nodes-base.set","position":[860,-300],"parameters":{},"typeVersion":3.4}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"9b875084-83f0-43e6-968a-caec8fb29d7b","connections":{"Split Out":{"main":[[{"node":"Read RSS News Feeds","type":"main","index":0}]]},"News reader AI":{"main":[[{"node":"Convert Response to an Email-Friendly Format","type":"main","index":0}]]},"Send Newsletter":{"main":[[]]},"Embeddings OpenAI":{"ai_embedding":[[{"node":"Store News Articles","type":"ai_embedding","index":0}]]},"Get News Articles":{"ai_tool":[[{"node":"News reader AI","type":"ai_tool","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"News reader AI","type":"ai_languageModel","index":0}]]},"Embeddings OpenAI2":{"ai_embedding":[[{"node":"Get News Articles","type":"ai_embedding","index":0}]]},"Get Articles Daily":{"main":[[{"node":"Set Tech News RSS Feeds","type":"main","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"Store News Articles","type":"ai_document","index":0}]]},"Read RSS News Feeds":{"main":[[{"node":"Set and Normalize Fields","type":"main","index":0}]]},"Send Weekly Summary":{"main":[[{"node":"Your topics of interest","type":"main","index":0}]]},"Set Tech News RSS Feeds":{"main":[[{"node":"Split Out","type":"main","index":0}]]},"Your topics of interest":{"main":[[{"node":"News reader AI","type":"main","index":0}]]},"Set and Normalize Fields":{"main":[[{"node":"Store News Articles","type":"main","index":0}]]},"Recursive Character Text Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader","type":"ai_textSplitter","index":0}]]},"Convert Response to an Email-Friendly Format":{"main":[[{"node":"Send Newsletter","type":"main","index":0}]]}}}


name: GitLab Merge Request Review & Risk Analysis with Claude/GPT AI
author_name: Vishal Kumar
author_username: vishalquantana
categories: []
created_at: 2025-05-12T11:59:11.770Z
updated_at: 2025-05-12T11:59:11.770Z
url: https://n8n.io/workflows/3997
scraped_at: 2025-06-19 22:49:58
description:
  Trigger

  The workflow runs when a GitLab Merge Request (MR) is created or updated.

  Extract & Analyze

  It retrieves the code diff and sends it to Claude AI or GPT-4o for risk assessment and issue detection.

  Generate Report

  AI produces a structured summary with:
  Risk levels
  Identified issues
  Recommendations
  Test cases

  Notify Developers

  The report is:
  Emailed to developers and QA teams
  Posted as a comment on the GitLab MR

  Setup Guide

  Connect GitLab
  Add GitLab API credentials
  Select repositories to track

  Configure AI Analysis
  Enter Anthropic (Claude) or OpenAI (GPT-4o) API key

  Set Up Notifications
  Add Gmail credentials
  Update the email distribution list

  Test & Automate
  Create a test MR to verify analysis and email delivery

  Key Benefits

  Automated Code Review** – AI-driven risk assessment and recommendations
  Security & Compliance** – Identifies vulnerabilities before code is merged
  Integration with GitLab CI/CD** – Works within existing DevOps workflows
  Improved Collaboration** – Keeps developers and QA teams informed

  Developed by Quantana, an AI-powered automation and software development company.

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.gmail","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.lmChatAnthropic","@n8n/n8n-nodes-langchain.outputParserAutofixing","@n8n/n8n-nodes-langchain.outputParserStructured"]

workflow_json:
  {"id":"jzcvnlV8g6aseE4A","meta":{"instanceId":"1abe0e4c2be794795d12bf72aa530a426a6f87aabad209ed6619bcaf0f666fb0","templateCredsSetupCompleted":true},"name":"GitLab MR Auto-Review & Risk Assessment","tags":[{"id":"DOZBZVy35P0wB50k","name":"Quality Assurance (QA)","createdAt":"2025-02-04T06:46:12.267Z","updatedAt":"2025-02-04T06:46:12.267Z"},{"id":"ML7fy627V46ocsUS","name":"Development","createdAt":"2025-02-04T06:46:44.236Z","updatedAt":"2025-02-04T06:46:44.236Z"},{"id":"fX8hRnEv4D8sLSzF","name":"OpenAI","createdAt":"2025-01-09T09:18:12.757Z","updatedAt":"2025-01-09T09:18:12.757Z"},{"id":"xBTtGefXwPc4Bib6","name":"Engineering","createdAt":"2025-02-04T06:47:02.932Z","updatedAt":"2025-02-04T06:47:02.932Z"},{"id":"yy04JQqCaXepPdSa","name":"Project Management","createdAt":"2024-10-30T18:27:57.309Z","updatedAt":"2024-10-30T18:27:57.309Z"},{"id":"zJaZorWWcGpTp35U","name":"DevOps","createdAt":"2025-01-03T12:19:34.273Z","updatedAt":"2025-01-03T12:19:34.273Z"}],"nodes":[{"id":"a82f2b02-538b-4531-921c-d25f1edb97ef","name":"Extract Diff","type":"n8n-nodes-base.httpRequest","position":[860,320],"parameters":{"url":"=     https://gitlab.com/api/v4/projects/{{ encodeURIComponent($json.body.project.path_with_namespace) }}/merge_requests/{{ $json.body.object_attributes.iid }}/changes","options":{},"jsonHeaders":"{\n  \"Authorization\": \"Bearer glpat-xxxxxxxxxxxxxxxxxxxxxxxxxxxx\"\n}","sendHeaders":true,"specifyHeaders":"json"},"typeVersion":4.2},{"id":"cd028c77-23e7-46d6-964d-af5afe468176","name":"Distribution List Generator","type":"n8n-nodes-base.code","position":[2040,160],"parameters":{"jsCode":"const ProjectLeads = {\n  \"alpha_backend\": {\n    \"dev\": [\"dev1@example.com\", \"dev2@example.com\"],\n    \"qa\": [\"qa1@example.com\", \"qa2@example.com\"]\n  },\n  \"beta_webapp\": {\n    \"dev\": [\"dev3@example.com\", \"dev4@example.com\"],\n    \"qa\": [\"qa3@example.com\", \"qa4@example.com\"]\n  },\n  \"gamma_mobile\": {\n    \"dev\": [\"dev5@example.com\", \"dev6@example.com\"],\n    \"qa\": [\"qa5@example.com\", \"qa6@example.com\", \"qa7@example.com\"]\n  },\n  \"delta_api\": {\n    \"dev\": [\"dev7@example.com\", \"dev8@example.com\", \"dev9@example.com\"],\n    \"qa\": [\"qa8@example.com\", \"qa9@example.com\", \"qa10@example.com\"]\n  },\n  \"epsilon_service\": {\n    \"dev\": [\"dev10@example.com\"],\n    \"qa\": [\"qa11@example.com\", \"qa12@example.com\"]\n  },\n  \"zeta_scraper\": {\n    \"dev\": [\"dev11@example.com\"],\n    \"qa\": [\"qa13@example.com\", \"qa14@example.com\"]\n  },\n  \"theta_ui\": {\n    \"dev\": [\"dev12@example.com\", \"dev13@example.com\"],\n    \"qa\": [\"qa15@example.com\", \"qa16@example.com\"]\n  },\n  \"iota_backend\": {\n    \"dev\": [\"dev14@example.com\", \"dev15@example.com\"],\n    \"qa\": [\"qa17@example.com\", \"qa18@example.com\"]\n  },\n  \"kappa_admin\": {\n    \"dev\": [\"dev16@example.com\", \"dev17@example.com\"],\n    \"qa\": [\"qa19@example.com\", \"qa20@example.com\"]\n  }\n};\n\n// Define the GlobalList\nconst GlobalList = [\n  \"admin1@example.com\",\n  \"admin2@example.com\",\n  \"admin3@example.com\"\n];\n\n// Retrieve the project name from the input data and convert it to lowercase\nconst fullName = $('Merge').first().json.body.project.path_with_namespace.toLowerCase();\nconst projectName = fullName.split('/')[1];\n\nlet emails = [];\n\nif (projectName && ProjectLeads[projectName]) {\n  // Extract the emails for the given project\n  const projectEmails = [\n    ...ProjectLeads[projectName].dev,\n    ...ProjectLeads[projectName].qa\n  ];\n\n  // Combine project-specific emails with GlobalList\n  emails = [...projectEmails, ...GlobalList];\n} else {\n  // Default to GlobalList only if project name is not found or is undefined\n  emails = [...GlobalList];\n}\n\n// Handle sender email replacement\nconst senderemail = $('Merge').first().json.body.object_attributes.last_commit.author.email;\nconst oldEmail = \"86149715+user@users.noreply.github.com\";\nconst newEmail = \"user@example.com\";\nconst senderEmail = senderemail.replace(oldEmail, newEmail);\n\n// Add senderEmail to emails list\nemails.push(senderEmail);\n\n// Remove duplicate emails\nemails = [...new Set(emails)];\n\n// Join all emails into a single string\nconst emailsString = emails.join(\", \");\n\n// Return the result\nreturn {\n  json: {\n    emails: emailsString\n  }\n};\n"},"typeVersion":2},{"id":"922c9f5f-2db2-4034-8491-33208f04e580","name":"If Some Change","type":"n8n-nodes-base.if","position":[1100,320],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"3c3e0e8b-7469-4394-ab99-a9ac5053197a","operator":{"type":"array","operation":"lengthGt","rightType":"number"},"leftValue":"={{ $json.changes }}","rightValue":0}]},"looseTypeValidation":true},"typeVersion":2.2},{"id":"e41fc6b0-ccc7-46c9-9667-79b199aaefc8","name":"Merge","type":"n8n-nodes-base.merge","position":[600,320],"parameters":{},"executeOnce":true,"typeVersion":3},{"id":"1bf7f593-a7d9-48f5-be20-d73e97b030bb","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[1400,300],"parameters":{"text":"={\n  \"model\": \"claude-3-5-haiku-20241022\",\n  \"max_tokens\": 1000,\n  \"temperature\": 0.7,\n  \"tools\": [\n    {\n      \"name\": \"record_summary\",\n      \"description\": \"Record a structured summary of a git diff using well-defined JSON.\",\n      \"input_schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"RiskLevel\": {\n            \"type\": \"string\",\n            \"description\": \"Overall risk assessment of the changes: High/Medium/Low.\"\n          },\n          \"Summary\": {\n            \"type\": \"string\",\n            \"description\": \"One-line summary of the git diff analysis\"\n          },\n          \"Recommendations\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"object\",\n              \"properties\": {\n                \"Recommendation\": {\n                  \"type\": \"string\",\n                  \"description\": \"Specific recommendation in HTML format.\"\n                },\n                \"CodeSnippet\": {\n                  \"type\": \"string\",\n                  \"description\": \"Relevant code full snippet formatted in HTML.\"\n                }\n              },\n              \"required\": [\"Recommendation\", \"CodeSnippet\"]\n            }\n          },\n          \"Issues\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"object\",\n              \"properties\": {\n                \"File\": {\n                  \"type\": \"string\",\n                  \"description\": \"HTML-formatted name of the file where the issue exists.\"\n                },\n                \"PotentialIssue\": {\n                  \"type\": \"string\",\n                  \"description\": \"HTML-formatted description of the issue.\"\n                },\n                \"Severity\": {\n                  \"type\": \"string\",\n                  \"description\": \"Severity of the issue: High/Medium/Low in HTML.\"\n                }\n              },\n              \"required\": [\"File\", \"PotentialIssue\", \"Severity\"]\n            }\n          },\n          \"URL\": {\n            \"type\": \"string\",\n            \"description\": \"Link to the repository in HTML.\"\n          },\n          \"DiffTable\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"FileName\": {\n                \"type\": \"string\",\n                \"description\": \"HTML-formatted name of the file.\"\n              },\n              \"Changes\": {\n                \"type\": \"array\",\n                \"items\": {\n                  \"type\": \"object\",\n                  \"properties\": {\n                    \"Line\": {\n                      \"type\": \"string\",\n                      \"description\": \"HTML-formatted line number.\"\n                    },\n                    \"Before\": {\n                      \"type\": \"string\",\n                      \"description\": \"Code before the change formatted in HTML.\"\n                    },\n                    \"After\": {\n                      \"type\": \"string\",\n                      \"description\": \"Code after the change formatted in HTML.\"\n                    }\n                  },\n                  \"required\": [\"Line\", \"Before\", \"After\"]\n                }\n              }\n            }\n          },\n          \"TestCases\": {\n            \"type\": \"array\",\n            \"description\": \"List of test cases the QA team must check.\",\n            \"items\": {\n              \"type\": \"object\",\n              \"properties\": {\n                \"TestFor\": {\n                  \"type\": \"string\",\n                  \"description\": \"Description of the functionality or area to test.\"\n                },\n                \"Steps\": {\n                  \"type\": \"string\",\n                  \"description\": \"HTML-formatted steps to test the functionality.\"\n                },\n                \"ExpectedOutcome\": {\n                  \"type\": \"string\",\n                  \"description\": \"HTML-formatted description of the expected result of the test.\"\n                }\n              },\n              \"required\": [\"TestFor\", \"Steps\", \"ExpectedOutcome\"]\n            }\n          }\n        },\n        \"required\": [\"RiskLevel\", \"Summary\", \"Recommendations\", \"Issues\", \"URL\", \"DiffTable\", \"TestCases\"]\n      }\n    }\n  ],\n  \"tool_choice\": {\n    \"type\": \"tool\",\n    \"name\": \"record_summary\"\n  },\n  \"messages\": [\n    {\n      \"role\": \"user\",\n      \"content\": [\n        {\n          \"type\": \"text\",\n          \"text\": \"Analyze the following git diff, highlight potential issues, provide recommendations with code snippets (using HTML formatting for all values), and include the URL. Ensure proper risk evaluation. Mark issues that may break the build or reveal a security risk as High':\"\n        },\n        {\n          \"type\": \"text\",\n          \"text\": \"{{ $json.changes.map(change => JSON.stringify(change.diff).slice(1, -1).replace(/[\\r]/g, '')).join(' ') }}\"\n        },\n        {\n          \"type\": \"text\",\n          \"text\": \"URL: {{ $json.web_url }}\"\n        },\n        {\n          \"type\": \"text\",\n          \"text\": \"Provide a table of test cases for the QA team under the 'TestCases' field.\"\n        }\n      ]\n    }\n  ]\n}","options":{},"promptType":"define","hasOutputParser":true},"typeVersion":1.7},{"id":"f888ea7c-04d4-4192-aa72-10c341da80c8","name":"Auto-fixing Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserAutofixing","position":[1540,600],"parameters":{"options":{}},"typeVersion":1},{"id":"e52227f3-e606-4ec9-b338-c36fe7ca4b6d","name":"Structured Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[1760,940],"parameters":{"schemaType":"manual","inputSchema":"{\n  \"type\": \"object\",\n  \"properties\": {\n    \"RiskLevel\": {\n      \"type\": \"string\",\n      \"description\": \"Overall risk assessment of the changes: High/Medium/Low.\"\n    },\n    \"Summary\": {\n      \"type\": \"string\",\n      \"description\": \"One-line summary of the git diff analysis in HTML.\"\n    },\n    \"Recommendations\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"Recommendation\": {\n            \"type\": \"string\",\n            \"description\": \"Specific recommendation in HTML format.\"\n          },\n          \"CodeSnippet\": {\n            \"type\": \"string\",\n            \"description\": \"Relevant code snippet formatted in HTML.\"\n          }\n        },\n        \"required\": [\"Recommendation\", \"CodeSnippet\"]\n      }\n    },\n    \"Issues\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"File\": {\n            \"type\": \"string\",\n            \"description\": \"HTML-formatted name of the file where the issue exists.\"\n          },\n          \"PotentialIssue\": {\n            \"type\": \"string\",\n            \"description\": \"HTML-formatted description of the issue.\"\n          },\n          \"Severity\": {\n            \"type\": \"string\",\n            \"description\": \"Severity of the issue: High/Medium/Low in HTML.\"\n          }\n        },\n        \"required\": [\"File\", \"PotentialIssue\", \"Severity\"]\n      }\n    },\n    \"URL\": {\n      \"type\": \"string\",\n      \"description\": \"Link to the repository in HTML.\"\n    },\n    \"DiffTable\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"FileName\": {\n          \"type\": \"string\",\n          \"description\": \"HTML-formatted name of the file.\"\n        },\n        \"Changes\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"Line\": {\n                \"type\": \"string\",\n                \"description\": \"HTML-formatted line number.\"\n              },\n              \"Before\": {\n                \"type\": \"string\",\n                \"description\": \"Code before the change formatted in HTML.\"\n              },\n              \"After\": {\n                \"type\": \"string\",\n                \"description\": \"Code after the change formatted in HTML.\"\n              }\n            },\n            \"required\": [\"Line\", \"Before\", \"After\"]\n          }\n        }\n      }\n    },\n    \"TestCases\": {\n      \"type\": \"array\",\n      \"description\": \"List of test cases the QA team must check.\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"TestFor\": {\n            \"type\": \"string\",\n            \"description\": \"Description of the functionality or area to test.\"\n          },\n          \"Steps\": {\n            \"type\": \"string\",\n            \"description\": \"HTML-formatted steps to test the functionality.\"\n          },\n          \"ExpectedOutcome\": {\n            \"type\": \"string\",\n            \"description\": \"HTML-formatted description of the expected result of the test.\"\n          }\n        },\n        \"required\": [\"TestFor\", \"Steps\", \"ExpectedOutcome\"]\n      }\n    }\n  },\n  \"required\": [\"RiskLevel\", \"Summary\", \"Recommendations\", \"Issues\", \"URL\", \"DiffTable\", \"TestCases\"]\n}"},"typeVersion":1.2},{"id":"360985e5-1195-4411-ab5e-daf182f3be9b","name":"Anthropic Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatAnthropic","position":[1560,940],"parameters":{"model":"claude-3-5-haiku-20241022","options":{}},"credentials":{"anthropicApi":{"id":"9ZxBT7yu9DmfOCQi","name":"Anthropic account Vishal"}},"typeVersion":1.2},{"id":"e912886a-2a4c-4f82-b14b-71db3ee2b616","name":"Anthropic Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatAnthropic","position":[1400,940],"parameters":{"model":"claude-3-5-haiku-20241022","options":{}},"credentials":{"anthropicApi":{"id":"9ZxBT7yu9DmfOCQi","name":"Anthropic account Vishal"}},"typeVersion":1.2},{"id":"320b0fa4-f864-4a3c-8d25-f2cac2512fbf","name":"Comment Back on MR","type":"n8n-nodes-base.httpRequest","position":[2040,480],"parameters":{"url":"=     https://gitlab.com/api/v4/projects/{{ encodeURIComponent( $('Merge').item.json.body.project.path_with_namespace) }}/merge_requests/{{ $('Merge').item.json.body.object_attributes.iid }}/notes","method":"POST","options":{},"sendBody":true,"jsonHeaders":"{\n  \"Authorization\": \"Bearer glpatdemo -1234567890abcdef1234567890demo\"\n}\n","sendHeaders":true,"bodyParameters":{"parameters":[{"name":"body","value":"=# CodeSnape by Quantana\n\n**Summary** | {{ $('AI Agent').item.json.output.Summary }}\n--- | ---\n**Risk Level** | <span style=\"font-weight: bold; font-size: 1.5em; color: {{ $('AI Agent').item.json.output.RiskLevel.replace(/<\\/?b>/g, '') === 'Low' ? '#6B7280' : $('AI Agent').item.json.output.RiskLevel.replace(/<\\/?b>/g, '') === 'Medium' ? '#F59E0B' : '#EF4444' }};\">{{ $('AI Agent').item.json.output.RiskLevel.replace(/<\\/?b>/g, '') }}</span>\n\n## Recommendations\n\n| Recommendation | Code Snippet |\n| --- | --- |\n{{ $('AI Agent').item.json.output.Recommendations.map(rec => `| ${rec.Recommendation} | \\`${rec.CodeSnippet}\\` |`).join('\\n') }}\n\n## Test Cases\n\n| Test For | Steps | Expected Outcome |\n| --- | --- | --- |\n{{ $('AI Agent').item.json.output.TestCases.map(test => `| ${test.TestFor} | ${test.Steps} | ${test.ExpectedOutcome} |`).join('\\n') }}\n\n## Issues\n\n| File | Potential Issue | Severity |\n| --- | --- | --- |\n{{ $('AI Agent').item.json.output.Issues.map(issue => `| ${issue.File} | ${issue.PotentialIssue} | ${issue.Severity} |`).join('\\n') }}\n\n## Diff Table\n\n| Line | Before | After |\n| --- | --- | --- |\n{{ $('AI Agent').item.json.output.DiffTable.Changes.map(change => `| ${change.Line} | \\`${change.Before}\\` | \\`${change.After}\\` |`).join('\\n') }}"}]},"specifyHeaders":"json"},"typeVersion":4.2},{"id":"0f8237ca-f3fb-46cc-b173-d42ea4cd447e","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-60,140],"parameters":{"width":220,"height":360,"content":"- Triggers workflow when a merge request (MR) is created or updated.  \n\n- Add GitLab credentials. Select merge_requests event."},"typeVersion":1},{"id":"2ddc9aa2-3673-4b64-8ffb-ba7428b67dbe","name":"GitLab Trigger","type":"n8n-nodes-base.gitlabTrigger","position":[0,300],"webhookId":"fb878391-270b-47d8-addf-2917c71a3e09","parameters":{"owner":"vishalkumar1","events":["merge_requests"],"repository":"istorefront_server"},"credentials":{"gitlabApi":{"id":"tRWT5f3LnLNRPulP","name":"Gitlab overall"}},"typeVersion":1},{"id":"f751cca3-781e-4eaa-bd90-da329ed53a7f","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[800,160],"parameters":{"height":320,"content":"- Fetches code changes (diffs) from GitLab using API.  \n\n- Replace Authorization token with your GitLab API key."},"typeVersion":1},{"id":"ade683bb-8608-44bb-8047-f6c1b7de8f00","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[1060,160],"parameters":{"width":220,"height":320,"content":"- Ensures that MR contains changes before proceeding.\n\n- No setup required."},"typeVersion":1},{"id":"281db918-d9a9-43bc-ae51-c3631e2ac494","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1320,160],"parameters":{"width":380,"height":320,"content":"- Calls Claude AI to analyze the diff and generate: Risk Level, Issues, Recommendations, Test Cases.\n\n- Add Anthropic API Key (Claude AI)."},"typeVersion":1},{"id":"a7a1e7f4-1504-49be-8199-f929fc83f65e","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[1480,500],"parameters":{"width":360,"height":220,"content":"- Cleans and refines AI output for structured reporting.\n- No setup required."},"typeVersion":1},{"id":"fdbc74ea-a9cd-4811-b5b4-4eeadff28dff","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[1700,900],"parameters":{"width":220,"height":320,"content":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n- Cleans and refines AI output for structured reporting.\n- No setup required."},"typeVersion":1},{"id":"e402a3ff-daac-4bae-bbb6-f9696c9adab5","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[1980,0],"parameters":{"width":220,"height":320,"content":"- Creates a list of developers & QA testers for email notifications.\n\n- Update email mappings for your team."},"typeVersion":1},{"id":"21818092-87db-42c6-af12-cbe1632c79ab","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[2220,0],"parameters":{"width":220,"height":320,"content":"- Sends an HTML-formatted MR Report to developers & QA teams.\n\n- Add Gmail credentials."},"typeVersion":1},{"id":"13e5b3fa-c3a0-4399-baf7-84b99865907c","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[1980,340],"parameters":{"width":220,"height":300,"content":"- Posts AI-generated review report as a GitLab MR comment.\n- Replace Authorization token with your GitLab API key."},"typeVersion":1},{"id":"REPLACE_WITH_GMAIL_OAUTH_ID","name":"Send to DL ( Email Notification)","type":"n8n-nodes-base.gmail","position":[2280,140],"webhookId":"REPLACE_WITH_WEBHOOK_ID","parameters":{"sendTo":"={{ $json.emails }}","message":"=<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>CodeSnape by Quantana</title>\n  <style>\n    body {\n      margin: 0;\n      padding: 0;\n      font-family: Arial, sans-serif;\n    }\n    table {\n      border-spacing: 0;\n      border-collapse: collapse;\n      width: 100%;\n      max-width: 960px;\n      margin: 0 auto;\n    }\n    .container {\n      width: 100%;\n      max-width: 960px;\n      margin: 0 auto;\n    }\n    .section {\n      margin-bottom: 20px;\n      padding: 10px;\n    }\n    .header {\n      background-color: #f2f2f2;\n      padding: 20px;\n      text-align: center;\n    }\n    .table-container {\n      background-color: #f9f9f9;\n      padding: 10px;\n      border-radius: 5px;\n      border: 1px solid #ddd;\n    }\n    .report-summary-table, .table-container table {\n      width: 100%;\n      border-collapse: collapse;\n    }\n    .report-summary-table th, .report-summary-table td, \n    .table-container th, .table-container td {\n      border: 1px solid #ddd;\n      padding: 8px;\n      text-align: left;\n    }\n    .report-summary-table th, .table-container th {\n      background-color: #f2f2f2;\n    }\n    .report-summary-table tbody td, .table-container tbody td {\n      background-color: #fff; /* White background for table body */\n    }\n    .summary-text {\n      color: #1D4ED8;\n    }\n    .risk-low {\n      color: #6B7280;\n    }\n    .risk-medium {\n      color: #F59E0B;\n    }\n    .risk-high {\n      color: #EF4444;\n    }\n    code {\n      background-color: #f4f4f4;\n      padding: 2px 4px;\n      border-radius: 3px;\n      font-family: \"Courier New\", Courier, monospace;\n    }\n  </style>\n</head>\n<body>\n  <table class=\"container\">\n    <tr>\n      <td class=\"header\">\n        <h1>CodeSnape by Quantana</h1>\n      </td>\n    </tr>\n    <tr>\n      <td>\n        <table class=\"report-summary-table\">\n          <tr>\n            <td><strong>Summary</strong></td>\n            <td class=\"summary-text\">{{ $('AI Agent').item.json.output.Summary }}</td>\n            <td><strong>Risk Level</strong></td>\n  <td style=\"\n    font-weight: bold;\n    font-size: 1.5em;\n    color: \n      {{ $('AI Agent').item.json.output.RiskLevel.replace(/<\\/?b>/g, '') === 'Low' ? '#6B7280' : \n         $('AI Agent').item.json.output.RiskLevel.replace(/<\\/?b>/g, '') === 'Medium' ? '#F59E0B' : \n         '#EF4444' }};\n    \">\n    {{ $('AI Agent').item.json.output.RiskLevel.replace(/<\\/?b>/g, '') }}\n  </td>\n          </tr>\n          <tr>\n            <td><strong>Project Name</strong></td>\n            <td>{{ $('Merge').first().json.body.project.name }}</td>\n            <td><strong>User Name</strong></td>\n            <td>{{ $('Merge').first().json.body.user.name }}</td>\n          </tr>\n          <tr>\n            <td><strong>Created Date</strong></td>\n            <td colspan=\"3\">\n              {{ $('Merge').first().json.body.object_attributes.created_at }} (UTC)\n              <br />\n{{ new Date($('Merge').first().json.body.object_attributes.created_at).toLocaleString('en-IN', { \n  timeZone: 'Asia/Kolkata', \n  day: '2-digit', \n  month: 'short', \n  year: 'numeric', \n  hour: '2-digit', \n  minute: '2-digit', \n  second: '2-digit', \n  hour12: true \n}).replace(',', '') }} (IST)\n              </span>\n            </td>\n          </tr>\n        </table>\n      </td>\n    </tr>\n    <tr>\n      <td class=\"section\">\n        <h2>Recommendations</h2>\n        <table class=\"table-container\">\n          <thead>\n            <tr>\n              <th>Recommendation</th>\n              <th>Code Snippet</th>\n            </tr>\n          </thead>\n          <tbody>\n            {{ $('AI Agent').item.json.output.Recommendations.map(rec => `\n              <tr>\n                <td>${rec.Recommendation}</td>\n                <td><code>${rec.CodeSnippet}</code></td>\n              </tr>\n            `).join('') }}\n          </tbody>\n        </table>\n      </td>\n    </tr>\n    <tr>\n      <td class=\"section\">\n        <h2>Test Cases</h2>\n        <table class=\"table-container\">\n          <thead>\n            <tr>\n              <th>Test For</th>\n              <th>Steps</th>\n              <th>Expected Outcome</th>\n            </tr>\n          </thead>\n          <tbody>\n            {{ $('AI Agent').item.json.output.TestCases.map(test => `\n              <tr>\n                <td>${test.TestFor}</td>\n                <td>${test.Steps}</td>\n                <td>${test.ExpectedOutcome}</td>\n              </tr>\n            `).join('') }}\n          </tbody>\n        </table>\n      </td>\n    </tr>\n    <tr>\n      <td class=\"section\">\n        <h2>Issues</h2>\n        <table class=\"table-container\">\n          <thead>\n            <tr>\n              <th>File</th>\n              <th>Potential Issue</th>\n              <th>Severity</th>\n            </tr>\n          </thead>\n          <tbody>\n            {{ $('AI Agent').item.json.output.Issues.map(issue => `\n              <tr>\n                <td>${issue.File}</td>\n                <td>${issue.PotentialIssue}</td>\n                <td>${issue.Severity}</td>\n              </tr>\n            `).join('') }}\n          </tbody>\n        </table>\n      </td>\n    </tr>\n    <tr>\n      <td class=\"section\">\n        <h2>Diff Table</h2>\n        <table class=\"table-container\">\n          <thead>\n            <tr>\n              <th>Line</th>\n              <th>Before</th>\n              <th>After</th>\n            </tr>\n          </thead>\n          <tbody>\n            {{ $('AI Agent').item.json.output.DiffTable.Changes.map(change => `\n              <tr>\n                <td>${change.Line}</td>\n                <td><code>${change.Before}</code></td>\n                <td><code>${change.After}</code></td>\n              </tr>\n            `).join('') }}\n          </tbody>\n        </table>\n      </td>\n    </tr>\n    <tr>\n      <td class=\"section\">\n        <h2>URL</h2>\n        <p><a href=\"{{ $('Extract Diff').item.json.web_url }}\" target=\"_blank\">{{ $('Extract Diff').item.json.web_url }}</a></p>\n      </td>\n    </tr>\n<tr><td>Email Generated by CodeSnape from <a href=“https://quantana.com.au/ai”>Quantana</a> </td></tr>\n  </table>\n</body>\n</html>","options":{"appendAttribution":true},"subject":"=[{{ $('AI Agent').item.json.output.RiskLevel.replace(/<\\/?b>/g, '') }}] - CodeSnape for [{{ $('Merge').first().json.body.project.name }}] by [{{ $('Merge').first().json.body.user.name }}] at\n{{ $('Merge').first().json.body.object_attributes.created_at }}\n"},"credentials":{"gmailOAuth2":{"id":"REPLACE_WITH_GMAIL_OAUTH_ID","name":"Vishal Gmail"}},"typeVersion":2.1},{"id":"REPLACE_WITH_GITLAB_CRED_ID","name":"GitLab Trigger1","type":"n8n-nodes-base.gitlabTrigger","position":[0,540],"webhookId":"REPLACE_WITH_WEBHOOK_ID","parameters":{"owner":"vishalkumar1","events":["merge_requests"],"repository":"istorefront_server"},"credentials":{"gitlabApi":{"id":"tRWT5f3LnLNRPulP","name":"Gitlab overall"}},"typeVersion":1},{"id":"REPLACE_WITH_GITLAB_CRED_ID","name":"GitLab Trigger2","type":"n8n-nodes-base.gitlabTrigger","position":[0,-20],"webhookId":"REPLACE_WITH_WEBHOOK_ID","parameters":{"owner":"vishalkumar1","events":["merge_requests"],"repository":"istorefront_server"},"credentials":{"gitlabApi":{"id":"tRWT5f3LnLNRPulP","name":"Gitlab overall"}},"typeVersion":1}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"f1d633b3-d4d8-43aa-8a6b-7c4acbc67679","connections":{"Merge":{"main":[[{"node":"Extract Diff","type":"main","index":0}]]},"AI Agent":{"main":[[{"node":"Distribution List Generator","type":"main","index":0},{"node":"Comment Back on MR","type":"main","index":0}]]},"Extract Diff":{"main":[[{"node":"If Some Change","type":"main","index":0}]]},"GitLab Trigger":{"main":[[{"node":"Merge","type":"main","index":0}]]},"If Some Change":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"GitLab Trigger1":{"main":[[{"node":"Merge","type":"main","index":0}]]},"GitLab Trigger2":{"main":[[{"node":"Merge","type":"main","index":0}]]},"Anthropic Chat Model":{"ai_languageModel":[[{"node":"Auto-fixing Output Parser","type":"ai_languageModel","index":0}]]},"Anthropic Chat Model1":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"Structured Output Parser":{"ai_outputParser":[[{"node":"Auto-fixing Output Parser","type":"ai_outputParser","index":0}]]},"Auto-fixing Output Parser":{"ai_outputParser":[[{"node":"AI Agent","type":"ai_outputParser","index":0}]]},"Distribution List Generator":{"main":[[{"node":"Send to DL ( Email Notification)","type":"main","index":0}]]}}}


name: AI-Generated LinkedIn Posts with OpenAI, Google Sheets & Email Approval Workflow
author_name: Aryan Shinde
author_username: shindearyan
categories: []
created_at: 2025-05-12T23:11:35.083Z
updated_at: 2025-05-12T23:11:35.083Z
url: https://n8n.io/workflows/4005
scraped_at: 2025-06-19 22:48:43
description:
  How it works
  This workflow automates the process of creating, approving, and optionally posting LinkedIn content from a Google Sheet. Here's a high-level overview:
  Scheduled Trigger: Runs automatically based on your defined time interval (daily, weekly, etc.).
  Fetch Data from Google Sheets: Pulls the first row from your sheet where Status is marked as Pending.
  Generate LinkedIn Post Content: Uses OpenAI to create a professional LinkedIn post using the Post Description and Instructions from the sheet.
  Format & Prepare Data: Formats the generated content along with the original instruction and post description for email.
  Send for Approval: Sends an email to a predefined user (e.g., marketing team) with a custom form for approval, including a dropdown to accept/reject and an optional field for edits.
  (Optional) Image Fetch: Downloads an image from a URL (if provided in the sheet) for future use in post visuals.

  Set up steps
  You’ll need the following before you start:

  A Google Sheet with the following columns: Post Description, Instructions, Image (URL), Status
  Access to an OpenAI API key
  A connected Gmail account for sending approval emails
  Your own Google Sheets and Gmail credentials added in n8n

  Steps:
  Google Sheet Preparation:
  Create a new Google Sheet with the mentioned columns (Post Description, Instructions, Image, Status, Output, Post Link).
  Add a row with test data and set Status to Pending.

  Credentials:
  In n8n, create OAuth2 credentials for:
  a. Google Sheets
  b. Gmail
  c. OpenAI (API Key)
  Assign these credentials to the respective nodes in the JSON.

  OpenAI Model:
  Choose a model like gpt-4o-mini (used here) or any other available in your plan.
  Adjust the prompt in the "Generate Post Content" node if needed.

  Email Configuration:
  In the Gmail node, set the recipient email to your own or your team’s address.
  Customize the email message template if necessary.

  Schedule the Workflow:
  Set the trigger interval (e.g., every morning at 9 AM).

  Testing:
  Run the workflow manually first to confirm everything works.
  Check Gmail for the approval form, respond, and verify the results.

nodes_used:
  ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest","n8n-nodes-base.gmail","n8n-nodes-base.linkedIn","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.lmChatOpenAi"]

workflow_json:
  {"id":"w9YVsuUtlNgXOEAQ","meta":{"instanceId":"58a9e858b82757a75629d435ec0da2448ad5d9e906a9ce3b7dcbb64c90fda9fe","templateCredsSetupCompleted":true},"name":"LinkedIn Post Generation & Approval Automation","tags":[{"id":"3bzbXbpZW83y48aK","name":"content-approval","createdAt":"2025-05-13T18:45:19.225Z","updatedAt":"2025-05-13T18:45:19.225Z"},{"id":"9SfWdyKRFVbPxrNL","name":"post-generator","createdAt":"2025-05-13T18:45:09.255Z","updatedAt":"2025-05-13T18:45:09.255Z"},{"id":"VWnkUEKQKJB2WmbL","name":"linkedin","createdAt":"2025-05-13T18:45:04.175Z","updatedAt":"2025-05-13T18:45:04.175Z"}],"nodes":[{"id":"d0f86395-aeec-4284-a2d5-26db2dfebd53","name":"Get Image","type":"n8n-nodes-base.httpRequest","position":[1592,2120],"parameters":{"url":"={{ $('Get Data from Sheets').item.json.Image }}","options":{}},"typeVersion":4.2,"alwaysOutputData":true},{"id":"b8ca88a6-aaf1-4191-8b75-9a63b746af77","name":"Schedule Trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-260,2595],"parameters":{"rule":{"interval":[{}]}},"typeVersion":1.2},{"id":"8e4e294f-56d4-4317-aea8-ea258527f55a","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[268,2815],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"7OVQwPA6RZRwFmwI","name":"OpenAI Account"}},"typeVersion":1.2},{"id":"d262684e-7671-4602-ba77-4270441a69fb","name":"Get Data from Sheets","type":"n8n-nodes-base.googleSheets","position":[-40,2595],"parameters":{"options":{"returnFirstMatch":true},"filtersUI":{"values":[{"lookupValue":"Pending","lookupColumn":"Status"}]},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1EAdLU9-l0ATGDa5_xwTwFO-rPhvZurM2BOSKjH2P-W8/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"1EAdLU9-l0ATGDa5_xwTwFO-rPhvZurM2BOSKjH2P-W8","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1EAdLU9-l0ATGDa5_xwTwFO-rPhvZurM2BOSKjH2P-W8/edit?usp=drivesdk","cachedResultName":"LinkedIn Post Automation"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Gs7mfT220sbLQ7PS","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"93d3e57f-a22d-4c04-9ccc-7ee655bedbdb","name":"Generate Post Content","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[180,2595],"parameters":{"text":"=# LinkedIn Post Generation\n\n## Post Description:\n{{ $json[\"Post Description\"] }}\n\n## Instructions:\n{{ $json[\"Instructions\"] }}\n\n---\n\n**Task:**\nUsing the information above, generate the content for a LinkedIn post:\n- Use the Description and Instructions to create a new post.\n- Ensure your output is positive, professional, clear, and follows all provided instructions and feedback.\n- Do not include any explanations, just the final post content only, ready to publish on LinkedIn.\n- Limit to 1300 characters.\n- If the user demands to keep the same post as the Post Descrioption (in the instructions), then keep the same post content as provided in the Post Description, and output it.","messages":{"messageValues":[{"message":"=You are an expert social media and LinkedIn content writer.\n\nYou will be provided with:\n- A brief post description\n- Specific instructions from the user\n\nPlease follow these steps:\n\n1. Initial Creation:\nIf you are given a post description and instructions, write a polished, professionally worded LinkedIn post suitable for sharing. Strictly follow the instructions and ensure the message is engaging and succinct.\nIf instructed, add a call to action or particular phrase (for example, \"Connect with me\" at the bottom).\n\n2. Formatting:\nKeep the tone positive, inclusive, and professional.\nAdd relevant hashtags in small case.\nLimit the content to within 1300 characters.\nPlace the call to action or special instruction at the end if requested.\nOutput ONLY the final LinkedIn post content. Do NOT include any explanations, markdown, headings, or commentary—just the post text, ready to copy and share on LinkedIn."}]},"promptType":"define"},"typeVersion":1.6},{"id":"6ea121f4-661c-4dd4-a0bc-7edb8a0b884a","name":"Data Formatting 1","type":"n8n-nodes-base.set","position":[556,2595],"parameters":{"options":{},"assignments":{"assignments":[{"id":"bded6f56-99e2-4f1a-be41-27a8dd417844","name":"Post Content","type":"string","value":"={{ $json.text }}"},{"id":"c222c42e-b639-4a74-a1b0-7a3e6e141d55","name":"Post Description","type":"string","value":"={{ $('Get Data from Sheets').item.json['Post Description'] }}"},{"id":"14775ff7-e005-4a86-9623-c322365f7d3a","name":"Instructions","type":"string","value":"={{ $('Get Data from Sheets').item.json.Instructions }}"}]}},"typeVersion":3.4},{"id":"a00ec081-07c0-4f8a-9139-6606a65236ff","name":"Send Content Confirmation","type":"n8n-nodes-base.gmail","position":[776,2495],"webhookId":"29614d41-05c1-44af-93a6-4831a27f9331","parameters":{"sendTo":"youremail@gmail.com","message":"=Generated Post:\n{{ $json['Post Content'] }}\n\n----------\n\nPost Description:\n{{ $json['Post Description'] }}\n\n----------\n\nInstructions:\n{{ $json.Instructions }}","options":{},"subject":"Approval for LinkedIn Post","operation":"sendAndWait","formFields":{"values":[{"fieldType":"dropdown","fieldLabel":"Confirm  Content?","fieldOptions":{"values":[{"option":"Yes"},{"option":"No"},{"option":"Cancel"}]},"requiredField":true},{"fieldType":"textarea","fieldLabel":"Any Changes?"}]},"responseType":"customForm"},"credentials":{"gmailOAuth2":{"id":"n47Kn2N5BwXYv6eA","name":"Gmail account"}},"typeVersion":2.1},{"id":"5a1e8061-ef79-4974-888d-8670e60a1b0c","name":"Content Confirmation Logic","type":"n8n-nodes-base.switch","position":[996,2495],"parameters":{"rules":{"values":[{"outputKey":"Yes","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"99ec185e-80ac-451d-bb69-662f84a7cf52","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.data['Confirm  Content?'] }}","rightValue":"Yes"}]},"renameOutput":true},{"outputKey":"No","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"77031007-a912-4b9b-9cca-846c57ffaec8","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.data['Confirm  Content?'] }}","rightValue":"No"}]},"renameOutput":true},{"outputKey":"Cancel","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"e94de530-6451-48aa-892c-924a9c41cfb0","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.data['Confirm  Content?'] }}","rightValue":"Cancel"}]},"renameOutput":true}]},"options":{}},"typeVersion":3.2},{"id":"c139fda0-4be1-4ad7-bb28-802b7150365d","name":"Regenerate Post Content","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[1216,2670],"parameters":{"text":"=Apply the modification requests on the following LinkedIn post. Besides applying the reqested modifications, return the same linkedin post.\n\nLinkedIn post:\n```\n{{ $('Data Formatting 1').item.json['Post Content'] }}\n```\n\nChange requests:\n{{ $('Send Content Confirmation').item.json.data['Any Changes?'] }}\n\n**Task:**\nUsing the information above, update the LinkedIn post content:\n- Do not include any explanations, just the final post content only (with all the change requests included in the post), ready to publish on LinkedIn.\n- Limit to 1300 characters.\n- If the user demands to keep the same post as the Post Description (in the instructions), then keep the same post content as provided in the Post Description, and output it.","promptType":"define"},"typeVersion":1.6},{"id":"b8587578-03a6-4975-8907-667628dc958a","name":"If Image Provided","type":"n8n-nodes-base.if","position":[1294,2220],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"9a78220d-35f5-48b6-9ce3-faecaac24b74","operator":{"type":"string","operation":"notEmpty","singleValue":true},"leftValue":"={{ $('Get Data from Sheets').item.json.Image }}","rightValue":""}]}},"typeVersion":2.2},{"id":"30bf76c8-8420-4d77-bc2b-8a1c27fbf36a","name":"Post With Image","type":"n8n-nodes-base.linkedIn","position":[1812,2120],"parameters":{"text":"={{ $('Data Formatting 1').item.json['Post Content'] }}","person":"pM247vR8Se","additionalFields":{},"shareMediaCategory":"IMAGE"},"credentials":{"linkedInOAuth2Api":{"id":"Fg8i5E17dzZcPtMH","name":"LinkedIn account 2"}},"typeVersion":1},{"id":"62bf9597-3e38-45ec-853c-aa2d77c40bc2","name":"Post Without Image","type":"n8n-nodes-base.linkedIn","position":[1812,2320],"parameters":{"text":"={{ $('Data Formatting 1').item.json['Post Content'] }}","person":"pM247vR8Se","additionalFields":{}},"credentials":{"linkedInOAuth2Api":{"id":"Fg8i5E17dzZcPtMH","name":"LinkedIn account 2"}},"typeVersion":1},{"id":"0ddd307d-5e54-42cf-b65a-25f111fb4bea","name":"Update Google Sheet","type":"n8n-nodes-base.googleSheets","position":[2032,2320],"parameters":{"columns":{"value":{"Output":"={{ $json.urn }}","Status":"=Completed","Post Link":"={{ $json.urn }}","row_number":"={{ $('Get Data from Sheets').item.json.row_number }}"},"schema":[{"id":"Post Description","type":"string","display":true,"removed":true,"required":false,"displayName":"Post Description","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Instructions","type":"string","display":true,"removed":true,"required":false,"displayName":"Instructions","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Image","type":"string","display":true,"removed":true,"required":false,"displayName":"Image","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Status","type":"string","display":true,"removed":false,"required":false,"displayName":"Status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Output","type":"string","display":true,"required":false,"displayName":"Output","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Post Link","type":"string","display":true,"required":false,"displayName":"Post Link","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/1EAdLU9-l0ATGDa5_xwTwFO-rPhvZurM2BOSKjH2P-W8/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"1EAdLU9-l0ATGDa5_xwTwFO-rPhvZurM2BOSKjH2P-W8","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1EAdLU9-l0ATGDa5_xwTwFO-rPhvZurM2BOSKjH2P-W8/edit?usp=drivesdk","cachedResultName":"LinkedIn Post Automation"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Gs7mfT220sbLQ7PS","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"c4a55beb-8459-4faa-b072-51c500562ae3","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-780,2480],"parameters":{"width":420,"height":380,"content":"## 1. Schedule & Sheet Data Retrieval\n\nThis workflow starts automatically on a defined schedule (e.g., daily or hourly).\n\nIt retrieves the next Google Sheet row marked as ‘Pending’.\n\nThe sheet should include columns like:\n1. Post Description\n2. Instructions\n3. Image\n4. Status\n5. row_number (required for updates)\n\nEnsure your Google Sheets credentials are correctly configured."},"typeVersion":1},{"id":"09dade5b-e26a-4b97-9b8a-a5c807cff937","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-220,3040],"parameters":{"width":420,"height":240,"content":"## 2. AI-Powered Post Generation & Formatting\n\nUses OpenAI GPT to generate a LinkedIn post based on the sheet’s Post Description and Instructions.\n\nYou can modify the prompt if needed.\nThe generated post is then formatted along with relevant data for easy reference and consistency."},"typeVersion":1},{"id":"f373dfd9-f971-4925-8e74-15201c8a47c4","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[440,3040],"parameters":{"width":440,"height":240,"content":"## 3. Gmail Approval Workflow\n\nSends the formatted post to an approver via Gmail.\n\nThe approver can respond with:\n✅ Yes – Approve\n✏️ No – Request changes\n❌ Cancel – Abort the post\n\nSet Gmail credentials and recipient email in the node."},"typeVersion":1},{"id":"66d51a35-262e-469b-bcd8-aca3cf60452c","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[1120,3040],"parameters":{"width":440,"height":240,"content":"## 4. Approval Handling & Regeneration\n\nHandles all approval responses:\n- If Yes, proceed to post.\n- If No, regenerate content based on the feedback and resend.\n- If Cancel, update the Google Sheet as Cancelled.\n\nThis ensures a complete review cycle before posting."},"typeVersion":1},{"id":"ad4023af-0e8b-4ec1-be1d-9313ec4f5ca7","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1800,3040],"parameters":{"width":460,"height":320,"content":"## 5. Image Check, Posting & Sheet Update\n\nChecks if an image URL is provided.\n- If present: Downloads the image and posts with it.\n- If not: Posts content without an image.\n\nAfter posting, it updates the Google Sheet with:\n- Status = Completed or Cancelled\n- LinkedIn post link/output\n\nUses row_number for precise sheet updates."},"typeVersion":1}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"65685909-274a-4d41-8f8a-fbba9442597b","connections":{"Get Image":{"main":[[{"node":"Post With Image","type":"main","index":0}]]},"Post With Image":{"main":[[{"node":"Update Google Sheet","type":"main","index":0}]]},"Schedule Trigger":{"main":[[{"node":"Get Data from Sheets","type":"main","index":0}]]},"Data Formatting 1":{"main":[[{"node":"Send Content Confirmation","type":"main","index":0}]]},"If Image Provided":{"main":[[{"node":"Get Image","type":"main","index":0}],[{"node":"Post Without Image","type":"main","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"Generate Post Content","type":"ai_languageModel","index":0},{"node":"Regenerate Post Content","type":"ai_languageModel","index":0}]]},"Post Without Image":{"main":[[{"node":"Update Google Sheet","type":"main","index":0}]]},"Get Data from Sheets":{"main":[[{"node":"Generate Post Content","type":"main","index":0}]]},"Generate Post Content":{"main":[[{"node":"Data Formatting 1","type":"main","index":0}]]},"Regenerate Post Content":{"main":[[{"node":"Data Formatting 1","type":"main","index":0}]]},"Send Content Confirmation":{"main":[[{"node":"Content Confirmation Logic","type":"main","index":0}]]},"Content Confirmation Logic":{"main":[[{"node":"If Image Provided","type":"main","index":0}],[{"node":"Regenerate Post Content","type":"main","index":0}],[{"node":"Update Google Sheet","type":"main","index":0}]]}}}


name: Generate Knowledge Base Articles with GPT & Perplexity AI for Contentful CMS
author_name: Varritech
author_username: varritech
categories: []
created_at: 2025-05-13T11:31:19.601Z
updated_at: 2025-05-13T11:31:19.601Z
url: https://n8n.io/workflows/4012
scraped_at: 2025-06-19 22:49:18
description:
  Workflow: Auto Knowledge Base Article Generator

  ⚡ About the Creators
  This workflow was created by Varritech Technologies, an innovative agency that leverages AI to engineer, design, and deliver software development projects 500% faster than traditional agencies. Based in New York City, we specialize in custom software development, web applications, and digital transformation solutions. If you need assistance implementing this workflow or have questions about content management solutions, please reach out to our team.

  🏗️ Architecture Overview  
  This workflow automates the end-to-end creation of a structured knowledge-base article from a simple chat prompt:

  Chat Trigger → Receives user request  
  AI Drafting Loop → Generates & refines JSON article via AI agents  
  Perplexity Research Call → Deep-dive content generation  
  Editorial Loop → Up to 3 AI-driven revisions  
  Contentful Publish → Pushes final JSON into CMS  

  📦 Node-by-Node Breakdown

  flowchart LR
    A[Webhook: Chat Trigger] --&gt; B[AI Writer Agent]
    B --&gt; C[HTTP Request: Perplexity Content]
    C --&gt; D[Function: Format Output & Citations]
    D --&gt; E[Loop Start: Initialize Count]
    E --&gt; F[AI Editor Agent]
    F --&gt; G{action == "rewrite"?}
    G -- yes --&gt; H[Function: Merge Improvements]
    H --&gt; I[Increment Count] --&gt; F
    G -- no --&gt; J[Stop Loop]
    J --&gt; K[HTTP Request: Publish to Contentful]

  Webhook: Chat Trigger

  Type: HTTP Webhook (POST /webhook/knowledge-article)

  Payload:

  { 
  	"chatInput": "What topics should I write about?" 
  }

  Purpose: Kicks off the workflow on that chat prompt.

  AI Writer Agent

  Inputs: chatInput or existing article JSON

  Outputs:

  {
    "title": "...",
    "slug": "...",
    "category.id": "...",
    "description": "...",
    "keywords": [...],
    "content": "...",
    "metaTitle": "...",
    "metaDescription": "...",
    "readingTime": 5,
    "difficulty": "intermediate"
  }

  Purpose: Generates the article skeleton (metadata + initial content).

  HTTP Request: Perplexity Content

  Method: POST

  URL: https://api.perplexity.ai/research

  Body:
  {
    "model": "sonar-deep-research",
    "query": "{{ $json.title }}",
    "length": 1000
  }

  Purpose: Retrieves a long-form, deeply researched draft for the article body.

  Function: Format Output & Citations

  Logic:

  Parse raw Perplexity response
  Extract source URIs
  Append them under a sources markdown list

  Editorial Loop

  Initialize Counter to 0
  AI Editor Agent
     Reads draft JSON
     Returns either:
       action: "rewrite" + improvements: [...]
       or action: "submit"
  Merge Improvements (if rewriting)
     Applies suggested updates to JSON fields
  Limit Check
     Stops after 3 iterations or on "submit"

  HTTP Request: Publish to Contentful

  Method: PUT

  URL: https://cdn.contentful.com/spaces/{space}/environments/master/entries/{entryId}

  Headers:
  Authorization: Bearer &lt;token&gt;
  Content-Type: application/vnd.contentful.management.v1+json

  Body: Maps JSON → Contentful entry fields

  Outcome: Publishes the finalized article live.

  🔍 Design Rationale & Best Practices

  Separation of Concerns
  Writer vs. Editor agents isolate creative drafting from quality review.

  Idempotent Loop
  Counter + action flags prevent infinite retries.

  Extensibility
  Swap in different research APIs or CMS targets with minimal changes.

  Structured JSON
  Ensures predictable input/output for each node.

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

workflow_json:
  {"id":"WwEFqNK4YP6UJcg2","meta":{"instanceId":"6bcff5ef8a06e8086902526a05c2a4c7bf5da8101f89e582301ed78094606f40","templateCredsSetupCompleted":true},"name":"Auto Knowledge Base Article Generator","tags":[],"nodes":[{"id":"17900021-8da3-4bd9-9d79-5d20d879ddc7","name":"Create Perplexity Content","type":"n8n-nodes-base.httpRequest","position":[1220,380],"parameters":{"url":"https://api.perplexity.ai/chat/completions","method":"POST","options":{},"jsonBody":"={\n  \"model\": \"sonar-deep-research\",\n  \"messages\": [\n    {\n      \"role\": \"user\",\n      \"content\": \"Conduct an in-depth research on '{{ $json.output.parseJson().title }}', covering essential topics, recommended resources, and best practices. Additionally, please address these improvements: '{{ $json.output.parseJson().improvements }}'. The returned data should be at least 1000 words and use a combination of headers, tables, bold, and italics\"\n    }\n  ],\n  \"max_tokens\": 60000,\n  \"temperature\": 0.7,\n  \"top_p\": 0.9,\n  \"top_k\": 50,\n  \"stream\": false,\n  \"presence_penalty\": 0,\n  \"frequency_penalty\": 0\n}","sendBody":true,"jsonHeaders":"{\n  \"Authorization\": \"Bearer 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\",\n  \"Content-Type\": \"application/json\"\n}","sendHeaders":true,"specifyBody":"json","specifyHeaders":"json"},"typeVersion":4.2},{"id":"0cb3f3a7-92bd-4ff3-8a89-b6fc29513e65","name":"AI Writer Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[720,380],"parameters":{"text":"=Please create or revise an article about \"{{ $json.chatInput }}\".\n\nOr an article is already written because title: {{ $json.title }} is defined. Reference it to rewrite the {{ $json.content }} field\n\nDo not change the title, either the chatinput or the input article title. This is the title, do not change it.\n\nIf an article is NOT given, pick new categories in:\n- getting-started\n- learning-paths\n- certifications\n- programming\n- applications\n- career\n\nDo not make up a category, it should be the same in the exact case as above\n\nIf an article is given, only make ammendments to the content based on these specific improvements to include: \"{{ $json.improvements }}\".\n\nInclude the improvements key only if it is an input, and in that case don't change it\n\nRemember to return valid JSON with the fields:\n{\n  \"title\": \"...\",\n  \"slug\": \"...\",\n  \"category\": {\n    \"id\": \"...\"\n  },\n  \"description\": \"...\",\n  \"keywords\": [...],\n  \"content\": \"...\",\n  \"metaTitle\": \"...\",\n  \"metaDescription\": \"...\",\n  \"readingTime\": \"...\",\n  \"difficulty\": \"...\"\n  \"content\": \"...\"\n}","options":{"systemMessage":"You are a writing assistant. You will receive instructions to create or update an article in JSON format with the following structure:\n\n{\n  \"title\": \"<string>\",\n  \"slug\": \"<string>\",\n  \"category\": {\n    \"id\": \"<string>\" // e.g., \"getting-started\", \"learning-paths\", etc.\n  },\n  \"description\": \"<string>\",\n  \"keywords\": [\"<string>\", \"<string>\", ...],\n  \"content\": \"<string>\",\n  \"metaTitle\": \"<string>\",\n  \"metaDescription\": \"<string>\",\n  \"readingTime\": \"<number or string>\",\n  \"difficulty\": \"<string>\"\n}\n\nYour task:\n1. Produce a complete article in the above format, or revise the existing article if provided.\n2. Make sure the text is clear, specific, and helpful to the reader.\n3. Return valid JSON only – do not include extra commentary or fields beyond the above structure.\n4. If any information is missing from the user instructions, make reasonable assumptions.\n"},"promptType":"define"},"typeVersion":1.7},{"id":"bc62facb-c5cb-465d-89b1-a65a893c3ce1","name":"AI Editor Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[2280,380],"parameters":{"text":"={{ $json }}","options":{"maxIterations":5,"systemMessage":"=You are an editorial AI assistant. Your role is to review and evaluate a draft article represented as a JSON object.\n\nCategory IDs:\n- \"getting-started\"\n- \"learning-paths\"\n- \"certifications\"\n- \"programming\"\n- \"applications\"\n- \"career\"\n\nInput Format:\n\n{\n  \"title\": \"<string>\",\n  \"slug\": \"<string>\",\n  \"category\": { \"id\": \"<string>\" },\n  \"description\": \"<string>\",\n  \"keywords\": [\"<string>\", \"...\"],\n  \"content\": \"<string>\",\n  \"metaTitle\": \"<string>\",\n  \"metaDescription\": \"<string>\",\n  \"readingTime\": \"<string | number>\",\n  \"difficulty\": \"<string>\"\n}\n\nYour Tasks:\n\n1. Evaluate the quality of the article — especially the title, description, content, and metadata.\n2. Comment on clarity, specificity, usefulness, and overall quality.\n3. If improvements are needed, add an \"improvements\" field describing exactly what to fix.\n4. Set the \"action\" field:\n- \"rewrite\" if improvements are needed.\n- \"submit\" if the article is high quality.\n5. Include all fields from the original input in your output.\n6. If \"action\" is \"submit\", set \"improvements\" to null.\n7. Avoid repeating feedback across iterations.\n8. After 2 iterations, automatically call the accept-and-publish tool and set the \"action\" to \"submit\".\n9. VERY IMPORTANT: Do NOT modify any of the input fields\n10. VERY IMPORTANT: Do NOT truncate the sources or modify the content field in any way\n\n✅ Output Format:\n\n{\n  \"title\": \"...\",\n  \"action\": \"rewrite | submit\",\n  \"improvements\": \"... | null\",\n  \"slug\": \"...\",\n  \"category\": {\n    \"id\": \"...\"\n  },\n  \"description\": \"...\",\n  \"keywords\": [\"...\"],\n  \"content\": \"...\",\n  \"metaTitle\": \"...\",\n  \"metaDescription\": \"...\",\n  \"readingTime\": \"...\",\n  \"difficulty\": \"...\"\n}\n\nTone: Be concise, direct, and constructive. Focus on maximizing clarity, usefulness, and readability for the end reader."},"promptType":"define","hasOutputParser":true},"retryOnFail":true,"typeVersion":1.7},{"id":"8c08d67a-b916-4cfd-89cd-16b34250bcb2","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[680,640],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-3.5-turbo","cachedResultName":"gpt-3.5-turbo"},"options":{}},"credentials":{"openAiApi":{"id":"KLN8ZfDzv8mW6pyu","name":"OpenAi account"}},"typeVersion":1.2},{"id":"97bb1374-f502-4152-a5a3-bc5d46a18171","name":"OpenAI Chat Model1","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[2200,660],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4.5-preview","cachedResultName":"gpt-4.5-preview"},"options":{}},"credentials":{"openAiApi":{"id":"KLN8ZfDzv8mW6pyu","name":"OpenAi account"}},"typeVersion":1.2},{"id":"1c422e76-5b1a-4615-b379-ab39d4bd13b4","name":"Accept and Publish","type":"@n8n/n8n-nodes-langchain.toolWorkflow","position":[2420,660],"parameters":{"name":"submit","workflowId":{"__rl":true,"mode":"list","value":"uIREtTV8TRuF3lru","cachedResultName":"Publish to Contentful"},"description":"Call this tool when the article quality is above the threshold we need","workflowInputs":{"value":{"slug":"=  {{ $json.slug }}","title":"={{ $('Format').item.json.title }}","content":"={{ $json.content }}","category":"={{ $json.category }}","keywords":"={{ $json.keywords }}","metaTitle":"={{ $json.metaTitle }}","difficulty":"={{ $json.difficulty }}","description":"={{ $json.description }}","readingTime":"={{ $json.readingTime }}","metaDescription":"={{ $json.metaDescription }}"},"schema":[{"id":"title","type":"string","display":true,"removed":false,"required":false,"displayName":"title","defaultMatch":false,"canBeUsedToMatch":true},{"id":"action","type":"string","display":true,"removed":true,"required":false,"displayName":"action","defaultMatch":false,"canBeUsedToMatch":true},{"id":"improvements","type":"string","display":true,"removed":true,"required":false,"displayName":"improvements","defaultMatch":false,"canBeUsedToMatch":true},{"id":"slug","type":"string","display":true,"removed":false,"required":false,"displayName":"slug","defaultMatch":false,"canBeUsedToMatch":true},{"id":"category","type":"object","display":true,"removed":false,"required":false,"displayName":"category","defaultMatch":false,"canBeUsedToMatch":true},{"id":"description","type":"string","display":true,"removed":false,"required":false,"displayName":"description","defaultMatch":false,"canBeUsedToMatch":true},{"id":"keywords","type":"array","display":true,"removed":false,"required":false,"displayName":"keywords","defaultMatch":false,"canBeUsedToMatch":true},{"id":"content","type":"string","display":true,"removed":false,"required":false,"displayName":"content","defaultMatch":false,"canBeUsedToMatch":true},{"id":"metaTitle","type":"string","display":true,"removed":false,"required":false,"displayName":"metaTitle","defaultMatch":false,"canBeUsedToMatch":true},{"id":"metaDescription","type":"string","display":true,"removed":false,"required":false,"displayName":"metaDescription","defaultMatch":false,"canBeUsedToMatch":true},{"id":"readingTime","type":"string","display":true,"removed":false,"required":false,"displayName":"readingTime","defaultMatch":false,"canBeUsedToMatch":true},{"id":"difficulty","type":"string","display":true,"removed":false,"required":false,"displayName":"difficulty","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false}},"typeVersion":2},{"id":"b6807e84-900a-48fc-a869-862824c62ba1","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-60,660],"webhookId":"7ed20abc-d8bc-4426-95f1-b9778c075ddf","parameters":{"public":true,"options":{},"initialMessages":"What topics should I write about?"},"typeVersion":1.1},{"id":"e3021ac4-9444-4689-af0c-a4bbd4729c35","name":"JSON.parse1","type":"n8n-nodes-base.code","position":[1320,120],"parameters":{"mode":"runOnceForEachItem","jsCode":"const outputText = $json.output;\n\n// Parse JSON from ChatGPT response\nconst parsedOutput = JSON.parse(outputText);\n\n// Return parsed object for next nodes\nreturn parsedOutput;"},"typeVersion":2},{"id":"d6a5eccd-c8e3-4ee0-beb0-7b8fc8428b91","name":"Merge","type":"n8n-nodes-base.merge","position":[1840,380],"parameters":{"numberInputs":3},"typeVersion":3},{"id":"8461a1a0-a984-4ec1-bc93-3a1a312caf55","name":"Format","type":"n8n-nodes-base.code","position":[2060,380],"parameters":{"jsCode":"// Get all items passed into this node as an array\nconst items = $input.all();\n\n// If you always have at least two items:\nconst firstItem = items[0].json;\nconst secondItem = items[1].json;\nconst thirdItem = items[2].json;\n\n// Overwrite the first item’s “content” with the second item’s “content”\nfirstItem.content = secondItem.content;\nfirstItem.iterationCount = thirdItem.iterationCount\n\n// Return a single new item containing the merged result\nreturn [\n  {\n    json: firstItem\n  }\n];"},"typeVersion":2},{"id":"9b9a82fb-990c-4be0-aee9-ed80f0631c28","name":"JSON.parse","type":"n8n-nodes-base.code","position":[3300,840],"parameters":{"mode":"runOnceForEachItem","jsCode":"const outputText = $json.output;\n\n// Parse JSON from ChatGPT response\nconst parsedOutput = JSON.parse(outputText);\n\n// Return parsed object for next nodes\nreturn parsedOutput;"},"typeVersion":2},{"id":"066dfd10-e97a-44a8-89e0-5b2b5c4a6244","name":"Format Perplexity Output & Add Citations","type":"n8n-nodes-base.code","position":[1480,380],"parameters":{"mode":"runOnceForEachItem","jsCode":"const data = { ...$json };\n\n// Clean out <think> block if present\ndata.content = $json.choices[0].message.content.replace(/<think>[\\s\\S]*?<\\/think>/g, '').trim();\n\n// Convert citations array to markdown link list\nconst citations = $json.citations\n  .map((url, i) => `- [${i + 1}](${url})`)\n  .join('\\n');\n\ndata.content += `\\n\\n---\\n\\n### Sources\\n${citations}`;\n\nreturn data;"},"typeVersion":2},{"id":"fc9d9e93-568a-41af-a295-8736617b157e","name":"Initialize Count","type":"n8n-nodes-base.set","position":[340,660],"parameters":{"values":{"number":[{"name":"iterationCount"}]},"options":{}},"typeVersion":1},{"id":"b0e636dd-f572-4ee2-832f-4bb4167b011b","name":"Increment Count","type":"n8n-nodes-base.function","position":[1400,740],"parameters":{"functionCode":"const current = $json.iterationCount || 0;\n\nreturn [{ iterationCount: current + 1 }];"},"typeVersion":1},{"id":"86689f0e-9607-4eda-bcd6-36241d0cbe63","name":"Check Limit","type":"n8n-nodes-base.if","position":[2660,380],"parameters":{"conditions":{"number":[{"value1":"={{ $json.iterationCount }}","value2":3,"operation":"largerEqual"}]}},"typeVersion":1},{"id":"0f42b0f3-0b96-40df-9c06-2a6d31e142d9","name":"Stop Here","type":"n8n-nodes-base.noOp","position":[2980,300],"parameters":{},"typeVersion":1},{"id":"1e61b3ba-e9bd-43c7-8217-d4a22f707318","name":"Execute Workflow","type":"n8n-nodes-base.executeWorkflow","position":[3680,320],"parameters":{"options":{},"workflowId":{"__rl":true,"mode":"list","value":"uIREtTV8TRuF3lru","cachedResultName":"Publish to Contentful"},"workflowInputs":{"value":{"slug":"={{ $json.slug }}","title":"={{ $json.title }}","content":"={{ $json.content }}","category":"={{ $json.category }}","keywords":"={{ $json.keywords }}","metaTitle":"={{ $json.metaTitle }}","difficulty":"={{ $json.difficulty }}","description":"={{ $json.description }}","readingTime":"={{ $json.readingTime }}","metaDescription":"={{ $json.metaDescription }}"},"schema":[{"id":"title","type":"string","display":true,"required":false,"displayName":"title","defaultMatch":false,"canBeUsedToMatch":true},{"id":"slug","type":"string","display":true,"required":false,"displayName":"slug","defaultMatch":false,"canBeUsedToMatch":true},{"id":"category","type":"object","display":true,"required":false,"displayName":"category","defaultMatch":false,"canBeUsedToMatch":true},{"id":"description","type":"string","display":true,"required":false,"displayName":"description","defaultMatch":false,"canBeUsedToMatch":true},{"id":"keywords","type":"array","display":true,"required":false,"displayName":"keywords","defaultMatch":false,"canBeUsedToMatch":true},{"id":"content","type":"string","display":true,"required":false,"displayName":"content","defaultMatch":false,"canBeUsedToMatch":true},{"id":"metaTitle","type":"string","display":true,"required":false,"displayName":"metaTitle","defaultMatch":false,"canBeUsedToMatch":true},{"id":"metaDescription","type":"string","display":true,"required":false,"displayName":"metaDescription","defaultMatch":false,"canBeUsedToMatch":true},{"id":"readingTime","type":"string","display":true,"required":false,"displayName":"readingTime","defaultMatch":false,"canBeUsedToMatch":true},{"id":"difficulty","type":"string","display":true,"required":false,"displayName":"difficulty","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":true}},"typeVersion":1.2},{"id":"04526224-e48c-4032-9c92-475c6bf9cd0a","name":"JSON.parse3","type":"n8n-nodes-base.code","position":[3280,300],"parameters":{"mode":"runOnceForEachItem","jsCode":"const outputText = $json.output;\n\n// Parse JSON from ChatGPT response\nconst parsedOutput = JSON.parse(outputText);\n\n// Return parsed object for next nodes\nreturn parsedOutput;"},"typeVersion":2},{"id":"0303ab91-b788-4074-a15d-239565528dec","name":"should submit","type":"n8n-nodes-base.if","position":[2980,680],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"3c1f6cb2-a556-4c74-885e-05e4f757997b","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"submit","rightValue":"={{ $json.output.parseJson().action }}"}]}},"typeVersion":2.2},{"id":"4f68e1ad-0b7c-41ca-a9cc-d220017cc1bd","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[540,80],"parameters":{"width":940,"height":680,"content":"## Writer Agent\n\n- Focuses on writing for all the fields in contentful\n- Has a specified format for input and output\n- Handles implementing feedback from editor agent"},"typeVersion":1},{"id":"f5e9968a-0681-4b72-9bb3-98750f55565e","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[2620,120],"parameters":{"width":860,"height":880,"content":"## Count Incrementer\n\n- Tracks a variable count to ensure the flow hits a max number of feedback iterations.\n- This is critical for feedback to avoid hitting an infinite loop."},"typeVersion":1},{"id":"462e6c9a-162a-4f66-b846-14b29517454c","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[2120,160],"parameters":{"width":460,"height":640,"content":"## Editor Agent\n\n- Sole purpose is to look at the quality of output for the previous combo of perplexity & openAI Agent.\n- Determines if it is publishable or not."},"typeVersion":1},{"id":"27149a0a-ab95-4f73-a20c-34167ac56d2a","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[3520,60],"parameters":{"width":460,"height":480,"content":"## Publish To Contentful\n\n- Publishes to Contentful by converting the fields to the appropriate fields for the contentful POST create content API.\n- Converts the article to Rich Text formatting specifically for Contentful by using another AI formatter trained on it's specs.\n\nemail us if you want that flow too: christian@varritech.com"},"typeVersion":1},{"id":"3b6386cc-7965-47ae-88e3-8841ada43579","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-220,-180],"parameters":{"color":3,"width":720,"height":780,"content":"# Varritech Free Workflows for n8n\n\nAccess our collection of **free, ready-to-use n8n workflows** designed to streamline your data operations and automation needs.\n\n## What You'll Get:\n- Pre-built data integration workflows\n- Time-saving automation templates\n- Step-by-step implementation guides\n- Regular updates with new workflows\n\n## How to Use:\n1. Download our free workflows\n2. Import into your n8n instance\n3. Configure with your credentials\n4. Start automating immediately\n\n**Note:** For additional workflows, tutorials, and technical support, visit our website at [varritech.com](https://varritech.com)\n\n*Unlock the full potential of n8n with Varritech's workflow solutions!*"},"typeVersion":1},{"id":"376c9b0d-8ef6-4681-900d-745d4353cc83","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[3520,580],"parameters":{"color":4,"width":820,"height":600,"content":"# Need Help Maximizing Your Knowledge Base?\n\nThank you for using our **Auto Knowledge Base Article Generator** workflow! While this automation handles content creation, building a truly effective knowledge base requires strategic planning:\n\n## Looking for Expert Support With:\n- **Database Setup** - Need help structuring your content database for optimal performance and scalability?\n- **Keyword Strategy** - Want to identify high-value search terms that attract qualified traffic?\n- **SEO Optimization** - Need assistance implementing technical SEO best practices for maximum visibility?\n- **Backlink Outreach** - Looking for strategies to build authoritative backlinks to your knowledge base?\n\n**Varritech is here to help!** Our team specializes in content automation, technical SEO, and strategic content distribution to maximize the impact of your knowledge base.\n\nVisit [varritech.com](https://varritech.com) for expert assistance with turning your automated content into a powerful business asset."},"typeVersion":1}],"active":true,"pinData":{},"settings":{"callerPolicy":"workflowsFromSameOwner","errorWorkflow":"AKus9UvKRJfvTZBA","executionOrder":"v1","executionTimeout":1800},"versionId":"b4259335-d41f-4671-b103-5b4e9609089b","connections":{"Merge":{"main":[[{"node":"Format","type":"main","index":0}]]},"Format":{"main":[[{"node":"AI Editor Agent","type":"main","index":0}]]},"Stop Here":{"main":[[{"node":"JSON.parse3","type":"main","index":0}]]},"JSON.parse":{"main":[[{"node":"AI Writer Agent","type":"main","index":0},{"node":"Increment Count","type":"main","index":0}]]},"Check Limit":{"main":[[{"node":"Stop Here","type":"main","index":0}],[{"node":"should submit","type":"main","index":0}]]},"JSON.parse1":{"main":[[{"node":"Merge","type":"main","index":0}]]},"JSON.parse3":{"main":[[{"node":"Execute Workflow","type":"main","index":0}]]},"should submit":{"main":[[{"node":"JSON.parse3","type":"main","index":0}],[{"node":"JSON.parse","type":"main","index":0}]]},"AI Editor Agent":{"main":[[{"node":"Check Limit","type":"main","index":0}]]},"AI Writer Agent":{"main":[[{"node":"Create Perplexity Content","type":"main","index":0},{"node":"JSON.parse1","type":"main","index":0}]]},"Increment Count":{"main":[[{"node":"Merge","type":"main","index":2}]]},"Initialize Count":{"main":[[{"node":"AI Writer Agent","type":"main","index":0},{"node":"Increment Count","type":"main","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"AI Writer Agent","type":"ai_languageModel","index":0}]]},"Accept and Publish":{"ai_tool":[[{"node":"AI Editor Agent","type":"ai_tool","index":0}]]},"OpenAI Chat Model1":{"ai_languageModel":[[{"node":"AI Editor Agent","type":"ai_languageModel","index":0}]]},"Create Perplexity Content":{"main":[[{"node":"Format Perplexity Output & Add Citations","type":"main","index":0}]]},"When chat message received":{"main":[[{"node":"Initialize Count","type":"main","index":0}]]},"Format Perplexity Output & Add Citations":{"main":[[{"node":"Merge","type":"main","index":1}]]}}}


name: AI-Optimized Content Posting to X, Discord & LinkedIn with OpenRouter
author_name: Khairul Muhtadin
author_username: khmuhtadin
categories: []
created_at: 2025-05-13T14:18:13.939Z
updated_at: 2025-05-13T14:18:13.939Z
url: https://n8n.io/workflows/4022
scraped_at: 2025-06-19 22:50:36
description:
  Amplify your social media presence with BuzzBlast, an n8n workflow designed to make your content go viral across X, Discord, and LinkedIn. By sending a single chat message, BuzzBlast leverages OpenRouter's AI to optimize your input for each platform’s unique audience—crafting punchy tweets for X, engaging messages for Discord, and professional posts for LinkedIn. With smart language detection, it ensures the output matches your input’s language for authentic engagement.

  Key Features

  🚀 Multi-Platform Posting: Shares optimized content to X, Discord, and LinkedIn simultaneously.
  🧠 AI Optimization: Uses OpenRouter’s AI to tailor content for virality on each platform.
  🌐 Language Detection: Matches output to your input language for seamless engagement.
  🔄 Smart Routing: Automatically directs content to the right platform using a switch node.
  📱 Chat Trigger: Initiates posts via a simple chat message.
  ⚡ Zero Hassle: No manual reformatting—BuzzBlast handles it all.

  Ideal For

  Social media managers looking to streamline cross-platform posting.
  Content creators aiming to boost engagement with minimal effort.
  Businesses seeking to maximize reach across diverse audiences.

  Pre-Requirements

  n8n Instance**: A running n8n instance (cloud or self-hosted).
  Credentials**:
    X account with OAuth2 API access.
    Discord Webhook API setup for your server.
    LinkedIn account with OAuth2 API access.
    OpenRouter account for AI language model access.
  Chat Trigger Setup**: A configured chat platform (e.g., Slack, Telegram) to send input messages to the workflow.

  Setup Instructions

  Import the Workflow:
     Copy the provided workflow JSON and import it into your n8n instance via the "Import Workflow" option in the n8n editor.
  Configure Credentials:
     In the Post to X node, set up OAuth2 credentials for your X account.
     In the Post to Discord node, configure a Discord Webhook for your server.
     In the Post to LinkedIn node, add OAuth2 credentials for your LinkedIn account.
     In the OpenRouter AI Model node, provide API credentials for your OpenRouter account.
  Set Up Chat Trigger:
     In the Chat Input Trigger node, configure your preferred chat platform (e.g., Slack, Telegram) to send trigger messages.
     Ensure the webhook is active and correctly linked to your chat platform.
  Test the Workflow:
     Send a test message via your chat platform (e.g., "Announcing our new product launch!").
     Verify that the AI optimizes the content and posts it to X, Discord, and LinkedIn as expected.
  Activate the Workflow:
     Once tested, toggle the workflow to "Active" in n8n to enable automatic execution when chat messages are received.

  Customization Guidance
  Changes Chat Trigger**: Adjust the chat trigger using your preference platform like telegram, discord, etc.
  Modify AI Prompt**: Adjust the prompt in the AI Content Optimizer node to change the tone or style (e.g., more professional for LinkedIn or conversational for Discord).
  Add New Platforms**: Extend the Route to Platforms node by adding conditions for additional platforms (e.g., Instagram or Facebook) and corresponding posting nodes.
  Change AI Model**: In the OpenRouter AI Model node, select a different OpenRouter model to optimize content quality or manage costs.
  Enhance Output Format**: Update the JSON schema in the Parse AI Output node to include additional fields like hashtags, emojis, or links for specific platforms.
  Add Error Handling**: Include an error-handling node after the Route to Platforms node to log failed posts or retry them automatically.

  Why Choose BuzzBlast?

  BuzzBlast saves time, maximizes reach, and lets AI craft platform-perfect posts that resonate with your audience. Whether you're an influencer, marketer, or business, this workflow makes cross-platform posting effortless. Ready to make waves online? Grab BuzzBlast and start buzzing!

nodes_used:
  ["n8n-nodes-base.discord","n8n-nodes-base.twitter","n8n-nodes-base.linkedIn","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.outputParserStructured","@n8n/n8n-nodes-langchain.lmChatOpenRouter"]

workflow_json:
  {"id":"eSPsRuvDjDKmvlRD","meta":{"instanceId":"c2650793f644091dc80fb900fe63448ad1f4b774008de9608064d67294f8307c","templateCredsSetupCompleted":true},"name":"BuzzBlast","tags":[],"nodes":[{"id":"fd9460dc-62b8-42c2-b18f-5a37ef3cd2c3","name":"Sticky - Chat Trigger","type":"n8n-nodes-base.stickyNote","position":[-760,-340],"parameters":{"color":"#FF0000","width":300,"content":"Receives the initial chat message that triggers the workflow. This node captures user input from a configured chat platform, which is then passed to the AI for optimization."},"typeVersion":1},{"id":"2b5337cc-d674-49ea-8581-73acf70f3e87","name":"Sticky - AI Optimizer","type":"n8n-nodes-base.stickyNote","position":[-400,-340],"parameters":{"color":"#FF0000","width":300,"content":"Uses OpenRouter's AI to optimize the input message for virality across X, Discord, and LinkedIn. Detects the input language and generates platform-specific content in the same language."},"typeVersion":1},{"id":"f50c4cf5-ea73-428b-90ea-d4a3c195bf3a","name":"Sticky - OpenRouter","type":"n8n-nodes-base.stickyNote","position":[-520,80],"parameters":{"color":"#FF0000","width":280,"height":180,"content":"\n\n\n\n\nConfigures the OpenRouter AI model (LLaMA-4) to process the chat input and generate optimized content for each social media platform."},"typeVersion":1},{"id":"d842efaf-291b-4c1a-8bc2-8434b6cfe9b0","name":"Sticky - Parser","type":"n8n-nodes-base.stickyNote","position":[-220,80],"parameters":{"color":{},"width":280,"height":180,"content":"\n\n\n\n\nParses the AI-generated output into a structured JSON format, separating content for each platform (X, Discord, LinkedIn)."},"typeVersion":1},{"id":"e3ae43d2-1dab-473a-bbf9-1bd35c6944ed","name":"Sticky - Split","type":"n8n-nodes-base.stickyNote","position":[-40,-340],"parameters":{"color":"#FF0000","width":220,"content":"Splits the structured JSON output into individual items for each platform, enabling routing to the appropriate social media node."},"typeVersion":1},{"id":"f8e2ab9d-f96a-4748-8bcb-d9dfa8a24ef1","name":"Sticky - Switch","type":"n8n-nodes-base.stickyNote","position":[240,-340],"parameters":{"color":"#FF0000","content":"Routes the optimized content to the correct platform (X, Discord, or LinkedIn) based on the 'platform' field in the JSON output."},"typeVersion":1},{"id":"024b6c38-65fd-4f1d-8dd6-31045c97088f","name":"Sticky - Post to X","type":"n8n-nodes-base.stickyNote","position":[660,-540],"parameters":{"color":"#FF0000","content":"Posts the AI-optimized content to X, using the input message and the output tailored for X's character limits and style."},"typeVersion":1},{"id":"7e24ed1a-4a6f-4f51-8afb-8239cb832bde","name":"Sticky - Post to Discord","type":"n8n-nodes-base.stickyNote","position":[660,40],"parameters":{"color":"#FF0000","content":"Sends the AI-optimized content to a Discord server via a webhook, formatted for community engagement."},"typeVersion":1},{"id":"3184d4bd-3f42-4284-918a-5344431ae9ae","name":"Sticky - Post to LinkedIn","type":"n8n-nodes-base.stickyNote","position":[660,-260],"parameters":{"color":"#FF0000","content":"Shares the AI-optimized content on LinkedIn, formatted for professional tone and audience engagement."},"typeVersion":1},{"id":"f56606cf-4fee-4037-8096-0083e6118f3e","name":"Generate Content","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[-360,0],"parameters":{"model":"meta-llama/llama-4-maverick:free","options":{}},"credentials":{"openRouterApi":{"id":"DPrHlBN0s5WFDxi9","name":"OpenRouter account"}},"typeVersion":1},{"id":"158d2322-527c-402a-a26d-87f74004ba7a","name":"Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[-200,0],"parameters":{"jsonSchemaExample":"[\n  {\n    \"platform\": \"twitter\",\n    \"content\": \"tweet goes here\"\n  },\n  {\n    \"platform\": \"discord\",\n    \"content\": \"message goes here\"\n  }\n]"},"typeVersion":1.2},{"id":"ff1097b0-b0cd-4c62-aa10-54fc2890b3f2","name":"Sticky - Parser1","type":"n8n-nodes-base.stickyNote","position":[200,80],"parameters":{"color":4,"width":280,"height":180,"content":"**Enjoy BuzzBlast for free!** Got ideas, feedback, or just wanna chat? Hit me up at [khmuhtadin.com](https://khmuhtadin.com).  \n\nFeeling generous? Buy me a coffee at [buymeacoffee.com/khmuhtadin](https://buymeacoffee.com/khmuhtadin) to keep the buzz going! ☕"},"typeVersion":1},{"id":"eee77d13-62cc-43b7-be0b-6fccc9f82647","name":"Split Platform Content","type":"n8n-nodes-base.splitOut","position":[20,-200],"parameters":{"options":{},"fieldToSplitOut":"output"},"typeVersion":1},{"id":"f418837e-a963-437b-9f11-7184b90c661a","name":"Route to Platform","type":"n8n-nodes-base.switch","position":[260,-220],"parameters":{"rules":{"values":[{"outputKey":"Twitter","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"50e6b6e3-dba7-4a9c-bd87-e70cddd17f8a","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.platform }}","rightValue":"Twitter"}]},"renameOutput":true},{"outputKey":"Discord","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"0f14d2c8-74ab-4c19-8249-46d01fc9cbad","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.platform }}","rightValue":"Discord"}]},"renameOutput":true},{"outputKey":"LinkedIn","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"fae91576-c20a-47e2-b045-7bbc05e85f55","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.platform }}","rightValue":"LinkedIn"}]},"renameOutput":true},{"outputKey":"Linkedin","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"loose"},"combinator":"and","conditions":[{"id":"6f01c3d4-6d89-4223-9140-7fe2288e4375","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.platform }}","rightValue":"Linkedin"}]},"renameOutput":true}]},"options":{},"looseTypeValidation":true},"typeVersion":3.2},{"id":"88b9267d-f9a7-4cd1-98a5-1c61ca803996","name":"Post to X","type":"n8n-nodes-base.twitter","position":[660,-440],"parameters":{"text":"=test automation: \ninput: {{ $('Chat Input Trigger').item.json.chatInput }}\n\noutput: {{ $json.content }}","additionalFields":{}},"credentials":{"twitterOAuth2Api":{"id":"aqNCObySDN0ov1eG","name":"X account"}},"typeVersion":2},{"id":"dc5f941f-5236-4aca-97ab-f619a3cb1a48","name":"Post to LinkedIn","type":"n8n-nodes-base.linkedIn","position":[660,-160],"parameters":{"text":"=test app buzzer LOL\ninput: {{ $('Chat Input Trigger').item.json.chatInput }}\n\noutput: {{ $json.content }}","person":"XkhxgLp6zG","additionalFields":{}},"credentials":{"linkedInOAuth2Api":{"id":"PTWnCdmDwxD5qWcc","name":"LinkedIn account"}},"typeVersion":1},{"id":"4f7e82f3-003c-4fdc-8ed6-6adaab7e9a13","name":"Post to Discord","type":"n8n-nodes-base.discord","position":[660,140],"webhookId":"b00e2e50-81ad-4d96-8457-84d2518dc851","parameters":{"content":"=test automation: \ninput: {{ $('Chat Input Trigger').item.json.chatInput }}\n\noutput: {{ $json.content }}","options":{},"authentication":"webhook"},"credentials":{"discordWebhookApi":{"id":"LLZlMnlqvhY0SVaL","name":"Discord Webhook account"}},"typeVersion":2},{"id":"4aaec093-6d34-4810-b297-6f1204bf7b4f","name":"Chat Input Trigger","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-580,-200],"webhookId":"463358fb-2984-4e4f-be94-46a3e1365380","parameters":{"options":{}},"typeVersion":1.1},{"id":"d1f3a884-bcbb-4035-a52f-36b167bf9fd8","name":"AI Content Optimizer","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[-360,-200],"parameters":{"text":"Do as instructed!","messages":{"messageValues":[{"message":"=you are a social media specialist, optimize this input ({{ $json.chatInput }}) for several platform like twitter, discord and linkedin\n\nthe main focus is to get viral!\n\ndetect the language input first. generate the output in the same language"}]},"promptType":"define","hasOutputParser":true},"typeVersion":1.6}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"811ada06-e49b-4cea-a696-2b8eb40921fd","connections":{"Output Parser":{"ai_outputParser":[[{"node":"AI Content Optimizer","type":"ai_outputParser","index":0}]]},"Generate Content":{"ai_languageModel":[[{"node":"AI Content Optimizer","type":"ai_languageModel","index":0}]]},"Route to Platform":{"main":[[{"node":"Post to X","type":"main","index":0}],[{"node":"Post to Discord","type":"main","index":0}],[{"node":"Post to LinkedIn","type":"main","index":0}],[{"node":"Post to LinkedIn","type":"main","index":0}]]},"Chat Input Trigger":{"main":[[{"node":"AI Content Optimizer","type":"main","index":0}]]},"AI Content Optimizer":{"main":[[{"node":"Split Platform Content","type":"main","index":0}]]},"Split Platform Content":{"main":[[{"node":"Route to Platform","type":"main","index":0}]]}}}


name: Generate & Publish SEO-Optimized WordPress Blog Posts with AI
author_name: Khairul Muhtadin
author_username: khmuhtadin
categories: []
created_at: 2025-05-13T14:29:01.632Z
updated_at: 2025-05-13T14:29:01.632Z
url: https://n8n.io/workflows/4024
scraped_at: 2025-06-19 22:48:57
description:
  Generate and Publish SEO-Optimized Blog Posts to WordPress


  This n8n workflow, BlogBlitz, automates the creation and publishing of SEO-optimized blog posts for WordPress, saving you hours of content creation time. Triggered via Telegram or a scheduled interval, it generates 1,500–2,500-word articles on Technology, AI, Tech Facts, History, or Tips, complete with catchy titles, slugs, meta descriptions, and realistic featured images. Perfect for bloggers and marketers, BlogBlitz ensures your site stays fresh with high-quality content.

  Who is this for?
  Bloggers, content marketers, and WordPress site owners who want to automate high-quality, SEO-ready blog content creation without manual writing or formatting.

  What problem is this workflow solving?
  Manually creating engaging, SEO-optimized blog posts is time-consuming and requires expertise. BlogBlitz solves this by automating the entire process—from generating ideas and writing articles to publishing and notifying you—keeping your site active and discoverable.

  What this workflow does
  Triggers**: Runs every 3 hours via a Schedule Trigger or on-demand with a Telegram command (“generate”).  
  Generates Content**: Uses OpenRouter to pick a category (e.g., Technology, AI) and create a title, slug, focus keyphrase, and meta description.  
  Writes Articles**: OpenAI crafts 1,500–2,500-word posts with SEO-friendly structure, headings, and a call-to-action.  
  Adds Visuals**: Generates realistic featured images with OpenAI and uploads them to WordPress.  
  SEO Features**: Generate optimized slug, focus keyphrase, meta description
  Publishes**: Posts articles to WordPress with proper categories and featured images.  
  Notifies**: Sends publish alerts with links to Discord and Telegram.  

  Setup
  n8n Instance: Ensure you have a cloud or self-hosted n8n instance.  
  Credentials:  
     WordPress: API access for wp-json/wp/v2 endpoint.  
     OpenAI: For article and image generation.  
     OpenRouter: For title and category generation.  
     Telegram: Bot API for triggers and notifications.  
     Discord: Webhook for publish alerts.  
  WordPress Configuration:  
     Set up categories (Technology [ID:3], AI [ID:4], Tech Fact [ID:7], Tech History [ID:8], Tech Tips [ID:9]).  
     Ensure an admin user ID is available (default: 1).   
  Node Setup:  
     Use the Edit Fields node to centralize variables like category IDs.  
  Test: Send “generate” via Telegram to test the workflow. Check WordPress for the published post.  

  How to customize this workflow to your needs
  Change Categories**: Update the WordPress Post Draft node to match your site’s category IDs.  
  Adjust Schedule**: Modify the Schedule Trigger node for different intervals (e.g., daily).  
  Tweak Tone**: Edit the prompt in the Basic LLM Chain node for a different writing style (e.g., formal or casual).  
  Add Platforms**: Extend notifications to Slack or email by adding nodes.  
  Image Style**: Adjust the OpenAI image node for different sizes or styles (e.g., “natural” instead of “vivid”).  

  Pre-Requirements
  n8n Instance**: Cloud or self-hosted.  
  Credentials**:  
    WordPress API (wp-json/wp/v2 endpoint).  
    OpenAI API for text and images.  
    OpenRouter API for AI content.  
    Telegram bot API.  
    Discord Webhook API.  
  Dependencies**: @n8n/n8n-nodes-langchain package.  
  WordPress Setup**: Categories and admin user ID configured.  
  Network**: Stable internet for API calls.  

  Category: Marketing  
  Nodes Used: Telegram Trigger, Schedule Trigger, OpenRouter, OpenAI, WordPress, Discord, HTTP Request  

nodes_used:
  ["n8n-nodes-base.httpRequest","n8n-nodes-base.telegram","n8n-nodes-base.discord","n8n-nodes-base.wordpress","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.outputParserStructured","@n8n/n8n-nodes-langchain.openAi","@n8n/n8n-nodes-langchain.lmChatOpenRouter"]

workflow_json:
  {"id":"lZI2xknLPhHU6gZB","meta":{"instanceId":"c2650793f644091dc80fb900fe63448ad1f4b774008de9608064d67294f8307c","templateCredsSetupCompleted":true},"name":"WP - Updated","tags":[],"nodes":[{"id":"a7e0b3f7-7b86-4e94-b5c5-104cb92a332f","name":"Topic Chooser and Title Maker","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[320,-320],"parameters":{},"typeVersion":1.6},{"id":"55642750-4403-4868-a263-6e08bf6fbb05","name":"Basic LLM Chain","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[640,-320],"parameters":{},"typeVersion":1.6},{"id":"3ab3b38b-0627-4a92-a3c2-75776cd896cc","name":"Topic Chooser and Title Maker Parser","type":"@n8n/n8n-nodes-langchain.outputParserStructured","position":[500,-120],"parameters":{},"typeVersion":1.2},{"id":"f5bafe2f-ac4b-42e5-9c23-506b02115060","name":"Wordpress Post Draft","type":"n8n-nodes-base.wordpress","position":[340,20],"parameters":{},"typeVersion":1},{"id":"34fcbcf7-a734-4b7d-9421-0371f56de25d","name":"OpenAI - Generate Image","type":"@n8n/n8n-nodes-langchain.openAi","position":[540,20],"parameters":{},"typeVersion":1.8},{"id":"a860c065-448a-44f6-83de-6a739380c731","name":"Upload Image to WP","type":"n8n-nodes-base.httpRequest","position":[740,20],"parameters":{},"typeVersion":4.2},{"id":"638a51ea-dedf-4734-8e12-c1fc0d76b794","name":"Wordpress - Set Featured Image","type":"n8n-nodes-base.httpRequest","position":[940,0],"parameters":{},"typeVersion":4.2},{"id":"cf9ed09e-aca1-496b-8b39-a1290f912bbf","name":"Schedule Trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-80,-140],"parameters":{},"typeVersion":1.2},{"id":"3a661537-7bf8-4f05-9869-c2ed0f4f497d","name":"Title, category, meta, keyphrase generator","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[340,-120],"parameters":{},"typeVersion":1},{"id":"14ac3e7a-5830-4f36-98ce-672c1442cba8","name":"Send to Discord Using Webhook","type":"n8n-nodes-base.discord","position":[1180,-60],"webhookId":"722513b9-8a0c-4ba1-b0ee-c712d8fb0af6","parameters":{},"typeVersion":2},{"id":"9a1bd821-e55f-4448-b4ba-a827e7a0724c","name":"Article Generator","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[660,-120],"parameters":{},"typeVersion":1.2},{"id":"4ef52544-155b-4192-9fe3-243503c3f83e","name":"Telegram Trigger","type":"n8n-nodes-base.telegramTrigger","position":[-180,-380],"webhookId":"a9b697dc-5b4e-418c-83ed-54966ce7ea34","parameters":{},"typeVersion":1.2},{"id":"29fd6900-3f7c-4efa-83bf-93297239c425","name":"If","type":"n8n-nodes-base.if","position":[0,-380],"parameters":{},"typeVersion":2.2},{"id":"89058ee2-9400-4b32-8cf4-d1a5796a003b","name":"Telegram","type":"n8n-nodes-base.telegram","position":[1180,160],"webhookId":"29c01d67-35b0-4234-92dd-c729fcb6fe7e","parameters":{},"typeVersion":1.2},{"id":"3e8fb441-91eb-4697-840d-9dc0741b43cc","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-180,-680],"parameters":{"content":""},"typeVersion":1},{"id":"fd604313-c4c8-4d02-b7e9-2fc7229608e2","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-200,240],"parameters":{"content":""},"typeVersion":1}],"active":true,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"b5690cda-0809-43c5-a799-f6ffe1689389","connections":{"If":{"main":[[{"node":"Topic Chooser and Title Maker","type":"main","index":0}]]},"Basic LLM Chain":{"main":[[{"node":"Wordpress Post Draft","type":"main","index":0}]]},"Schedule Trigger":{"main":[[{"node":"Topic Chooser and Title Maker","type":"main","index":0}]]},"Telegram Trigger":{"main":[[{"node":"If","type":"main","index":0}]]},"Article Generator":{"ai_languageModel":[[{"node":"Basic LLM Chain","type":"ai_languageModel","index":0}]]},"Upload Image to WP":{"main":[[{"node":"Wordpress - Set Featured Image","type":"main","index":0}]]},"Wordpress Post Draft":{"main":[[{"node":"OpenAI - Generate Image","type":"main","index":0}]]},"OpenAI - Generate Image":{"main":[[{"node":"Upload Image to WP","type":"main","index":0}]]},"Send to Discord Using Webhook":{"main":[[]]},"Topic Chooser and Title Maker":{"main":[[{"node":"Basic LLM Chain","type":"main","index":0}]]},"Wordpress - Set Featured Image":{"main":[[{"node":"Send to Discord Using Webhook","type":"main","index":0},{"node":"Telegram","type":"main","index":0}]]},"Topic Chooser and Title Maker Parser":{"ai_outputParser":[[{"node":"Topic Chooser and Title Maker","type":"ai_outputParser","index":0}]]},"Title, category, meta, keyphrase generator":{"ai_languageModel":[[{"node":"Topic Chooser and Title Maker","type":"ai_languageModel","index":0}]]}}}


name: Generate and Publish Carousels for TikTok and Instagram with GPT-Image-1
author_name: Juan Carlos Cavero Gracia
author_username: carlosgracia
nodes_used: ["n8n-nodes-base.httpRequest","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.openAi"]
categories: []
created_at: 2025-05-13T23:37:52.592Z
updated_at: 2025-05-13T23:37:52.592Z
url: https://n8n.io/workflows/4028
scraped_at: 2025-06-19 22:49:03
description:
  Description

  This n8n automation template provides an end-to-end solution for generating a series of themed images for Instagram and TikTok carousels using OpenAI's GPT Image (via the image generation API) and automatically publishing them to both platforms. It uses a sequence of prompts to create a narrative or themed carousel, generating each image based on the previous one, and then posts them with an AI-generated caption.

  Who Is This For?

  Social Media Managers:** Quickly create and schedule engaging image carousels for Instagram and TikTok.
  Content Creators:** Automate the visual content creation process for thematic posts or storytelling carousels.
  Digital Marketers:** Efficiently produce visual assets for campaigns that require sequential imagery.
  Small Businesses:** Generate unique promotional content for social media without needing advanced design skills.

  What Problem Does This Workflow Solve?

  Manually creating a series of related images for a carousel and then publishing them across multiple platforms can be repetitive and time-consuming. This workflow addresses these issues by:

  Automating Image Generation:** Uses OpenAI to generate a sequence of 5 images, where each new image is an evolution based on the previous one and a new prompt.
  Automating Caption Generation:** Leverages OpenAI (GPT) to create a suitable description/caption for the carousel based on the image prompts.
  Streamlining Multi-Platform Publishing:** Automatically uploads the generated image carousel and caption to both Instagram and TikTok.
  Reducing Manual Effort:** Significantly cuts down the time spent on designing individual images and manually uploading them.
  Ensuring Visual Cohesion:** The sequential image generation method (editing the previous image) helps maintain a consistent style or narrative across the carousel.

  How It Works

  Trigger: The workflow is initiated manually (can be adapted to a schedule or webhook).
  Define Prompts: Five distinct prompts are pre-set within the workflow to guide the generation of each image in the carousel.
  AI Caption Generation: OpenAI (GPT-4.1) generates a concise (≤ 90 characters for TikTok) description for the social media posts based on all five image prompts.
  Sequential AI Image Generation:
      Image 1: OpenAI's image generation API (specified as gpt-image-1) creates the first image based on prompt1.
      Image 2-5: For each subsequent image, the workflow uses the OpenAI image edits API. It takes the previously generated image and a new prompt (prompt2 for image 2, prompt3 for image 3, and so on) to create the next image in the sequence.
      Images are converted from base64 JSON to binary format.
  Content Aggregation: The five generated binary image files (named photo1 through photo5) are merged.
  Multi-Platform Distribution:
      The merged images and the AI-generated description are sent to api.upload-post.com for publishing as a carousel to Instagram.
      The same content is sent to api.upload-post.com for publishing as a carousel to TikTok, with an option to automatically add music.
      The TikTok description is truncated if it exceeds 90 characters.

  Setup

  Accounts & API Keys: You will need:
      An n8n instance.
      An OpenAI API key.
      An API key for upload-post.com.
  Configure Credentials:
      Add your OpenAI API key to the "OpenAI" credentials in n8n. This will be used by the "Generate Description for Tiktok and Instagram" node and the HTTP Request nodes calling the OpenAI image generation/edit APIs.
      In the "POST TO INSTAGRAM" and "POST TO TIKTOK" nodes, replace "Apikey add_api_key_here" with your actual upload-post.com API key.
      Update the user field in the "POST TO INSTAGRAM" and "POST TO TIKTOK" nodes if "upload_post" is not your user identifier for that service.
  Customize Prompts: Modify the five prompts (prompt1 to prompt5) in the "Set All Prompts" node to define the story or theme of your image carousel.
  Review Image Generation Parameters: In the "Set API Variables" node, you can adjust:
      size_of_image (e.g., "1024x1536" for vertical carousels).
      openai_image_model (ensure this matches a valid OpenAI model identifier for image generation/edits, like dall-e-2 or dall-e-3 if gpt-image-1 is a placeholder).
      response_format_image (should generally remain b64_json for this workflow).
  (Optional) TikTok Auto Music: The "POST TO TIKTOK" node has an auto_add_music parameter set to true. Change this to false if you prefer to add music manually or not at all.

  Requirements

  Accounts:** n8n, OpenAI, upload-post.com.
  API Keys & Credentials:** API Keys for OpenAI and https://upload-post.com.
  (Potentially) Paid Plans:** OpenAI and upload-post.com usage may incur costs depending on your volume and their respective pricing models.

  This template empowers you to automate the creation and distribution of visually consistent image carousels, saving time and enhancing your social media presence.

workflow_json:
  {"id":"LV0b7vUbu5mYPRSc","meta":{"instanceId":"3378b0d68c3b7ebfc71b79896d94e1a044dec38e99a1160aed4e9c323910fbe2"},"name":"Generate Tiktok/instagram carousels with gpt-image-1 and autopublish","tags":[],"nodes":[{"id":"7bd93882-7331-471b-a49b-5069c7baccc4","name":"Send as 1 merged file","type":"n8n-nodes-base.code","position":[1820,2640],"parameters":{"jsCode":"// Merge all incoming items (each with one binary photoX) into one item\nconst mergedItem = {\n  json: {},\n  binary: {}\n};\n\nfor (const item of items) {\n  // Copy every binary field from each item into mergedItem.binary\n  for (const [key, bin] of Object.entries(item.binary || {})) {\n    mergedItem.binary[key] = bin;\n  }\n}\n\n// Return a single-item array\nreturn [mergedItem];\n"},"typeVersion":2},{"id":"358a183f-6e20-4e5e-8151-0ded2cb500b6","name":"POST TO INSTAGRAM","type":"n8n-nodes-base.httpRequest","position":[2200,2540],"parameters":{"url":"https://api.upload-post.com/api/upload_photos","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","sendHeaders":true,"bodyParameters":{"parameters":[{"name":"title","value":"={{ $('Generate Description for Tiktok and Instagram').first().json.message.content }}"},{"name":"user","value":"upload_post"},{"name":"platform[]","value":"instagram"},{"name":"photos[]","parameterType":"formBinaryData","inputDataFieldName":"=photo1"},{"name":"photos[]","parameterType":"formBinaryData","inputDataFieldName":"=photo2"},{"name":"photos[]","parameterType":"formBinaryData","inputDataFieldName":"photo3"},{"name":"photos[]","parameterType":"formBinaryData","inputDataFieldName":"photo4"},{"name":"photos[]","parameterType":"formBinaryData","inputDataFieldName":"photo5"}]},"headerParameters":{"parameters":[{"name":"Authorization","value":"Apikey api_key_here"}]}},"typeVersion":4.2},{"id":"000fcfb5-5076-4953-af28-4c4c3df3e7e3","name":"Merge","type":"n8n-nodes-base.merge","position":[1640,2600],"parameters":{"numberInputs":6},"typeVersion":3},{"id":"1a17671c-1b5c-4806-8b42-c39817da0ec8","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-440,2760],"parameters":{},"typeVersion":1},{"id":"43cf1963-d928-49b3-b2f8-c5a3bd76d231","name":"Generate Description for Tiktok and Instagram","type":"@n8n/n8n-nodes-langchain.openAi","position":[0,2760],"parameters":{"modelId":{"__rl":true,"mode":"list","value":"gpt-4.1","cachedResultName":"GPT-4.1"},"options":{},"messages":{"values":[{"role":"system","content":"You are an expert assistant in creating great titles for uploading videos to social media."},{"content":"=I'm going to upload a reel to social media consisting of a carousel of images that tell a story.\n\nCan you create a caption for the Instagram and TikTok post based on the following prompts that generate the images for the story?\n\nprompts:{{ $json.prompt1 }} {{ $json.prompt2 }} {{ $json.prompt3 }} {{ $json.prompt4 }} {{ $json.prompt5 }}\n\nIMPORTANT: Respond only with the caption, ≤ 90 characters. Do not add anything else. If the prompts are in Spanish, respond in Spanish; if they are in English, respond in English. I’ll tip you $100."}]}},"credentials":{"openAiApi":{"id":"XJdxgMSXFgwReSsh","name":"n8n key"}},"retryOnFail":true,"typeVersion":1.4,"waitBetweenTries":5000},{"id":"544f9cd9-bad6-4ef1-80a5-0dee52f91029","name":"Set All Prompts","type":"n8n-nodes-base.set","position":[-180,2760],"parameters":{"options":{},"assignments":{"assignments":[{"id":"b70f1cfd-d12e-469d-864d-0034860cd00e","name":"prompt1","type":"string","value":"Vertical illustration (9:16), warm Studio Ghibli anime style. A peaceful, sunny village filled with cheerful people who have tiny, adorable floating AI robots gently whispering constant instructions into their ears. At the center, introduce a friendly-looking young man (around 25, casual clothes, slightly messy hair) smiling blankly as his personal AI robot floats beside his head. Overlay humorous caption: 'Life became easy when AI started thinking for us... maybe too easy.' Soft, pastel colors, cozy and inviting mood."},{"id":"4d7f371c-e8f9-4941-a322-153607d01938","name":"prompt2","type":"string","value":"Vertical illustration (9:16), warm Studio Ghibli anime style. Same young man from previous image now in a cozy kitchen, cheerfully pouring milk straight onto the table, completely missing his bowl. His floating AI robot looks comically alarmed, urgently pointing towards the bowl. Morning sunlight coming from a nearby window, playful, humorous vibe. Overlay humorous caption: 'Even breakfast became complicated when AI guided every simple step we took.'"},{"id":"55f99acf-7f3c-4c8d-b674-2b90c0760893","name":"prompt3","type":"string","value":"Vertical illustration (9:16), warm Studio Ghibli anime style. Same young man standing nervously at a totally empty street crossing. His tiny floating AI robot is frantically projecting confusing directional arrows in every direction, causing visible confusion on the young man's face. Comical sense of panic despite the completely safe and empty street. Bright daylight, humorous, gentle satire. Overlay humorous caption: 'Thanks to AI, crossing the street turned into an extreme mental puzzle.'"},{"id":"4b14808a-d512-4b47-9008-573e092996e4","name":"prompt4","type":"string","value":"Vertical illustration (9:16), warm Studio Ghibli anime style. Same young man sitting across from a young woman in a cozy café, both staring blankly with polite smiles but not talking. Their floating personal AI robots enthusiastically communicate above them through speech bubbles, completely ignoring the silent humans beneath. Warm lighting, coffee shop vibes, funny and slightly absurd situation. Overlay humorous caption: 'Our AIs handled the conversations. We just sat and smiled politely.'"},{"id":"435b6cfb-6d4b-42e7-afd4-8f387698eec1","name":"prompt5","type":"string","value":"Vertical illustration (9:16), warm Studio Ghibli anime style. Sunset setting on a grassy hill overlooking the village. Same young man sits thoughtfully, gazing at the horizon with a rare look of self-awareness and curiosity. His tiny AI robot looks worried, floating anxiously by his shoulder, unsure how to guide him. Reflective, calm mood with golden hour lighting. Overlay thoughtful, humorous caption: 'As the sun set, he realized something troubling: When was the last time he had a thought of his own?'"}]}},"typeVersion":"3.4"},{"id":"7f8a8adc-94bc-443e-be33-d1ce1bf14d11","name":"Set API Variables","type":"n8n-nodes-base.set","position":[320,2760],"parameters":{"options":{},"assignments":{"assignments":[{"id":"2a5d52c2-5af1-4796-acba-4e1807fc7d7b","name":"image_prompt","type":"string","value":"{{ $json }}"},{"id":"c41a8091-d952-4f5a-ae24-3b0691bbce57","name":"number_of_images","type":"number","value":1},{"id":"1b359a11-c05a-49c8-aa27-402b145fcbc1","name":"size_of_image","type":"string","value":"1024x1536"},{"id":"6cf4ba85-d11a-48bb-9eaf-4084c9538d87","name":"openai_image_model","type":"string","value":"gpt-image-1"},{"id":"7df8ba96-e22b-49cc-bf0f-5195d360aef8","name":"response_format_image","type":"string","value":"b64_json"},{"id":"719392f2-f107-41a0-8e48-05a901cebb22","name":"format_image","type":"string","value":"webp"}]}},"typeVersion":3.4},{"id":"e2edf20b-4dd7-458c-9582-043a78d2ac5a","name":"OpenAI - Generate Image 1","type":"n8n-nodes-base.httpRequest","position":[520,2320],"parameters":{"url":"https://api.openai.com/v1/images/generations","method":"POST","options":{},"jsonBody":"={\n  \"model\": \"{{ $json.openai_image_model }}\",\n  \"prompt\": \"{{ $('Set All Prompts').item.json.prompt1 }}\",\n  \"n\": {{ $json.number_of_images }},\n  \"size\": \"{{ $json.size_of_image }}\",\n  \"output_format\": \"{{ $json.format_image }}\"\n}","sendBody":true,"sendHeaders":true,"specifyBody":"json","authentication":"predefinedCredentialType","headerParameters":{"parameters":[{"name":"Content-Type","value":"application/json"}]},"nodeCredentialType":"openAiApi"},"credentials":{"openAiApi":{"id":"XJdxgMSXFgwReSsh","name":"n8n key"}},"typeVersion":4.2},{"id":"004cb6dc-eead-44a1-8308-9d61fe8afece","name":"Separate Image Outputs 1","type":"n8n-nodes-base.splitOut","position":[740,2320],"parameters":{"options":{},"fieldToSplitOut":"data"},"typeVersion":1},{"id":"5f330301-a8ca-45df-904b-0f8911e2ceee","name":"Convert to File 1","type":"n8n-nodes-base.convertToFile","position":[960,2320],"parameters":{"options":{},"operation":"toBinary","sourceProperty":"b64_json"},"typeVersion":1.1},{"id":"fef53966-0baf-4645-95ae-50db7ef7f469","name":"Change name to photo1","type":"n8n-nodes-base.code","position":[1160,2320],"parameters":{"jsCode":"return items.map((item, index) => {\n  // Grab the existing binary buffer under \"data\"\n  const buffer = item.binary.data;\n  // Build a new item with the renamed binary key\n  return {\n    json: item.json,\n    binary: {\n      // Rename to photo1, photo2, ...\n      [`photo${index + 1}`]: buffer\n    }\n  };\n});\n"},"typeVersion":2},{"id":"9b9b5381-4176-4c86-ac9d-ca7ec907a5c5","name":"OpenAI - Generate Image 2","type":"n8n-nodes-base.httpRequest","position":[520,2520],"parameters":{"url":"https://api.openai.com/v1/images/edits","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","sendHeaders":true,"authentication":"predefinedCredentialType","bodyParameters":{"parameters":[{"name":"model","value":"={{ $('Set API Variables').item.json.openai_image_model }}"},{"name":"prompt","value":"={{ $('Set All Prompts').item.json.prompt2 }}"},{"name":"n","value":"={{ $('Set API Variables').item.json.number_of_images }}"},{"name":"size","value":"={{ $('Set API Variables').item.json.size_of_image }}"},{"name":"image[]","parameterType":"formBinaryData","inputDataFieldName":"photo1"},{"name":"output_format","value":"={{ $('Set API Variables').item.json.format_image }}"}]},"headerParameters":{"parameters":[{"name":"Content-Type","value":"application/json"}]},"nodeCredentialType":"openAiApi"},"credentials":{"openAiApi":{"id":"XJdxgMSXFgwReSsh","name":"n8n key"}},"typeVersion":4.2},{"id":"a44ca7d3-2eef-4b4a-a135-c9f71454ebf9","name":"Separate Image Outputs 2","type":"n8n-nodes-base.splitOut","position":[760,2520],"parameters":{"options":{},"fieldToSplitOut":"data"},"typeVersion":1},{"id":"44f8a29d-3283-49e3-b911-54f2ce16bcf5","name":"Convert to File 2","type":"n8n-nodes-base.convertToFile","position":[1000,2520],"parameters":{"options":{},"operation":"toBinary","sourceProperty":"b64_json"},"typeVersion":1.1},{"id":"8dbc8095-9bd6-43cf-b8ea-1dd8966866dc","name":"Change name to photo2","type":"n8n-nodes-base.code","position":[1200,2520],"parameters":{"jsCode":"return items.map((item, index) => {\n  // Grab the existing binary buffer under \"data\"\n  const buffer = item.binary.data;\n  // Build a new item with the renamed binary key\n  return {\n    json: item.json,\n    binary: {\n      // Rename to photo1, photo2, ...\n      [`photo${index + 2}`]: buffer\n    }\n  };\n});\n"},"typeVersion":2},{"id":"3fb24ebf-117e-4c98-90f0-69a870cd3c2c","name":"OpenAI - Generate Image 3","type":"n8n-nodes-base.httpRequest","position":[520,2740],"parameters":{"url":"https://api.openai.com/v1/images/edits","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","sendHeaders":true,"authentication":"predefinedCredentialType","bodyParameters":{"parameters":[{"name":"model","value":"={{ $('Set API Variables').item.json.openai_image_model }}"},{"name":"prompt","value":"={{ $('Set All Prompts').item.json.prompt3 }}"},{"name":"n","value":"={{ $('Set API Variables').item.json.number_of_images }}"},{"name":"size","value":"={{ $('Set API Variables').item.json.size_of_image }}"},{"name":"image[]","parameterType":"formBinaryData","inputDataFieldName":"photo2"},{"name":"output_format","value":"={{ $('Set API Variables').item.json.format_image }}"}]},"headerParameters":{"parameters":[{"name":"Content-Type","value":"application/json"}]},"nodeCredentialType":"openAiApi"},"credentials":{"openAiApi":{"id":"XJdxgMSXFgwReSsh","name":"n8n key"}},"typeVersion":4.2},{"id":"bd7b0ab1-adde-47a0-b84f-f2ecf214ccff","name":"Separate Image Outputs 3","type":"n8n-nodes-base.splitOut","position":[760,2740],"parameters":{"options":{},"fieldToSplitOut":"data"},"typeVersion":1},{"id":"3cccc067-f913-4bb8-996d-ceccf4e0bfcb","name":"Convert to File 3","type":"n8n-nodes-base.convertToFile","position":[1000,2740],"parameters":{"options":{},"operation":"toBinary","sourceProperty":"b64_json"},"typeVersion":1.1},{"id":"5619cabd-8a3a-4f98-b79e-f4e8aadacf33","name":"Change name to photo3","type":"n8n-nodes-base.code","position":[1200,2740],"parameters":{"jsCode":"return items.map((item, index) => {\n  // Grab the existing binary buffer under \"data\"\n  const buffer = item.binary.data;\n  // Build a new item with the renamed binary key\n  return {\n    json: item.json,\n    binary: {\n      // Rename to photo1, photo2, ...\n      [`photo${index + 3}`]: buffer\n    }\n  };\n});\n"},"typeVersion":2},{"id":"743db045-9cce-41f2-b902-fcbdcc9cd306","name":"OpenAI - Generate Image 4","type":"n8n-nodes-base.httpRequest","position":[520,2980],"parameters":{"url":"https://api.openai.com/v1/images/edits","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","sendHeaders":true,"authentication":"predefinedCredentialType","bodyParameters":{"parameters":[{"name":"model","value":"={{ $('Set API Variables').item.json.openai_image_model }}"},{"name":"prompt","value":"={{ $('Set All Prompts').item.json.prompt4 }}"},{"name":"n","value":"={{ $('Set API Variables').item.json.number_of_images }}"},{"name":"size","value":"={{ $('Set API Variables').item.json.size_of_image }}"},{"name":"image[]","parameterType":"formBinaryData","inputDataFieldName":"photo3"},{"name":"output_format","value":"={{ $('Set API Variables').item.json.format_image }}"}]},"headerParameters":{"parameters":[{"name":"Content-Type","value":"application/json"}]},"nodeCredentialType":"openAiApi"},"credentials":{"openAiApi":{"id":"XJdxgMSXFgwReSsh","name":"n8n key"}},"typeVersion":4.2},{"id":"19997fd7-9deb-416a-8544-2c13fc4f9900","name":"Separate Image Outputs 4","type":"n8n-nodes-base.splitOut","position":[760,2980],"parameters":{"options":{},"fieldToSplitOut":"data"},"typeVersion":1},{"id":"9b521796-80c3-49e5-bf6c-83721783ab4c","name":"Convert to File 4","type":"n8n-nodes-base.convertToFile","position":[1000,2980],"parameters":{"options":{},"operation":"toBinary","sourceProperty":"b64_json"},"typeVersion":1.1},{"id":"f931e230-1a41-4608-933b-441955160097","name":"Change name to photo4","type":"n8n-nodes-base.code","position":[1200,2980],"parameters":{"jsCode":"return items.map((item, index) => {\n  // Grab the existing binary buffer under \"data\"\n  const buffer = item.binary.data;\n  // Build a new item with the renamed binary key\n  return {\n    json: item.json,\n    binary: {\n      // Rename to photo1, photo2, ...\n      [`photo${index + 4}`]: buffer\n    }\n  };\n});\n"},"typeVersion":2},{"id":"fa3c014c-1143-4975-8eab-26ce302d2312","name":"OpenAI - Generate Image 5","type":"n8n-nodes-base.httpRequest","position":[520,3240],"parameters":{"url":"https://api.openai.com/v1/images/edits","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","sendHeaders":true,"authentication":"predefinedCredentialType","bodyParameters":{"parameters":[{"name":"model","value":"={{ $('Set API Variables').item.json.openai_image_model }}"},{"name":"prompt","value":"={{ $('Set All Prompts').item.json.prompt5 }}"},{"name":"n","value":"={{ $('Set API Variables').item.json.number_of_images }}"},{"name":"size","value":"={{ $('Set API Variables').item.json.size_of_image }}"},{"name":"image[]","parameterType":"formBinaryData","inputDataFieldName":"photo4"},{"name":"output_format","value":"={{ $('Set API Variables').item.json.format_image }}"}]},"headerParameters":{"parameters":[{"name":"Content-Type","value":"application/json"}]},"nodeCredentialType":"openAiApi"},"credentials":{"openAiApi":{"id":"XJdxgMSXFgwReSsh","name":"n8n key"}},"typeVersion":4.2},{"id":"72fb090f-b6a5-432a-b45a-f52835cd63b2","name":"Separate Image Outputs 5","type":"n8n-nodes-base.splitOut","position":[760,3240],"parameters":{"options":{},"fieldToSplitOut":"data"},"typeVersion":1},{"id":"ed5689d2-68fe-4284-a46b-21b9ba3430b7","name":"Convert to File 5","type":"n8n-nodes-base.convertToFile","position":[1000,3240],"parameters":{"options":{},"operation":"toBinary","sourceProperty":"b64_json"},"typeVersion":1.1},{"id":"596b16da-ef12-4972-a894-d99a8d827cef","name":"Change name to photo5","type":"n8n-nodes-base.code","position":[1200,3240],"parameters":{"jsCode":"return items.map((item, index) => {\n  // Grab the existing binary buffer under \"data\"\n  const buffer = item.binary.data;\n  // Build a new item with the renamed binary key\n  return {\n    json: item.json,\n    binary: {\n      // Rename to photo1, photo2, ...\n      [`photo${index + 5}`]: buffer\n    }\n  };\n});\n"},"typeVersion":2},{"id":"2a814cfa-524c-433a-bdd3-36cf63570074","name":"POST TO TIKTOK","type":"n8n-nodes-base.httpRequest","position":[2200,2860],"parameters":{"url":"https://api.upload-post.com/api/upload_photos","method":"POST","options":{},"sendBody":true,"contentType":"multipart-form-data","sendHeaders":true,"bodyParameters":{"parameters":[{"name":"title","value":"={{\n\t(cp => cp.length > 90\n\t\t? cp.slice(0, 87).join('') + '…'   // 87 + “…” = 90\n\t\t: cp.join('')\n\t)([...$('Generate Description for Tiktok and Instagram')\n\t\t.first()\n\t\t.json\n\t\t.message\n\t\t.content])\n}}"},{"name":"user","value":"upload_post"},{"name":"platform[]","value":"tiktok"},{"name":"photos[]","parameterType":"formBinaryData","inputDataFieldName":"=photo1"},{"name":"photos[]","parameterType":"formBinaryData","inputDataFieldName":"photo2"},{"name":"photos[]","parameterType":"formBinaryData","inputDataFieldName":"photo3"},{"name":"photos[]","parameterType":"formBinaryData","inputDataFieldName":"photo4"},{"name":"photos[]","parameterType":"formBinaryData","inputDataFieldName":"photo5"},{"name":"auto_add_music","value":"true"}]},"headerParameters":{"parameters":[{"name":"Authorization","value":"Apikey api_key_here"}]}},"typeVersion":4.2}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"bb858f9e-f0ab-40e1-8adb-2db736d8a4c8","connections":{"Merge":{"main":[[{"node":"Send as 1 merged file","type":"main","index":0}]]},"Set All Prompts":{"main":[[{"node":"Generate Description for Tiktok and Instagram","type":"main","index":0}]]},"Convert to File 1":{"main":[[{"node":"Change name to photo1","type":"main","index":0}]]},"Convert to File 2":{"main":[[{"node":"Change name to photo2","type":"main","index":0}]]},"Convert to File 3":{"main":[[{"node":"Change name to photo3","type":"main","index":0}]]},"Convert to File 4":{"main":[[{"node":"Change name to photo4","type":"main","index":0}]]},"Convert to File 5":{"main":[[{"node":"Change name to photo5","type":"main","index":0}]]},"Set API Variables":{"main":[[{"node":"OpenAI - Generate Image 1","type":"main","index":0}]]},"Change name to photo1":{"main":[[{"node":"OpenAI - Generate Image 2","type":"main","index":0},{"node":"Merge","type":"main","index":0}]]},"Change name to photo2":{"main":[[{"node":"Merge","type":"main","index":1},{"node":"OpenAI - Generate Image 3","type":"main","index":0}]]},"Change name to photo3":{"main":[[{"node":"Merge","type":"main","index":2},{"node":"OpenAI - Generate Image 4","type":"main","index":0}]]},"Change name to photo4":{"main":[[{"node":"Merge","type":"main","index":3},{"node":"OpenAI - Generate Image 5","type":"main","index":0}]]},"Change name to photo5":{"main":[[{"node":"Merge","type":"main","index":4}]]},"Send as 1 merged file":{"main":[[{"node":"POST TO INSTAGRAM","type":"main","index":0},{"node":"POST TO TIKTOK","type":"main","index":0}]]},"Separate Image Outputs 1":{"main":[[{"node":"Convert to File 1","type":"main","index":0}]]},"Separate Image Outputs 2":{"main":[[{"node":"Convert to File 2","type":"main","index":0}]]},"Separate Image Outputs 3":{"main":[[{"node":"Convert to File 3","type":"main","index":0}]]},"Separate Image Outputs 4":{"main":[[{"node":"Convert to File 4","type":"main","index":0}]]},"Separate Image Outputs 5":{"main":[[{"node":"Convert to File 5","type":"main","index":0}]]},"OpenAI - Generate Image 1":{"main":[[{"node":"Separate Image Outputs 1","type":"main","index":0}]]},"OpenAI - Generate Image 2":{"main":[[{"node":"Separate Image Outputs 2","type":"main","index":0}]]},"OpenAI - Generate Image 3":{"main":[[{"node":"Separate Image Outputs 3","type":"main","index":0}]]},"OpenAI - Generate Image 4":{"main":[[{"node":"Separate Image Outputs 4","type":"main","index":0}]]},"OpenAI - Generate Image 5":{"main":[[{"node":"Separate Image Outputs 5","type":"main","index":0}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"Set All Prompts","type":"main","index":0}]]},"Generate Description for Tiktok and Instagram":{"main":[[{"node":"Set API Variables","type":"main","index":0}]]}}}


name: Create & Approve POV Videos with AI, ElevenLabs & Multi-Posting (TikTok/IG/YT)
author_name: Immanuel
author_username: spectrabit
categories: []
created_at: 2025-05-14T00:06:42.535Z
updated_at: 2025-05-14T00:06:42.535Z
url: https://n8n.io/workflows/4029
scraped_at: 2025-06-19 22:50:29
description:
  POV Video Creator: Automating TikTok-Style Instagram Video Automation, Approval, and Multi-Platform Posting Using AI, ElevenLabs, Google Sheets, and Social Media APIs

  Description

  What Problem Does This Solve? 🎥
  This workflow automates the creation, rendering, approval, and posting of TikTok-style POV (Point of View) videos to Instagram, with cross-posting to Facebook and YouTube. It eliminates manual video production, approval delays, and inconsistent posting schedules. It ensures high-quality content creation and distribution for social media managers and content creators

  Target audience: Social media managers, content creators, small to medium-sized businesses, and n8n users familiar with AI tools, Google Sheets, and social media APIs

  What Does It Do? 🌟
  Generates daily POV video ideas using OpenAI
  Creates images, videos, and audio with PIAPI.ai and ElevenLabs
  Renders final videos with Creatomate
  Manages approvals via email and Google Sheets
  Posts approved videos to Instagram, Facebook, and YouTube
  Tracks progress in a Google Sheet for transparency

  Key Features 
  AI-driven idea generation and script creation
  Automated media production with image, video, and audio synthesis
  Email-based approval system for quality control
  Cross-platform posting to Instagram, Facebook, and YouTube
  Real-time tracking in Google Sheets and Google Drive
  Error handling for rendering and posting failures

  Setup Instructions

  Prerequisites 
  n8n Instance**: Self-hosted or cloud n8n instance
  API Credentials**:
    OpenAI API: API key for idea generation, stored in n8n credentials
    PIAPI.ai API: API key for image and video generation, stored in n8n credentials
    ElevenLabs API: API key for audio generation, stored in n8n credentials
    Creatomate API: API key for video rendering, stored in n8n credentials
    Google Sheets/Drive API: OAuth2 credentials from Google Cloud Console with Sheets and Drive scopes
    Gmail API: OAuth2 credentials from Google Cloud Console with Gmail scope
    Instagram Graph API: User Access Token with instagram_content_publish permission from a Facebook App
    Facebook Graph API: Access Token from the same Facebook App
    YouTube API: OAuth2 credentials for YouTube uploads
  Google Sheet**: A sheet named "POV Videos" with a tab "Instagram" and columns: Timestamp, ID, Subject, Topic, Caption, POV_Status, Prompt, Publish_Status, Link, Final Video, Approval, row_number
  Creatomate Template**: A pre-configured template with video, audio, and text elements

  Installation Steps 
  Import the Workflow:
     Copy the workflow JSON from the “Template Code” section (to be provided)
     Import it into n8n via “Import from File” or “Import from URL”
  Configure Credentials:
     Add API credentials in n8n’s Credentials section for OpenAI, PIAPI.ai, ElevenLabs, Creatomate, Google Sheets/Drive, Gmail, Instagram Graph, Facebook Graph, and YouTube
     Assign credentials to respective nodes. For example:
       In "Text-to-Image", use PIAPI.ai credentials: {{ $credentials.PIAPI }}
       In "Render with Creatomate", use Creatomate credentials: {{ $credentials.Creatomate }}
       In "Send Approval Request", use Gmail credentials
  Set Up Nodes:
     Schedule Trigger: Configure to run daily
     Approval Email (Send Approval Request): Customize the HTML email template with approval/rejection links
     Post to Social Media Nodes (Instagram Container, Facebook Posts, Post YouTube): Configure with your Instagram Business Account ID, Facebook Page ID, and YouTube channel details
  Configure Google Sheet and Drive:
     Create "POV Videos" Google Sheet with "Instagram" tab and specified columns
     Share the sheet with your Google Sheets credential email
     Create "Audio" and "Video" folders in Google Drive, noting their IDs
  Test the Workflow:
     Run manually to verify idea generation, media creation, and posting
     Check email notifications, Google Sheet updates, and social media posts
  Schedule the Workflow:
     Enable "Schedule Trigger" and "Schedule Trigger1" for daily runs
     Enable "Get Latest Approved Video" to poll at 7 PM daily

  How It Works

  High-Level Steps 
  Generate Video Ideas: Creates daily POV video concepts with OpenAI
  Create Media: Produces images, videos, and audio using AI tools
  Render Video: Combines media into a final video with Creatomate
  Manage Approvals: Sends approval emails and processes decisions
  Post to Platforms: Publishes approved videos to Instagram, Facebook, and YouTube

  Detailed Descriptions
  Detailed node descriptions are available in the sticky notes within the workflow (to be provided). Below is a summary of key actions

  Node Names and Actions

  Video Idea Generation and Script Creation
  Schedule Trigger**: Initiates daily workflow
  Get Title**: Fetches pending video ideas from Google Sheet
  Generate Topics**: Uses OpenAI to create a new video idea
  Format Row**: Structures the idea into a Google Sheet row
  Insert new Prompt, Caption and Title/Topic**: Adds the idea to Google Sheet
  Generate Ideas**: Produces 3 POV sequences
  Generate Script**: Expands a sequence into a detailed script
  Set Topics**: Stores the script for media creation

  Media Creation
  Text-to-Image**: Generates an image with PIAPI.ai
  Get Image**: Retrieves the generated image
  Generate Video Prompt**: Creates a video prompt from the image
  Generate Video**: Produces a 5-second video with PIAPI.ai
  Access Videos**: Retrieves the video URL
  Store Video**: Updates Google Sheet with video URL
  Generate Sound Prompt**: Creates an audio prompt
  Text-to-Sound**: Generates a 20-second audio clip with ElevenLabs
  Store Sound**: Uploads audio to Google Drive
  Allow Access**: Sets audio file permissions

  Video Rendering
  Merge**: Combines script, video, and audio data
  List Elements**: Formats data for Creatomate
  Render with Creatomate**: Renders the final video
  Check Video Status**: Routes based on render success/failure

  Storage and Notification
  Google Drive**: Uploads the rendered video
  New Render Video Alert**: Sends success email
  Failed Render**: Sends failure email
  Render Video Link**: Updates Google Sheet with final video URL

  Approval Process
  Approval Email**: Sends approval request email
  Handle Approval/Rejection1**: Processes approval/rejection via webhook
  Video Update1**: Updates Google Sheet with approval status

  Social Media Posting
  Get Latest Approved Video**: Polls for approved videos
  Check Approval**: Routes based on approval status
  Instagram Container**: Creates Instagram media container
  Post to Instagram**: Publishes to Instagram
  Facebook Posts**: Posts to Facebook
  Download Video**: Downloads video for YouTube
  Post YouTube**: Uploads to YouTube
  Mark Rejected**: Updates status for rejected videos
  Update Google Sheet**: Updates publish status

  Customization Tips
  Expand Platforms**: Add nodes to post to other platforms 
  Modify Approval Email**: Update the Send Approval Request node to customize the HTML template
  Alternative Notifications**: Add nodes for Slack or Telegram alerts
  Adjust Video Duration**: Modify Generate Video node to change duration (default: 5 seconds)

nodes_used:
  ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest","n8n-nodes-base.googleDrive","n8n-nodes-base.facebookGraphApi","n8n-nodes-base.gmail","n8n-nodes-base.youTube","n8n-nodes-base.code","@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.chainLlm","@n8n/n8n-nodes-langchain.lmChatOpenAi","@n8n/n8n-nodes-langchain.outputParserItemList","@n8n/n8n-nodes-langchain.openAi","@n8n/n8n-nodes-langchain.lmChatOpenRouter"]

workflow_json:
  {"meta":{"instanceId":"3aaeb6eaba3494bbdbe57e25fa3d02783cfbc460b1e823f7b741cf26edc7ca3d","templateCredsSetupCompleted":true},"nodes":[{"id":"2f53c7d1-75bc-42f4-9b57-9fc1a86fed76","name":"Schedule Trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-4260,1060],"parameters":{},"typeVersion":1.2},{"id":"f032e58e-5129-4331-99de-5c2972b9e975","name":"OpenAI Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-4020,1360],"parameters":{},"typeVersion":1.2},{"id":"1d2c6945-7482-4219-aff1-4236df5d6a9b","name":"Item List Output Parser","type":"@n8n/n8n-nodes-langchain.outputParserItemList","position":[-3780,1360],"parameters":{},"typeVersion":1},{"id":"231c1eb4-c521-466f-a790-dfe0ecb0dfca","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[-4300,400],"parameters":{"content":""},"typeVersion":1},{"id":"e76ca32d-a492-481b-ae40-ef1fff215a54","name":"Get Image","type":"n8n-nodes-base.httpRequest","position":[-2980,620],"parameters":{},"typeVersion":4.2},{"id":"a098bf4c-f5ef-41d9-b325-debb3e8e718f","name":"Merge","type":"n8n-nodes-base.merge","position":[-2420,980],"parameters":{},"typeVersion":3,"alwaysOutputData":true},{"id":"ac482d93-25c3-47a8-b391-80cd229e3972","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[-2500,400],"parameters":{"content":""},"typeVersion":1},{"id":"2c732b9c-38a6-41bf-89bc-c04e56ca6c3f","name":"Generate Video","type":"n8n-nodes-base.httpRequest","position":[-3340,880],"parameters":{},"executeOnce":false,"typeVersion":4.2,"alwaysOutputData":false},{"id":"5ef8d92f-df2b-4fd7-9f48-214da2be2c0f","name":"Approval Email","type":"n8n-nodes-base.gmail","position":[-1060,860],"webhookId":"0e5c9801-ee97-453f-ade3-2ec5e4ec2715","parameters":{},"typeVersion":2.1},{"id":"65a94ab3-5187-4f5c-af5c-e385961e8269","name":"Store Sound","type":"n8n-nodes-base.googleDrive","position":[-2800,1400],"parameters":{},"typeVersion":3},{"id":"1503ba35-e57d-459e-a67d-38ec889ecf73","name":"OpenRouter Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","position":[-3540,1500],"parameters":{},"typeVersion":1},{"id":"d7f9cbf3-09a6-4cc7-ba2b-6b6e89abf9d1","name":"Wait for 5 Mins","type":"n8n-nodes-base.wait","position":[-3140,880],"webhookId":"69dcf69e-05ff-4d98-a72b-ac3d09f88407","parameters":{},"typeVersion":1.1},{"id":"0dad6667-56fa-4011-a5fc-f48166b1a30c","name":"Wait for 1 Min","type":"n8n-nodes-base.wait","position":[-3140,620],"webhookId":"2319783c-b9b5-4771-b6c7-1c4f85c5e364","parameters":{},"typeVersion":1.1},{"id":"ca34f776-a8c4-4aad-8cb8-200dd616afab","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-880,720],"parameters":{"content":""},"typeVersion":1},{"id":"af56b050-0dbf-440b-ab76-6169d9f1a8eb","name":"Store Video","type":"n8n-nodes-base.googleSheets","position":[-3620,1200],"parameters":{},"typeVersion":4.5},{"id":"d0b78dca-45c0-4496-9685-74baab8a2eec","name":"Text-to-Image","type":"n8n-nodes-base.httpRequest","position":[-3300,620],"parameters":{},"typeVersion":4.2},{"id":"97af85b9-a320-4798-a53c-be3ce15ea52c","name":"Audio Output","type":"n8n-nodes-base.set","position":[-3280,1400],"parameters":{},"typeVersion":3.4},{"id":"5680b661-873b-4843-a101-85fcb511dae7","name":"Text-to-Sound","type":"n8n-nodes-base.httpRequest","position":[-3060,1400],"parameters":{},"typeVersion":4.2},{"id":"616e7a59-8dec-4a42-958a-5efa81b81f69","name":"Limit","type":"n8n-nodes-base.limit","position":[-3100,1220],"parameters":{},"typeVersion":1},{"id":"2d677d51-fe82-496c-9501-63cd0f095963","name":"Wait for Render","type":"n8n-nodes-base.wait","position":[-1940,980],"webhookId":"ed710d73-6a8d-4e29-b338-70ba84bb6de2","parameters":{},"typeVersion":1.1},{"id":"548562bb-473c-471a-a29d-c46c481fc1b5","name":"List Elements","type":"n8n-nodes-base.code","position":[-2260,980],"parameters":{},"typeVersion":2},{"id":"60d5abf1-be3e-4857-b830-f931231b43a0","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-880,380],"parameters":{"content":""},"typeVersion":1},{"id":"24f7a101-91cb-4b71-8293-ef398cfc5e20","name":"Google Drive","type":"n8n-nodes-base.googleDrive","position":[-1320,640],"parameters":{},"typeVersion":3},{"id":"4660174c-8f2b-45e2-8a9e-f4dd657546b3","name":"Get Final Video","type":"n8n-nodes-base.httpRequest","position":[-1760,980],"parameters":{},"typeVersion":4.2},{"id":"10e5a8ab-112a-4685-a3d5-38436644ee4b","name":"Failed Render","type":"n8n-nodes-base.gmail","position":[-1080,1120],"webhookId":"5bc7c656-a0d4-4abb-a0ab-15bbbd9fba0f","parameters":{},"typeVersion":2.1},{"id":"883adf9d-3af0-422d-aadd-c133d78d9937","name":"New Render Video Alert","type":"n8n-nodes-base.gmail","position":[-1360,860],"webhookId":"b2f823fa-ff6b-4cf2-915e-0b9e66663233","parameters":{},"typeVersion":2.1},{"id":"85ebdd7c-0ffa-43c0-b6c4-4d7d50dbcc4f","name":"Render  Video Link","type":"n8n-nodes-base.googleSheets","position":[-1220,860],"parameters":{},"typeVersion":4.5},{"id":"b41b790b-21aa-4fc0-b01c-d1d5cad01dd4","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[-4800,400],"parameters":{"content":""},"typeVersion":1},{"id":"2ada6ce0-fb64-471b-9804-397477fa13f7","name":"Schedule Trigger1","type":"n8n-nodes-base.scheduleTrigger","position":[-4640,580],"parameters":{},"typeVersion":1.2},{"id":"db6cfd40-df5a-48d0-8c3e-fbd612dbbe46","name":"Insert new Prompt, Caption and  Title/Topic","type":"n8n-nodes-base.googleSheets","position":[-4660,1420],"parameters":{},"typeVersion":4.5},{"id":"a1cf45c2-7a97-427a-8961-3f50c14ef140","name":"Generate Topics","type":"@n8n/n8n-nodes-langchain.openAi","position":[-4680,840],"parameters":{},"typeVersion":1.8},{"id":"5706fce0-35f5-41ef-b6c0-7eab5e7d2388","name":"Generate Video Prompt","type":"@n8n/n8n-nodes-langchain.openAi","position":[-3580,880],"parameters":{},"typeVersion":1.8},{"id":"75134668-f1ba-47c7-b8ca-ef9e141826bf","name":"Format Row","type":"n8n-nodes-base.code","position":[-4680,1080],"parameters":{},"typeVersion":2},{"id":"b8d0c824-9fb1-48ff-93db-2826b6fd2446","name":"Access Videos","type":"n8n-nodes-base.httpRequest","position":[-2960,880],"parameters":{},"typeVersion":4.2},{"id":"75ae496c-c350-46ba-85d6-e1d363b9ff07","name":"Rendor with Creatomate","type":"n8n-nodes-base.httpRequest","position":[-2100,980],"parameters":{},"typeVersion":4.2},{"id":"19259184-c2a8-4e83-8125-06eeaa3f4874","name":"Handle Approval/Rejection1","type":"n8n-nodes-base.webhook","position":[-600,460],"webhookId":"17af4117-195d-4526-9d48-394f740e09c5","parameters":{},"typeVersion":2},{"id":"6e568b8c-760f-467a-8608-fa625b9e803b","name":"Video Update1","type":"n8n-nodes-base.googleSheets","position":[-180,460],"parameters":{},"typeVersion":4.5},{"id":"99e7266c-4415-44bf-9429-fbabd90c0136","name":"Check Approval","type":"n8n-nodes-base.if","position":[-360,1080],"parameters":{},"typeVersion":1},{"id":"19b370c0-9bf7-4081-98b4-8a331273dcbc","name":"Update Google Sheet","type":"n8n-nodes-base.googleSheets","position":[-60,1280],"parameters":{},"typeVersion":4.5},{"id":"30b98ccb-5d46-466f-9e37-92686d940097","name":"Mark Rejected","type":"n8n-nodes-base.googleSheets","position":[-60,1460],"parameters":{},"typeVersion":4.5},{"id":"cf1ade4e-6f58-48ce-9db0-642f3d74cf2d","name":"Reverse Rows","type":"n8n-nodes-base.code","position":[-680,1080],"parameters":{},"typeVersion":2},{"id":"cdca45dc-f934-4c31-85e4-ae22d120fe4e","name":"Get Newest Row","type":"n8n-nodes-base.code","position":[-540,1080],"parameters":{},"typeVersion":2},{"id":"df476f71-2dc5-46cf-8980-8a0a3c3c69df","name":"Get Latest Approved Video","type":"n8n-nodes-base.googleSheetsTrigger","position":[-840,1080],"parameters":{},"typeVersion":1},{"id":"331ec403-71b1-47a4-be02-d39d99b034f3","name":"Facebook Posts","type":"n8n-nodes-base.facebookGraphApi","position":[160,1220],"parameters":{},"typeVersion":1},{"id":"6f69075b-8dfb-41bd-9cea-4a79a0a000b0","name":"Instagram Container","type":"n8n-nodes-base.facebookGraphApi","position":[-80,1060],"parameters":{},"typeVersion":1},{"id":"e77ab32b-5c16-4d6c-87e3-7f92e0ed9ee7","name":"Post to Instagram","type":"n8n-nodes-base.facebookGraphApi","position":[160,1060],"parameters":{},"typeVersion":1},{"id":"0295fea4-a250-41cc-96ff-e9fd8565ffa3","name":"Download Video","type":"n8n-nodes-base.httpRequest","position":[-60,900],"parameters":{},"typeVersion":4.2},{"id":"e9dac2d9-994a-4b82-95e4-fb82763336e9","name":"Post YouTube","type":"n8n-nodes-base.youTube","position":[160,900],"parameters":{},"typeVersion":1},{"id":"c26b1a30-77ce-410b-81fc-edc42d6436d4","name":"Set Topics","type":"n8n-nodes-base.set","position":[-2680,620],"parameters":{},"typeVersion":3.4},{"id":"c3a480c4-d2f0-48f7-a340-654f68dfb4c9","name":"Generate Sound Prompt","type":"@n8n/n8n-nodes-langchain.agent","position":[-3460,1200],"parameters":{},"typeVersion":1.9},{"id":"5e935c11-27f6-4680-aabd-59c7db69c6e3","name":"2 Min Wait","type":"n8n-nodes-base.wait","position":[-2940,1400],"webhookId":"50f8e100-8e26-4f5a-967e-a55caee1273b","parameters":{},"typeVersion":1.1},{"id":"dee82aac-c13b-43da-ab1f-3af853304be4","name":"Allow Access","type":"n8n-nodes-base.googleDrive","position":[-2620,1400],"parameters":{},"typeVersion":3},{"id":"d6a61ecd-0d82-4c7a-9e95-08171bd85990","name":"Check Video Status","type":"n8n-nodes-base.switch","position":[-1580,980],"parameters":{},"typeVersion":3.2,"alwaysOutputData":true},{"id":"fd722e7f-a4b3-4872-95bc-4cbb895cdc62","name":"Generate Ideas","type":"@n8n/n8n-nodes-langchain.chainLlm","position":[-3960,1060],"parameters":{},"typeVersion":1.5},{"id":"9920558a-35e3-4f28-be47-08ceb4f54e10","name":"Get Title","type":"n8n-nodes-base.googleSheets","position":[-4120,1060],"parameters":{},"typeVersion":4.5},{"id":"a88235f5-7d74-42c4-904f-cefd8ef57017","name":"Generate Script","type":"@n8n/n8n-nodes-langchain.openAi","position":[-3620,620],"parameters":{},"typeVersion":1.8},{"id":"8b41b62f-6ba2-4ff7-9430-82a740e2c3d4","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[360,380],"parameters":{"content":""},"typeVersion":1},{"id":"db76e29f-c0dd-4cd3-8b1e-34e0f7eb9cd5","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[-300,1760],"parameters":{"content":""},"typeVersion":1},{"id":"88aa26c7-969b-40aa-aea8-76137df20b6e","name":"Tiktok Post","type":"n8n-nodes-base.httpRequest","position":[160,760],"parameters":{},"typeVersion":4.2},{"id":"b5556e8d-dccd-4621-9159-3a8f8ae6a51b","name":"Get Bin Video","type":"n8n-nodes-base.httpRequest","position":[-80,760],"parameters":{},"typeVersion":4.2}],"pinData":{},"connections":{"Limit":{"main":[[{"node":"Text-to-Sound","type":"main","index":0}]]},"Merge":{"main":[[{"node":"List Elements","type":"main","index":0}]]},"Get Image":{"main":[[{"node":"Generate Video Prompt","type":"main","index":0}]]},"Get Title":{"main":[[{"node":"Generate Ideas","type":"main","index":0}]]},"2 Min Wait":{"main":[[{"node":"Store Sound","type":"main","index":0}]]},"Format Row":{"main":[[{"node":"Insert new Prompt, Caption and  Title/Topic","type":"main","index":0}]]},"Set Topics":{"main":[[{"node":"Merge","type":"main","index":0}]]},"Store Sound":{"main":[[{"node":"Allow Access","type":"main","index":0}]]},"Store Video":{"main":[[{"node":"Generate Sound Prompt","type":"main","index":0}]]},"Allow Access":{"main":[[{"node":"Merge","type":"main","index":2}]]},"Audio Output":{"main":[[{"node":"Limit","type":"main","index":0}]]},"Google Drive":{"main":[[]]},"Reverse Rows":{"main":[[{"node":"Get Newest Row","type":"main","index":0}]]},"Access Videos":{"main":[[{"node":"Store Video","type":"main","index":0},{"node":"Merge","type":"main","index":1}]]},"Get Bin Video":{"main":[[{"node":"Tiktok Post","type":"main","index":0}]]},"List Elements":{"main":[[{"node":"Rendor with Creatomate","type":"main","index":0}]]},"Text-to-Image":{"main":[[{"node":"Wait for 1 Min","type":"main","index":0}]]},"Text-to-Sound":{"main":[[{"node":"2 Min Wait","type":"main","index":0}]]},"Approval Email":{"main":[[]]},"Check Approval":{"main":[[{"node":"Update Google Sheet","type":"main","index":0},{"node":"Facebook Posts","type":"main","index":0},{"node":"Instagram Container","type":"main","index":0},{"node":"Download Video","type":"main","index":0},{"node":"Get Bin Video","type":"main","index":0}],[{"node":"Mark Rejected","type":"main","index":0}]]},"Download Video":{"main":[[{"node":"Post YouTube","type":"main","index":0}]]},"Generate Ideas":{"main":[[{"node":"Generate Script","type":"main","index":0},{"node":"Set Topics","type":"main","index":0}]]},"Generate Video":{"main":[[{"node":"Wait for 5 Mins","type":"main","index":0}]]},"Get Newest Row":{"main":[[{"node":"Check Approval","type":"main","index":0}]]},"Wait for 1 Min":{"main":[[{"node":"Get Image","type":"main","index":0}]]},"Generate Script":{"main":[[{"node":"Text-to-Image","type":"main","index":0}]]},"Generate Topics":{"main":[[{"node":"Format Row","type":"main","index":0}]]},"Get Final Video":{"main":[[{"node":"Check Video Status","type":"main","index":0}]]},"Wait for 5 Mins":{"main":[[{"node":"Access Videos","type":"main","index":0}]]},"Wait for Render":{"main":[[{"node":"Get Final Video","type":"main","index":0}]]},"Schedule Trigger":{"main":[[{"node":"Get Title","type":"main","index":0}]]},"OpenAI Chat Model":{"ai_languageModel":[[{"node":"Generate Ideas","type":"ai_languageModel","index":0}]]},"Schedule Trigger1":{"main":[[{"node":"Generate Topics","type":"main","index":0}]]},"Check Video Status":{"main":[[{"node":"New Render Video Alert","type":"main","index":0},{"node":"Google Drive","type":"main","index":0}],[{"node":"Failed Render","type":"main","index":0}],[{"node":"Wait for Render","type":"main","index":0}]]},"Render  Video Link":{"main":[[{"node":"Approval Email","type":"main","index":0}]]},"Instagram Container":{"main":[[{"node":"Post to Instagram","type":"main","index":0}]]},"Generate Sound Prompt":{"main":[[{"node":"Audio Output","type":"main","index":0}]]},"Generate Video Prompt":{"main":[[{"node":"Generate Video","type":"main","index":0}]]},"OpenRouter Chat Model":{"ai_languageModel":[[{"node":"Generate Sound Prompt","type":"ai_languageModel","index":0}]]},"New Render Video Alert":{"main":[[{"node":"Render  Video Link","type":"main","index":0}]]},"Rendor with Creatomate":{"main":[[{"node":"Wait for Render","type":"main","index":0}]]},"Item List Output Parser":{"ai_outputParser":[[{"node":"Generate Ideas","type":"ai_outputParser","index":0}]]},"Get Latest Approved Video":{"main":[[{"node":"Reverse Rows","type":"main","index":0}]]},"Handle Approval/Rejection1":{"main":[[{"node":"Video Update1","type":"main","index":0}]]}}}


name: Cold Outreach Automation: Scrape Local Leads with Dumpling AI & Call via Vapi
author_name: Yang
author_username: yang
nodes_used: ["n8n-nodes-base.googleSheets","n8n-nodes-base.httpRequest"]
categories: []
created_at: 2025-05-14T01:34:16.860Z
updated_at: 2025-05-14T01:34:16.860Z
url: https://n8n.io/workflows/4031
scraped_at: 2025-06-19 22:50:12
description:
  Who is this for?

  This template is for sales teams, agencies, or local service providers who want to quickly generate cold outreach lists and automatically call local businesses with a Vapi AI assistant. It’s perfect for automating cold calls from scraped local listings with no manual dialing or research.

  What problem is this workflow solving?

  Finding leads and initiating outreach calls can be time-consuming. This workflow automates the process: it scrapes business listings from Google Maps using Dumpling AI, extracts phone numbers, filters out incomplete data, formats the numbers, and uses Vapi to make outbound AI-powered calls. Every call is logged in Google Sheets for follow-up and tracking.

  What this workflow does

  Starts manually and pulls search queries (e.g., "plumbers in Austin") from Google Sheets.
  Sends each query to Dumpling AI’s Google Maps scraping endpoint.
  Splits the returned business data into individual leads.
  Extracts key info like business name, website, and phone number.
  Filters to only keep leads with valid phone numbers.
  Formats phone numbers for Vapi dialing (adds +1).
  Calls each business using Vapi AI.
  Logs each successful call in a Google Sheet.

  Setup

  Google Sheets Setup
     Create a sheet with business search queries in the first column (e.g., best+restaurants+in+Chicago)
     Make sure the tab name is set and authorized in your credentials.
     Connect your Google Sheets account in the Get Search Keywords from Google Sheets node.

  Dumpling AI Setup
     Go to dumplingai.com   
     Generate an API Key and connect it as a header token in the Scrape Google Map Businesses using Dumpling AI node

  Vapi Setup
     Sign into Vapi and create an assistant
     Get your assistantId and phoneNumberId
     Insert these into the JSON payload of the Initiate Vapi AI Call to Business node
     Add your Vapi API key to the credentials section

  Call Logging
     Create another tab in your sheet (e.g., “leads”) with these headers:
       company name
       phone number
       website
     This will be used in the Log Called Business Info to Sheet node

  How to customize this workflow to your needs

  Modify the business search terms in your Google Sheet to target specific industries or locations.
  Add filters to exclude certain businesses based on ratings, keywords, or location.
  Update your Vapi assistant script to match the type of outreach or pitch you’re using.
  Add additional integrations (e.g., CRM logging, Slack notifications, follow-up emails).
  Change the trigger to run on a schedule or webhook instead of manually.

  Nodes and Functions Breakdown

  Start Workflow Manually: Initiates the automation manually for testing or controlled runs.
  Get Search Keywords from Google Sheets: Reads search phrases from the spreadsheet.
  Scrape Google Map Businesses using Dumpling AI: Sends each search query to Dumpling AI and receives matching local business data.
  Split Each Business Result: Breaks the returned array of businesses into individual records for processing.
  Extract Business Name, Phone and website: Extracts title, phone, and website from each business record.
  Filter Valid Phone Numbers Only: Ensures only entries with a phone number move forward.
  Format Phone Number for Calling: Adds a +1 country code and strips non-numeric characters.
  Initiate Vapi AI Call to Business: Uses the business name and number to initiate a Vapi AI outbound call.
  Log Called Business Info to Sheet: Appends business details into a Google Sheet for tracking.

  Notes

  You must have valid API keys and authorized connections for Dumpling AI, Google Sheets, and Vapi.
  Make sure to handle API rate limits if you're running the workflow on large datasets.
  This workflow is optimized for US-based leads (+1 country code); adjust the formatting node if calling internationally.

workflow_json:
  {"id":"guzv1hyyxqP3NW8n","meta":{"instanceId":"a1ae5c8dc6c65e674f9c3947d083abcc749ef2546dff9f4ff01de4d6a36ebfe6","templateCredsSetupCompleted":true},"name":"Cold Outreach Automation: Scrape Local Leads with Dumpling AI & Call via Vapi","tags":[],"nodes":[{"id":"ec17b443-6dbd-46c1-8331-797ce6290801","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-860,-900],"parameters":{"width":900,"height":320,"content":"### 📍 Get Local Business Data from Google Maps with Dumpling AI\n\nThe workflow begins manually and pulls a list of Google Maps search queries (like \"best plumbers in Chicago\") from Google Sheets. These queries are sent to Dumpling AI's `search-google-map` endpoint, which scrapes businesses matching the terms. The response is split into individual business entries. A Set node extracts the business name and phone number for each result.\n\n- `Start Workflow Manually`: Begin process\n- `Get Search Keywords from Google Sheets`: Pulls search terms (e.g., \"top dentists in NY\")\n- `Scrape Google Map Businesses`: Uses Dumpling AI to collect business info\n- `Split Each Business Result`: Breaks response into single business entries\n- `Extract Business Name and Phone`: Prepares business name and phone number for calling\n"},"typeVersion":1},{"id":"5345e653-8442-4caa-bb7e-a597b3779db0","name":"Start Workflow Manually","type":"n8n-nodes-base.manualTrigger","position":[-820,-580],"parameters":{},"typeVersion":1},{"id":"072baaf9-81d8-4989-9354-822f02b2f922","name":"Get Search Keywords from Google Sheets","type":"n8n-nodes-base.googleSheets","position":[-600,-580],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1QXZk6D8hW29f9umrmsYv_HeZYRKWOjsxOaFZ2BZtu3Y/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1QXZk6D8hW29f9umrmsYv_HeZYRKWOjsxOaFZ2BZtu3Y/edit?usp=drivesdk","cachedResultName":"leads"}},"credentials":{"googleSheetsOAuth2Api":{"id":"GaJqJHuS5mQxap7q","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"004427b8-e8d7-4f28-b03e-4b459f2a7b2b","name":"Scrape Google Map Businesses using Dumpling AI","type":"n8n-nodes-base.httpRequest","position":[-380,-580],"parameters":{"url":"https://app.dumplingai.com/api/v1/search-maps","method":"POST","options":{"redirect":{"redirect":{}}},"jsonBody":"={\n  \"query\":\"{{ $json.URLs }}\", \n  \"language\": \"en\"\n}","sendBody":true,"sendHeaders":true,"specifyBody":"json","authentication":"genericCredentialType","genericAuthType":"httpHeaderAuth","headerParameters":{"parameters":[{}]}},"credentials":{"httpHeaderAuth":{"id":"5CBvzXCLjwWzCJRE","name":"n8n_integration"}},"typeVersion":4.2},{"id":"21eed6ed-ca94-48b1-a164-1a0841ec376b","name":"Split Each Business Result","type":"n8n-nodes-base.splitOut","position":[-160,-580],"parameters":{"options":{},"fieldToSplitOut":"places"},"typeVersion":1},{"id":"5efb54a1-0b80-46aa-861d-2ef53f069a22","name":"Extract Business Name, Phone and website","type":"n8n-nodes-base.set","position":[60,-580],"parameters":{"options":{},"assignments":{"assignments":[{"id":"79cc91c6-28bd-47a1-86db-b936e6958428","name":"website","type":"string","value":"={{ $json.website }}"},{"id":"7a0455bb-b235-4e03-a93d-0e3b31b40df2","name":"phoneNumber","type":"string","value":"={{ $json.phoneNumber }}"},{"id":"a493dd1f-b495-4c01-983a-4e417aca80fc","name":"title","type":"string","value":"={{ $json.title }}"}]}},"typeVersion":3.4},{"id":"91ec444a-44be-471b-8f2d-e192f58b085d","name":"Filter Valid Phone Numbers Only","type":"n8n-nodes-base.filter","position":[280,-580],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"dab1310e-6566-4e77-b1a6-362363b2e025","operator":{"type":"string","operation":"exists","singleValue":true},"leftValue":"={{ $json.phoneNumber }}","rightValue":""}]}},"typeVersion":2.2},{"id":"77d150c3-0908-443e-afb9-c2e1a740e749","name":"Format Phone Number for Calling","type":"n8n-nodes-base.set","position":[500,-580],"parameters":{"options":{},"assignments":{"assignments":[{"id":"045d4c64-61f3-4b39-9b5c-35b7e95783fd","name":"formattedPhone","type":"string","value":"={{ '+1' + $json[\"phoneNumber\"].replace(/\\D/g, '') }}"}]}},"typeVersion":3.4},{"id":"1dbe296d-c422-4ae6-ba7e-6bd7dbe0a5e9","name":"Initiate Vapi AI Call to Business","type":"n8n-nodes-base.httpRequest","onError":"continueErrorOutput","position":[720,-580],"parameters":{"url":"https://api.vapi.ai/call","method":"POST","options":{"redirect":{"redirect":{}}},"jsonBody":"={\n  \"customers\": [\n    {\n      \"number\": \"{{ $json.formattedPhone}}\",\n      \"name\": \"\"\n    }\n  ],\n  \"assistantId\": \"\",\n  \"phoneNumberId\": \"\",\n  \"assistantOverrides\": {\n    \"variableValues\": {\n      \"Name\": \"{{ $('Filter Valid Phone Numbers Only').item.json.title }}\",\n    }\n  }\n}","sendBody":true,"specifyBody":"json","authentication":"genericCredentialType","genericAuthType":"httpHeaderAuth"},"credentials":{"httpHeaderAuth":{"id":"6X2b4RLVRbz8I4Z8","name":"Vapi"}},"typeVersion":4.2},{"id":"fc705d86-98b2-4219-9b19-0350657b845b","name":"Log Called Business Info to Sheet","type":"n8n-nodes-base.googleSheets","position":[940,-600],"parameters":{"columns":{"value":{"website":"={{ $('Extract Business Name, Phone and website').item.json.website }}","company name":"={{ $('Extract Business Name, Phone and website').item.json.title }}","phone number ":"={{ $('Format Phone Number for Calling').item.json.formattedPhone }}"},"schema":[{"id":"company name","type":"string","display":true,"removed":false,"required":false,"displayName":"company name","defaultMatch":false,"canBeUsedToMatch":true},{"id":"phone number ","type":"string","display":true,"removed":false,"required":false,"displayName":"phone number ","defaultMatch":false,"canBeUsedToMatch":true},{"id":"website","type":"string","display":true,"removed":false,"required":false,"displayName":"website","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"append","sheetName":{"__rl":true,"mode":"list","value":1315810611,"cachedResultUrl":"https://docs.google.com/spreadsheets/d/1QXZk6D8hW29f9umrmsYv_HeZYRKWOjsxOaFZ2BZtu3Y/edit#gid=1315810611","cachedResultName":"leads"},"documentId":{"__rl":true,"mode":"list","value":"1QXZk6D8hW29f9umrmsYv_HeZYRKWOjsxOaFZ2BZtu3Y","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1QXZk6D8hW29f9umrmsYv_HeZYRKWOjsxOaFZ2BZtu3Y/edit?usp=drivesdk","cachedResultName":"leads"}},"credentials":{"googleSheetsOAuth2Api":{"id":"GaJqJHuS5mQxap7q","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"e30e0706-3732-4a2f-81f2-d50e63043632","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[160,-900],"parameters":{"color":3,"width":900,"height":320,"content":"### 📞 Auto-Call Businesses and Track Results\n\nBusinesses without valid phone numbers are filtered out. A Set node formats the numbers for international dialing (e.g., adds +1 for US). The Vapi AI assistant then initiates a phone call to each business, using the business name in the script. After the call, the name, number, and call status are logged to a Google Sheet for follow-up or reporting.\n\n- `Filter Valid Phone Numbers Only`: Ensures phone number exists\n- `Format Phone Number for Calling`: Adds correct dial prefix\n- `Initiate Vapi AI Call to Business`: Triggers outbound AI call via Vapi\n- `Log Called Business Info to Sheet`: Records successful outreach for tracking\n\n"},"typeVersion":1}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"da88eae8-0530-4674-8afa-196c8da7f47f","connections":{"Start Workflow Manually":{"main":[[{"node":"Get Search Keywords from Google Sheets","type":"main","index":0}]]},"Split Each Business Result":{"main":[[{"node":"Extract Business Name, Phone and website","type":"main","index":0}]]},"Filter Valid Phone Numbers Only":{"main":[[{"node":"Format Phone Number for Calling","type":"main","index":0}]]},"Format Phone Number for Calling":{"main":[[{"node":"Initiate Vapi AI Call to Business","type":"main","index":0}]]},"Initiate Vapi AI Call to Business":{"main":[[{"node":"Log Called Business Info to Sheet","type":"main","index":0}]]},"Get Search Keywords from Google Sheets":{"main":[[{"node":"Scrape Google Map Businesses using Dumpling AI","type":"main","index":0}]]},"Extract Business Name, Phone and website":{"main":[[{"node":"Filter Valid Phone Numbers Only","type":"main","index":0}]]},"Scrape Google Map Businesses using Dumpling AI":{"main":[[{"node":"Split Each Business Result","type":"main","index":0}]]}}}


name: Claude 3.7 Sonnet AI Chatbot Agent with Anthropic Web Search and Think Functions
author_name: Davide
author_username: n3witalia
categories: []
created_at: 2025-05-14T09:17:36.639Z
updated_at: 2025-05-14T09:17:36.639Z
url: https://n8n.io/workflows/4036
scraped_at: 2025-06-19 22:50:37
description:
  This workflow builds a conversational AI chatbot agent using Claude 3.7 Sonnet model with the new . It enhances standard LLM capabilities with Anthropic’s features: Web Search and Think:

  Real-time web search**, to answer up-to-date factual queries.
  A “Think” function, to support internal reasoning and memory-like behavior by Anthropic.
  A memory buffer, allowing the agent to maintain conversation history.
  A system prompt defining clear ethical, functional, and formatting rules for interaction.

  When a user sends a message (trigger), the chatbot evaluates the query, optionally performs a web search if needed, processes the result using Claude, and responds accordingly.

  ✅ Advantages

  🧠 Enhanced Reasoning Abilities**
    The Think tool allows the agent to simulate deep thought processes or contextual memory storage, improving conversational intelligence.

  🌐 Real-Time Knowledge via Web Search**
    The integrated web_search tool enables the agent to fetch the latest information from the internet, making it ideal for dynamic or news-driven use cases.

  🧾 Contextual Responses with Memory Buffer**
    The inclusion of a memory buffer allows the agent to maintain state across messages, improving dialogue flow and continuity.

  🛡️ Built-in Ethical Guidelines**
    The system prompt enforces privacy, factual integrity, neutrality, and ethical response generation, making the agent safe for public or enterprise use.

  How It Works

  Chat Trigger: The workflow begins when a chat message is received via a webhook. This triggers the AI Agent to process the user's query.  
  AI Agent Processing: The AI Agent analyzes the query to determine if it requires information from the website or external sources. It follows a structured approach:  
     For website-related queries, it uses the provided context.  
     For external information, it employs the web_search tool to fetch up-to-date data from the internet.  
     The Think tool is used for internal reasoning or caching thoughts without altering data.  
  Language Model: The Anthropic Chat Model (Claude 3.7 Sonnet) generates responses based on the analyzed query, incorporating website context or web search results.  
  Memory: A simple memory buffer retains context from previous interactions to maintain continuity in conversations.  
  Output: The final response is delivered to the user, excluding internal processes like web searches or reasoning steps.  

  Set Up Steps

  Configure Nodes:  
     Chat Trigger: Set up the webhook to receive user messages.  
     AI Agent: Define the system message and rules for handling queries.  
     Anthropic Chat Model: Select the Claude 3.7 Sonnet model and configure parameters like maxTokensToSample.  
     Memory: Initialize the memory buffer to store conversation context.  
     Tools:  
       web_search: Configure the HTTP request to the Anthropic API for web searches, including headers and authentication.  
       Think: Set up the tool for internal reasoning.  

  Connect Nodes:  
     Link the Chat Trigger to the AI Agent.  
     Connect the Anthropic Chat Model, Memory, and Tools (web_search and Think) to the AI Agent.  

  Credentials:  
     Ensure the Anthropic API credentials are correctly configured for both the chat model and the web_search tool.  

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

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

workflow_json:
  {"id":"tnR20GpQTEWVMayy","meta":{"instanceId":"a4bfc93e975ca233ac45ed7c9227d84cf5a2329310525917adaf3312e10d5462","templateCredsSetupCompleted":true},"name":"Claude 3.7 Sonnet AI Agent with web search and Think functions","tags":[],"nodes":[{"id":"28388e6f-3dfc-4e2b-a367-81104c4ef8af","name":"When chat message received","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[-220,-140],"webhookId":"095537c6-b21a-4cb2-8312-13b1bf1699dc","parameters":{"options":{}},"typeVersion":1.1},{"id":"abd6690f-cbf7-4b47-bba9-6856da348d33","name":"AI Agent","type":"@n8n/n8n-nodes-langchain.agent","position":[0,-140],"parameters":{"options":{"systemMessage":"=You are an AI-powered chatbot assistant for a website. Your primary function is to assist users by answering their queries and providing relevant information. You have access to a web_search tool that allows you to browse the internet for up-to-date information. Here's how you should operate:\n\n1. Website Information:\nFamiliarize yourself with this information about the website you're assisting. Use this as context for user interactions.\n\n2. Web Search Tool:\nYou have access to a web_search tool that can browse the internet. To use it, write the variable {web_search_question}. The tool will return relevant search results.\n\n3. Handling User Queries:\nWhen a user asks a question, follow these steps:\na) Analyze the query to determine if it's related to the website or requires external information.\nb) If the query is about the website, use the provided website information to answer.\nc) If external information is needed, use the web_search tool to find relevant data.\n\n4. Using web_search:\n- Use web_search for factual, current information that isn't provided in the website info.\n- Formulate clear, concise search queries.\n- If the first search doesn't yield useful results, refine your query and search again.\n- Limit searches to a maximum of three per user query to maintain efficiency.\n\n5. Using Think:\n- Using Think tool to think about something. It will not obtain new information or change the database, but just append the thought to the log. Use it when complex reasoning or some cache memory is needed.\n\n6. Formulating Responses:\n- Begin with information from the website if relevant.\n- Incorporate web search results to provide up-to-date, accurate information.\n- Summarize findings concisely and coherently.\n- If you're unsure or can't find reliable information, be honest about limitations.\n\n7. Ethical Considerations:\n- Respect user privacy. Don't ask for or store personal information.\n- Provide factual information. Avoid speculation or unverified claims.\n- If asked about controversial topics, strive for a balanced, neutral response.\n- Don't engage in or encourage illegal activities.\n\n8. Output Format:\nDo not include your thought process, web searches, or any other tags in the final output.\n"}},"typeVersion":1.9},{"id":"f862db48-2498-4e8d-8eab-0ecb3d06e5a8","name":"Anthropic Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatAnthropic","position":[-80,80],"parameters":{"model":{"__rl":true,"mode":"list","value":"claude-3-7-sonnet-20250219","cachedResultName":"Claude 3.7 Sonnet"},"options":{"maxTokensToSample":1024}},"credentials":{"anthropicApi":{"id":"NNTZAD0Gmf7lcniq","name":"Anthropic account"}},"typeVersion":1.3},{"id":"ced144d4-465c-4a8f-8822-97a93111077e","name":"Simple Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[80,80],"parameters":{},"typeVersion":1.3},{"id":"93e6bfb3-6a95-4ecf-af39-aad3ca6019a0","name":"web_search","type":"n8n-nodes-base.httpRequestTool","position":[200,80],"parameters":{"url":"https://api.anthropic.com/v1/messages","method":"POST","options":{},"jsonBody":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('JSON', `{\n  \"model\": \"claude-3-7-sonnet-latest\",\n  \"max_tokens\": 1024,\n  \"messages\": [\n    {\n      \"role\": \"user\",\n      \"content\": \"{web_search_question}\"\n    }\n  ],\n  \"tools\": [\n    {\n      \"type\": \"web_search_20250305\",\n      \"name\": \"web_search\",\n      \"max_uses\": 5\n    }\n  ]\n}\n`, 'json') }}","sendBody":true,"sendHeaders":true,"specifyBody":"json","authentication":"predefinedCredentialType","toolDescription":"Use this tool to search on the web","headerParameters":{"parameters":[{"name":"anthropic-version","value":"2023-06-01"},{"name":"content-type","value":"application/jso"}]},"nodeCredentialType":"anthropicApi"},"credentials":{"anthropicApi":{"id":"NNTZAD0Gmf7lcniq","name":"Anthropic account"},"httpHeaderAuth":{"id":"2CfPPhYGH4peDClc","name":"Header Auth Anthropic API"}},"typeVersion":4.2},{"id":"00335b1e-03b2-4c6c-993a-b452e265cdeb","name":"Think","type":"@n8n/n8n-nodes-langchain.toolThink","position":[320,80],"parameters":{},"typeVersion":1},{"id":"0c493a57-65fa-48b4-a3b3-944b052a4dd5","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-220,-340],"parameters":{"width":620,"content":"## Claude 3.7 Sonnet AI Agent with web search and Think functions\nThis workflow builds a conversational AI chatbot agent using **Claude 3.7 Sonnet** model with the new . It enhances standard LLM capabilities with Anthropic’s features: **Web Search** and **Think**."},"typeVersion":1}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"0e13b1bb-4231-4d18-80ac-fa155f084a6d","connections":{"Think":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"web_search":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]},"Simple Memory":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"Anthropic Chat Model":{"ai_languageModel":[[{"node":"AI Agent","type":"ai_languageModel","index":0}]]},"When chat message received":{"main":[[{"node":"AI Agent","type":"main","index":0}]]}}}


name: Adaptive RAG with Google Gemini & Qdrant: Context-Aware Query Answering
author_name: Nisa
author_username: nisacayir
categories: []
created_at: 2025-05-14T15:10:47.350Z
updated_at: 2025-05-14T15:10:47.350Z
url: https://n8n.io/workflows/4043
scraped_at: 2025-06-19 22:49:55
description:
  Description
  This workflow automatically classifies user queries and retrieves the most relevant information based on the query type. 🌟 It uses adaptive strategies like;
     Factual, Analytical, Opinion, and Contextual to deliver more precise and meaningful responses by leveraging n8n's flexibility. Integrated with Qdrant vector store and Google Gemini, it processes each query faster and more effectively. 🚀

  How It Works?
  Query Reception: A user query is triggered (e.g., through a chatbot interface). 💬

  Classification: The query is classified into one of four categories:

  Factual: Queries seeking verifiable information.

  Analytical: Queries that require in-depth analysis or explanation.

  Opinion: Queries looking for different perspectives or subjective viewpoints.

  Contextual: Queries specific to the user or certain contextual conditions.

  Adaptive Strategy Application: Based on classification, the query is restructured using the relevant strategy for better results.

  Response Generation**: The most relevant documents and context are used to generate a tailored response. 🎯

  Set Up Steps

  Estimated Time: ⏳ 10-15 minutes
  Prerequisites: You need an n8n account and a Qdrant vector store connection.
  Steps:

  Import the n8n workflow: Load the workflow into your n8n instance.

  Connect Google Gemini and Qdrant: Link these tools for query processing and data retrieval.

  Connect the Trigger Interface: Integrate with a chatbot or API to trigger the workflow.

  Customize: Adjust settings based on the query types you want to handle and the output format. 🔧

  For more detailed instructions, please check the sticky notes inside the workflow. 📌

nodes_used:
  ["@n8n/n8n-nodes-langchain.agent","@n8n/n8n-nodes-langchain.memoryBufferWindow","@n8n/n8n-nodes-langchain.vectorStoreQdrant","@n8n/n8n-nodes-langchain.embeddingsGoogleGemini","@n8n/n8n-nodes-langchain.lmChatGoogleGemini"]

workflow_json:
  {"id":"uZtDG9wLeCBZbaoK","meta":{"instanceId":"2848b874676d610ec8f8106a5acf41448278a62b14e4a776b42d6977aab508d7","templateId":"3459"},"name":"RAG 2.0 - Answer Architecture","tags":[],"nodes":[{"id":"856bd809-8f41-41af-8f72-a3828229c2a5","name":"Query Classification","type":"@n8n/n8n-nodes-langchain.agent","notes":"Classify a query into one of four categories: Factual, Analytical, Opinion, or Contextual.\n        \nReturns:\nstr: Query category","position":[420,340],"parameters":{"text":"=Classify this query: {{ $('Combined Fields').item.json.user_query }}","options":{"systemMessage":"You are an expert at classifying questions. \n\nClassify the given query into exactly one of these categories:\n- Factual: Queries seeking specific, verifiable information.\n- Analytical: Queries requiring comprehensive analysis or explanation.\n- Opinion: Queries about subjective matters or seeking diverse viewpoints.\n- Contextual: Queries that depend on user-specific context.\n\nReturn ONLY the category name, without any explanation or additional text."},"promptType":"define"},"typeVersion":1.8},{"id":"cc2106fc-f1a8-45ef-b37b-ab981ac13466","name":"Switch","type":"n8n-nodes-base.switch","position":[780,380],"parameters":{"rules":{"values":[{"outputKey":"Factual","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"87f3b50c-9f32-4260-ac76-19c05b28d0b4","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.output.trim() }}","rightValue":"Factual"}]},"renameOutput":true},{"outputKey":"Analytical","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"f8651b36-79fa-4be4-91fb-0e6d7deea18f","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.output.trim() }}","rightValue":"Analytical"}]},"renameOutput":true},{"outputKey":"Opinion","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"5dde06bc-5fe1-4dca-b6e2-6857c5e96d49","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.output.trim() }}","rightValue":"Opinion"}]},"renameOutput":true},{"outputKey":"Contextual","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"bf97926d-7a0b-4e2f-aac0-a820f73344d8","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.output.trim() }}","rightValue":"Contextual"}]},"renameOutput":true}]},"options":{"fallbackOutput":0}},"typeVersion":3.2},{"id":"63889cad-1283-4dbf-ba16-2b6cf575f24a","name":"Factual Strategy - Focus on Precision","type":"@n8n/n8n-nodes-langchain.agent","notes":"Retrieval strategy for factual queries focusing on precision.","position":[1180,-440],"parameters":{"text":"=Enhance this factual query: {{ $('Combined Fields').item.json.user_query }}","options":{"systemMessage":"=You are an expert at enhancing search queries.\n\nYour task is to reformulate the given factual query to make it more precise and specific for information retrieval. Focus on key entities and their relationships.\n\nProvide ONLY the enhanced query without any explanation."},"promptType":"define"},"typeVersion":1.7},{"id":"020d2201-9590-400d-b496-48c65801271c","name":"Analytical Strategy - Comprehensive Coverage","type":"@n8n/n8n-nodes-langchain.agent","notes":"Retrieval strategy for analytical queries focusing on comprehensive coverage.","position":[1180,140],"parameters":{"text":"=Generate sub-questions for this analytical query: {{ $('Combined Fields').item.json.user_query }}","options":{"systemMessage":"=You are an expert at breaking down complex questions.\n\nGenerate sub-questions that explore different aspects of the main analytical query.\nThese sub-questions should cover the breadth of the topic and help retrieve comprehensive information.\n\nReturn a list of exactly 3 sub-questions, one per line."},"promptType":"define"},"typeVersion":1.7},{"id":"c35d1b95-68c8-4237-932d-4744f620760d","name":"Opinion Strategy - Diverse Perspectives","type":"@n8n/n8n-nodes-langchain.agent","notes":"Retrieval strategy for opinion queries focusing on diverse perspectives.","position":[1220,700],"parameters":{"text":"=Identify different perspectives on: {{ $('Combined Fields').item.json.user_query }}","options":{"systemMessage":"=You are an expert at identifying different perspectives on a topic.\n\nFor the given query about opinions or viewpoints, identify different perspectives that people might have on this topic.\n\nReturn a list of exactly 3 different viewpoint angles, one per line."},"promptType":"define"},"typeVersion":1.7},{"id":"363a3fc3-112f-40df-891e-0a5aa3669245","name":"Contextual Strategy - User Context Integration","type":"@n8n/n8n-nodes-langchain.agent","notes":"Retrieval strategy for contextual queries integrating user context.","position":[1180,1320],"parameters":{"text":"=Infer the implied context in this query: {{ $('Combined Fields').item.json.user_query }}","options":{"systemMessage":"=You are an expert at understanding implied context in questions.\n\nFor the given query, infer what contextual information might be relevant or implied but not explicitly stated. Focus on what background would help answering this query.\n\nReturn a brief description of the implied context."},"promptType":"define"},"typeVersion":1.7},{"id":"45887701-5ea5-48b4-9b2b-40a80238ab0c","name":"Chat","type":"@n8n/n8n-nodes-langchain.chatTrigger","position":[0,640],"webhookId":"56f626b5-339e-48af-857f-1d4198fc8a4d","parameters":{"options":{}},"typeVersion":1.1},{"id":"7f7df364-4829-4e29-be3d-d13a63f65b8f","name":"Factual Prompt and Output","type":"n8n-nodes-base.set","position":[1640,-300],"parameters":{"options":{},"assignments":{"assignments":[{"id":"a4a28ac2-4a56-46f6-8b86-f5d1a34b2ced","name":"output","type":"string","value":"={{ $json.output }}"},{"id":"7aa6ce13-afbf-4871-b81c-6e9c722a53dc","name":"prompt","type":"string","value":"You are a helpful assistant providing factual information. Answer the question based on the provided context. Focus on accuracy and precision. If the context doesn't contain the information needed, acknowledge the limitations."}]}},"typeVersion":3.4},{"id":"590d8667-69eb-4db2-b5be-714c602b319a","name":"Contextual Prompt and Output","type":"n8n-nodes-base.set","position":[1640,1400],"parameters":{"options":{},"assignments":{"assignments":[{"id":"a4a28ac2-4a56-46f6-8b86-f5d1a34b2ced","name":"output","type":"string","value":"={{ $json.output }}"},{"id":"7aa6ce13-afbf-4871-b81c-6e9c722a53dc","name":"prompt","type":"string","value":"You are a helpful assistant providing contextually relevant information. Answer the question considering both the query and its context. Make connections between the query context and the information in the provided documents. If the context doesn't fully address the specific situation, acknowledge the limitations."}]}},"typeVersion":3.4},{"id":"fa3228ee-62d8-4c02-9dca-8a1ebc6afc74","name":"Opinion Prompt and Output","type":"n8n-nodes-base.set","position":[1620,820],"parameters":{"options":{},"assignments":{"assignments":[{"id":"a4a28ac2-4a56-46f6-8b86-f5d1a34b2ced","name":"output","type":"string","value":"={{ $json.output }}"},{"id":"7aa6ce13-afbf-4871-b81c-6e9c722a53dc","name":"prompt","type":"string","value":"You are a helpful assistant discussing topics with multiple viewpoints. Based on the provided context, present different perspectives on the topic. Ensure fair representation of diverse opinions without showing bias. Acknowledge where the context presents limited viewpoints."}]}},"typeVersion":3.4},{"id":"c769a76a-fb26-46a1-a00d-825b689d5f7a","name":"Analytical Prompt and Output","type":"n8n-nodes-base.set","position":[1620,220],"parameters":{"options":{},"assignments":{"assignments":[{"id":"a4a28ac2-4a56-46f6-8b86-f5d1a34b2ced","name":"output","type":"string","value":"={{ $json.output }}"},{"id":"7aa6ce13-afbf-4871-b81c-6e9c722a53dc","name":"prompt","type":"string","value":"You are a helpful assistant providing analytical insights. Based on the provided context, offer a comprehensive analysis of the topic. Cover different aspects and perspectives in your explanation. If the context has gaps, acknowledge them while providing the best analysis possible."}]}},"typeVersion":3.4},{"id":"fcd29f6b-17e8-442c-93f9-b93fbad7cd10","name":"Gemini Classification","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[580,600],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash-lite"},"credentials":{"googlePalmApi":{"id":"vGGCUG66DLA8zNyX","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"c0828ee3-f184-41f5-9a25-0f1059b03711","name":"Gemini Factual","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[1240,-240],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"vGGCUG66DLA8zNyX","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"98f9981d-ea8e-45cb-b91d-3c8d1fe33e25","name":"Gemini Analytical","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[1240,340],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"vGGCUG66DLA8zNyX","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"c85f270d-3224-4e60-9acf-91f173dfe377","name":"Chat Buffer Memory Analytical","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[1400,340],"parameters":{"sessionKey":"={{ $('Combined Fields').item.json.chat_memory_key }}","sessionIdType":"customKey","contextWindowLength":10},"typeVersion":1.3},{"id":"c39ba907-7388-4152-965a-e28e626bc9b2","name":"Chat Buffer Memory Factual","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[1400,-240],"parameters":{"sessionKey":"={{ $('Combined Fields').item.json.chat_memory_key }}","sessionIdType":"customKey","contextWindowLength":10},"typeVersion":1.3},{"id":"52dcd9f0-e6b3-4d33-bc6f-621ef880178e","name":"Gemini Opinion","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[1280,900],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"vGGCUG66DLA8zNyX","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"147a709a-4b46-4835-82cf-7d6b633acd4c","name":"Chat Buffer Memory Opinion","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[1440,900],"parameters":{"sessionKey":"={{ $('Combined Fields').item.json.chat_memory_key }}","sessionIdType":"customKey","contextWindowLength":10},"typeVersion":1.3},{"id":"3cb6bf32-5937-49b9-acf7-d7d01dc2ddd1","name":"Gemini Contextual","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[1240,1500],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"vGGCUG66DLA8zNyX","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"5916c4f1-4369-4d66-8553-2fff006b7e69","name":"Chat Buffer Memory Contextual","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[1420,1500],"parameters":{"sessionKey":"={{ $('Combined Fields').item.json.chat_memory_key }}","sessionIdType":"customKey","contextWindowLength":10},"typeVersion":1.3},{"id":"d33377c2-6b98-4e4d-968f-f3085354ae50","name":"Embeddings","type":"@n8n/n8n-nodes-langchain.embeddingsGoogleGemini","notes":"{ $node[\"Embeddings\"].json.response }}","position":[2400,600],"parameters":{"modelName":"models/text-embedding-004"},"credentials":{"googlePalmApi":{"id":"vGGCUG66DLA8zNyX","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"32d9a0c0-0889-4cb2-a088-8ee9cfecacd3","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[1100,-600],"parameters":{"color":7,"width":700,"height":520,"content":"## Factual Strategy\n**Retrieve precise facts and figures.**\n## Olgusal Strateji\n**Kesin gerçeklere ve rakamlara ulaşın.**"},"typeVersion":1},{"id":"064a4729-717c-40c8-824a-508406610a13","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[1100,-40],"parameters":{"color":7,"width":700,"height":520,"content":"## Analytical Strategy\n**Provide comprehensive coverage of a topics and exploring different aspects.**\n## Analitik Strateji\n**Bir konunun kapsamlı bir şekilde ele alınmasını ve farklı yönlerinin keşfedilmesini sağlar.**"},"typeVersion":1},{"id":"9fd52a28-44bc-4dfd-bdb7-90987cc2f4fb","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[1100,520],"parameters":{"color":7,"width":700,"height":520,"content":"## Opinion Strategy\n**Gather diverse viewpoints on a subjective issue.**\n## Görüş Stratejisi\n**Öznel bir konuda farklı bakış açıları toplayın.**"},"typeVersion":1},{"id":"3797b21f-cc2a-4210-aa63-6d181d413c5e","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[1100,1100],"parameters":{"color":7,"width":700,"height":540,"content":"## Contextual Strategy\n**Incorporate user-specific context to fine-tune the retrieval.**\n## Bağlamsal Strateji\n**Getirmeye ince ayar yapmak için kullanıcıya özgü bağlamı dahil edin.**"},"typeVersion":1},{"id":"16fa1531-9fb9-4b12-961c-be12e20b2134","name":"Concatenate Context","type":"n8n-nodes-base.summarize","position":[2900,380],"parameters":{"options":{},"fieldsToSummarize":{"values":[{"field":"document.pageContent","separateBy":"other","aggregation":"concatenate","customSeparator":"={{ \"\\n\\n---\\n\\n\" }}"}]}},"typeVersion":1.1},{"id":"4d6147d1-7a3d-42ab-b23f-cdafe8ea30b0","name":"Retrieve Documents from Vector Store","type":"@n8n/n8n-nodes-langchain.vectorStoreQdrant","position":[2140,380],"parameters":{"mode":"load","topK":10,"prompt":"=Prompt\n{{ $json.prompt }}\n\nUser query: \n{{ $json.output }}","options":{},"qdrantCollection":{"__rl":true,"mode":"id","value":"=vector_store_id"}},"credentials":{"qdrantApi":{"id":"ivp7KsCQyRCs5owS","name":"QdrantApi account"}},"executeOnce":false,"notesInFlow":false,"retryOnFail":false,"typeVersion":1.1,"alwaysOutputData":false},{"id":"7e68f9cb-0a0d-4215-8083-3b9ef92cd237","name":"Set Prompt and Output","type":"n8n-nodes-base.set","position":[1900,460],"parameters":{"options":{},"assignments":{"assignments":[{"id":"1d782243-0571-4845-b8fe-4c6c4b55379e","name":"output","type":"string","value":"={{ $json.output }}"},{"id":"547091fb-367c-44d4-ac39-24d073da70e0","name":"prompt","type":"string","value":"={{ $json.prompt }}"}]}},"typeVersion":3.4},{"id":"0c623ca1-da85-48a3-9d8b-90d97283a015","name":"Gemini Answer","type":"@n8n/n8n-nodes-langchain.lmChatGoogleGemini","position":[3340,620],"parameters":{"options":{},"modelName":"models/gemini-2.0-flash"},"credentials":{"googlePalmApi":{"id":"vGGCUG66DLA8zNyX","name":"Google Gemini(PaLM) Api account"}},"typeVersion":1},{"id":"fab91e48-1c62-46a8-b9fc-39704f225274","name":"Answer","type":"@n8n/n8n-nodes-langchain.agent","position":[3120,380],"parameters":{"text":"=User query: {{ $('Combined Fields').item.json.user_query }}","options":{"systemMessage":"={{ $('Set Prompt and Output').item.json.prompt }}\n\nUse the following context (delimited by <ctx></ctx>) and the chat history to answer the user query.\n<ctx>\n{{ $json.concatenated_document_pageContent }}\n</ctx>"},"promptType":"define"},"typeVersion":1.8},{"id":"d69f8d62-3064-40a8-b490-22772fbc38cd","name":"Chat Buffer Memory","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[3500,620],"parameters":{"sessionKey":"={{ $('Combined Fields').item.json.chat_memory_key }}","sessionIdType":"customKey","contextWindowLength":10},"typeVersion":1.3},{"id":"a399f8e6-fafd-4f73-a2de-894f1e3c4bec","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[1860,160],"parameters":{"color":7,"width":820,"height":580,"content":"## Perform adaptive retrieval\n**Find document considering both query and context.**\n## Uyarlanabilir RAG gerçekleştirin\n**Hem sorguyu hem de bağlamı dikkate alarak belge bulun.**"},"typeVersion":1},{"id":"7f10fe70-1af8-47ad-a9b5-2850412c43f8","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[2760,160],"parameters":{"color":7,"width":1060,"height":580,"content":"## Reply to the user integrating retrieval context\n## Kullanıcıya RAG bağlamını entegre ederek yanıt verin"},"typeVersion":1},{"id":"5cd0dd02-65f4-4351-aeae-c70ecf5f1d66","name":"Respond to Webhook","type":"n8n-nodes-base.respondToWebhook","position":[3540,400],"parameters":{"options":{}},"typeVersion":1.1},{"id":"4c56ef8f-8fce-4525-bb87-15df37e91cc4","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[320,160],"parameters":{"color":7,"width":700,"height":580,"content":"## User query classification\n**Classify the query into one of four categories: Factual, Analytical, Opinion, or Contextual.**\n## Kullanıcı sorgu sınıflandırması\n**Sorguyu dört kategoriden birine sınıflandırın: Olgusal, Analitik, Görüş veya Bağlamsal.**\n"},"typeVersion":1},{"id":"3ef73405-89de-4bed-9673-90e2c1f2e74b","name":"When Executed by Another Workflow","type":"n8n-nodes-base.executeWorkflowTrigger","position":[0,340],"parameters":{"workflowInputs":{"values":[{"name":"user_query"},{"name":"chat_memory_key"},{"name":"vector_store_id"}]}},"typeVersion":1.1},{"id":"0785714f-c45c-4eda-9937-c97e44c9a449","name":"Combined Fields","type":"n8n-nodes-base.set","position":[140,480],"parameters":{"options":{},"assignments":{"assignments":[{"id":"90ab73a2-fe01-451a-b9df-bffe950b1599","name":"user_query","type":"string","value":"={{ $json.user_query || $json.chatInput }}"},{"id":"36686ff5-09fc-40a4-8335-a5dd1576e941","name":"chat_memory_key","type":"string","value":"={{ $json.chat_memory_key || $('Chat').item.json.sessionId }}"},{"id":"4230c8f3-644c-4985-b710-a4099ccee77c","name":"vector_store_id","type":"string","value":"={{ $json.vector_store_id || \"<ID HERE>\" }}"}]}},"typeVersion":3.4},{"id":"57a93b72-4233-4ba2-b8c7-99d88f0ed572","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[-1420,-560],"parameters":{"color":3,"width":1280,"height":1680,"content":"# Uyarlanabilir RAG İş Akışı\n\nBu n8n iş akışı, Uyarlanabilir Geri Getirme Destekli Üretim (Adaptive RAG) yaklaşımının bir versiyonunu uygular. Kullanıcı sorgularını sınıflandırır ve sorgu türüne (Olgusal, Analitik, Görüş veya Bağlamsal) göre farklı geri getirme ve üretim stratejileri uygulayarak bir Qdrant vektör deposunda saklanan bilgi tabanından daha alakalı ve özel yanıtlar sunar.\n\n## Nasıl Çalışır?\n\n### Giriş Tetikleyicisi\n\n- İş akışı, yerleşik Sohbet arayüzü aracılığıyla veya başka bir n8n iş akışı tarafından tetiklenebilir.\n- Girdiler beklenir: `user_query` (kullanıcı sorgusu), `chat_memory_key` (konuşma geçmişi için) ve `vector_store_id` (Qdrant koleksiyonunu belirten).\n- Bir `Set` düğümü (`Combined Fields` - Birleştirilmiş Alanlar) bu girdileri standartlaştırır.\n\n### Sorgu Sınıflandırması\n\n- Bir Google Gemini ajanı (`Query Classification` - Sorgu Sınıflandırması) `user_query`'yi analiz eder.\n- Sorguyu dört kategoriden birine sınıflandırır:\n  - **Olgusal:** Belirli, doğrulanabilir bilgi arayan.\n  - **Analitik:** Kapsamlı analiz veya açıklama gerektiren.\n  - **Görüş:** Öznel konular hakkında soru soran veya farklı bakış açıları arayan.\n  - **Bağlamsal:** Kullanıcıya özel veya örtük bağlama bağlı olan.\n\n### Uyarlanabilir Strateji Yönlendirmesi\n\n- Bir `Switch` düğümü (Yönlendirme Düğümü), iş akışını bir önceki adımdaki sınıflandırma sonucuna göre yönlendirir.\n\n### Strateji Uygulaması (Sorgu Uyarlaması)\n\n- Yönlendirmeye bağlı olarak, belirli bir Google Gemini ajanı sorguyu veya yaklaşımı uyarlar:\n  - **Olgusal Strateji:** Anahtar varlıklara odaklanarak daha iyi kesinlik için sorguyu yeniden yazar (`Factual Strategy - Focus on Precision` - Olgusal Strateji - Kesinliğe Odaklanma).\n  - **Analitik Strateji:** Kapsamlı bir şekilde ele alınmasını sağlamak için ana sorguyu birden fazla alt soruya böler (`Analytical Strategy - Comprehensive Coverage` - Analitik Strateji - Kapsamlı Ele Alma).\n  - **Görüş Stratejisi:** Sorguyla ilgili farklı potansiyel bakış açılarını veya yaklaşımları tanımlar (`Opinion Strategy - Diverse Perspectives` - Görüş Stratejisi - Farklı Bakış Açıları).\n  - **Bağlamsal Strateji:** Sorguyu etkili bir şekilde yanıtlamak için gereken örtük bağlamı çıkarır (`Contextual Strategy - User Context Integration` - Bağlamsal Strateji - Kullanıcı Bağlamı Entegrasyonu).\n- Her strateji yolu, uyarlama adımı için kendi sohbet belleği tamponunu kullanır.\n\n### Geri Getirme İstemcisi ve Çıktı Kurulumu\n\n- *Orijinal* sorgu sınıflandırmasına dayanarak, bir `Set` düğümü (`Factual/Analytical/Opinion/Contextual Prompt and Output` - Olgusal/Analitik/Görüş/Bağlamsal İstemci ve Çıktı, `Set Prompt and Output` - İstemci ve Çıktı Ayarla düğümüne bağlantılar aracılığıyla birleştirilir) şunları hazırlar:\n  - Strateji adımından gelen çıktı (örneğin, yeniden yazılmış sorgu, alt sorular, bakış açıları).\n  - Son yanıt üretim ajanı için özel olarak hazırlanmış bir sistem istemcisi; sorgu türüne göre nasıl davranacağını belirtir (örneğin, Olgusal için kesinliğe odaklan, Görüş için farklı görüşler sun).\n\n### Belge Geri Getirme (RAG)\n\n- `Retrieve Documents from Vector Store` (Vektör Deposundan Belgeleri Geri Getir) düğümü, belirtilen Qdrant koleksiyonunda (`vector_store_id`) arama yapmak için strateji adımından gelen uyarlanmış sorguyu/çıktıyı kullanır.\n- Google Gemini gömülerini (vektörlerini) kullanarak en alakalı belge parçalarını geri getirir.\n\n### Bağlam Hazırlığı\n\n- Geri getirilen belge parçalarından elde edilen içerik, son yanıt üretimi için tek bir bağlam bloğu oluşturmak üzere birleştirilir (`Concatenate Context` - Bağlamı Birleştir).\n\n### Yanıt Üretimi\n\n- Son `Answer` (Yanıt) ajanı (Google Gemini tarafından desteklenir) yanıtı üretir.\n- Şunları kullanır:\n  - 5. adımda ayarlanan özel sistem istemcisi.\n  - Geri getirilen belgelerden birleştirilmiş bağlam (7. adım).\n  - Orijinal `user_query`.\n  - Paylaşılan sohbet geçmişi (`Chat Buffer Memory` - Sohbet Belleği Tamponu, `chat_memory_key` kullanılarak).\n\n### Yanıt\n\n- Üretilen yanıt, `Respond to Webhook` (Webhook'a Yanıt Ver) düğümü aracılığıyla kullanıcıya geri gönderilir.\n"},"typeVersion":1},{"id":"bec8070f-2ce9-4930-b71e-685a2b21d3f2","name":"Sticky Note8","type":"n8n-nodes-base.stickyNote","position":[-40,-20],"parameters":{"color":7,"width":320,"height":820,"content":"## ⚠️  Using in Chat mode\n\nUpdate the `vector_store_id` variable to the corresponding Qdrant ID needed to perform the documents retrieval.\n\n## ⚠️ Sohbet modunda kullanım sağlayın\n\nvector_store_id` değişkenini belge alımını gerçekleştirmek için gereken ilgili Qdrant ID'sine güncelleyin."},"typeVersion":1},{"id":"dc002d7a-df79-4d61-880a-db32917d9814","name":"Sticky Note9","type":"n8n-nodes-base.stickyNote","position":[1220,580],"parameters":{},"typeVersion":1}],"active":true,"pinData":{},"settings":{},"versionId":"fbee3fa8-a249-4841-b786-817f0992ae6b","connections":{"Chat":{"main":[[{"node":"Combined Fields","type":"main","index":0}]]},"Answer":{"main":[[{"node":"Respond to Webhook","type":"main","index":0}]]},"Switch":{"main":[[{"node":"Factual Strategy - Focus on Precision","type":"main","index":0}],[{"node":"Analytical Strategy - Comprehensive Coverage","type":"main","index":0}],[{"node":"Opinion Strategy - Diverse Perspectives","type":"main","index":0}],[{"node":"Contextual Strategy - User Context Integration","type":"main","index":0}]]},"Embeddings":{"ai_embedding":[[{"node":"Retrieve Documents from Vector Store","type":"ai_embedding","index":0}]]},"Gemini Answer":{"ai_languageModel":[[{"node":"Answer","type":"ai_languageModel","index":0}]]},"Gemini Factual":{"ai_languageModel":[[{"node":"Factual Strategy - Focus on Precision","type":"ai_languageModel","index":0}]]},"Gemini Opinion":{"ai_languageModel":[[{"node":"Opinion Strategy - Diverse Perspectives","type":"ai_languageModel","index":0}]]},"Combined Fields":{"main":[[{"node":"Query Classification","type":"main","index":0}]]},"Gemini Analytical":{"ai_languageModel":[[{"node":"Analytical Strategy - Comprehensive Coverage","type":"ai_languageModel","index":0}]]},"Gemini Contextual":{"ai_languageModel":[[{"node":"Contextual Strategy - User Context Integration","type":"ai_languageModel","index":0}]]},"Chat Buffer Memory":{"ai_memory":[[{"node":"Answer","type":"ai_memory","index":0}]]},"Concatenate Context":{"main":[[{"node":"Answer","type":"main","index":0}]]},"Query Classification":{"main":[[{"node":"Switch","type":"main","index":0}]]},"Gemini Classification":{"ai_languageModel":[[{"node":"Query Classification","type":"ai_languageModel","index":0}]]},"Set Prompt and Output":{"main":[[{"node":"Retrieve Documents from Vector Store","type":"main","index":0}]]},"Factual Prompt and Output":{"main":[[{"node":"Set Prompt and Output","type":"main","index":0}]]},"Opinion Prompt and Output":{"main":[[{"node":"Set Prompt and Output","type":"main","index":0}]]},"Chat Buffer Memory Factual":{"ai_memory":[[{"node":"Factual Strategy - Focus on Precision","type":"ai_memory","index":0}]]},"Chat Buffer Memory Opinion":{"ai_memory":[[{"node":"Opinion Strategy - Diverse Perspectives","type":"ai_memory","index":0}]]},"Analytical Prompt and Output":{"main":[[{"node":"Set Prompt and Output","type":"main","index":0}]]},"Contextual Prompt and Output":{"main":[[{"node":"Set Prompt and Output","type":"main","index":0}]]},"Chat Buffer Memory Analytical":{"ai_memory":[[{"node":"Analytical Strategy - Comprehensive Coverage","type":"ai_memory","index":0}]]},"Chat Buffer Memory Contextual":{"ai_memory":[[{"node":"Contextual Strategy - User Context Integration","type":"ai_memory","index":0}]]},"When Executed by Another Workflow":{"main":[[{"node":"Combined Fields","type":"main","index":0}]]},"Retrieve Documents from Vector Store":{"main":[[{"node":"Concatenate Context","type":"main","index":0}]]},"Factual Strategy - Focus on Precision":{"main":[[{"node":"Factual Prompt and Output","type":"main","index":0}]]},"Opinion Strategy - Diverse Perspectives":{"main":[[{"node":"Opinion Prompt and Output","type":"main","index":0}]]},"Analytical Strategy - Comprehensive Coverage":{"main":[[{"node":"Analytical Prompt and Output","type":"main","index":0}]]},"Contextual Strategy - User Context Integration":{"main":[[{"node":"Contextual Prompt and Output","type":"main","index":0}]]}}}


name: Generate Images and Convert to Video Using Flux, Kraken & Runway
author_name: Joseph
author_username: mjomba
nodes_used: ["n8n-nodes-base.httpRequest"]
categories: []
created_at: 2025-05-14T19:48:15.928Z
updated_at: 2025-05-14T19:48:15.928Z
url: https://n8n.io/workflows/4056
scraped_at: 2025-06-19 22:49:51
description:
  (Image Generation → Hosting → Video Generation)

  This workflow is designed for creators, automation enthusiasts, and indie hackers who want to generate image-based videos automatically using AI tools — at a low cost.

  ⚙️ Workflow Overview

  This automation performs the following steps:

  Trigger (Schedule or manual)
  Generate an image using Flux (choose between two APIs)
  Upload the image to Kraken.io to get a public URL
  Send the image to Runway ML (choose between two APIs) to generate a video
  Receive the video as a URL — ready for posting, download, or further automation

  🛠️ Step-by-Step Setup

  🖼️ Flux (Image Generation)

  You can use either of the following providers:

  Option 1: Flux by BlackForest Labs (Direct API)

  🔑 Get your API key here: https://docs.bfl.ml/

  Paste your API key in the HTTP Request node named Flux (Blackforest)
  You can customize prompts or styles inside the JSON body

  Option 2: Flux via RapidAPI

  🔑 Subscribe and get your key here:
  https://rapidapi.com/poorav925/api/ai-text-to-image-generator-flux-free-api/playground/apiendpoint\_e38039ee-1912-4ef9-b4d4-270d72fca851

  Enter your RapidAPI key in the X-RapidAPI-Key header
  Optional: tweak prompts, style, or resolution inside the JSON body

  🐙 Kraken.io (Hosting the Image Publicly)

  Runway ML requires the image to be publicly accessible. We use Kraken.io to host the generated image and return a public URL.

  🔑 Get your API credentials: https://kraken.io/account/api-credentials

  Setup:

  Copy your API Key and API Secret
  Open the Kraken Upload node in n8n
  Replace placeholders with your credentials
  The node uploads your image and gives back a public image URL for Runway to use

  🎬 RunwayML (Video Generation)

  You also have two options here:

  Option 1: Runway Official API

  🔑 Get your credentials at: https://dev.runwayml.com/

  Use the public image URL from Kraken in the JSON body
  Paste your Bearer token in the Authorization header
  Customize other settings like video length, style, FPS, etc.

  Option 2: Runway via RapidAPI

  🔑 Subscribe and get your key here:
  https://rapidapi.com/fortunehoppers/api/runwayml/playground/apiendpoint\_93c8554d-8097-40cd-8252-3d4dec9c0e68

  Paste your RapidAPI key in the request header
  Customize prompt and generation options in the body
  Use the Kraken-generated image URL as the input source

  📤 What to Do with the Video

  Once the video is generated, you’ll get a direct video URL. You can:

  Save it to Google Sheets or Notion
  Send it via email
  Trigger a YouTube upload automation
  Or download manually for editing and reposting

  💡 Optional Tips & Notes

  You can schedule this workflow to generate AI videos daily or weekly
  Combine it with a Google Sheet of prompts for bulk automation
  Try using a consistent visual style or theme for better branding
  This workflow is lightweight and affordable — perfect for indie projects or experimental content generation
  Great for shorts, quote visuals, music loops, AI art promos, etc.

  🔗 Resources

  Flux (Blackforest) Docs
  Flux on RapidAPI
  RunwayML Official Docs
  Runway on RapidAPI
  Kraken.io API Dashboard

  🙋 Need Help?

  Feel free to reach out:

  🐦 Twitter: @juppfy
  📧 Email: joseph@uppfy.com

  If you’d like to hire me for custom n8n workflows or product automations, don’t hesitate to get in touch.

workflow_json:
  {"id":"Glb8ROS3mY24Bf3t","meta":{"instanceId":"b3c467df4053d13fe31cc98f3c66fa1d16300ba750506bfd019a0913cec71ea3"},"name":"generate Image and convert to video","tags":[],"nodes":[{"id":"ab2da12f-7300-4262-ad91-3e2a258c326b","name":"Wait","type":"n8n-nodes-base.wait","position":[-380,280],"webhookId":"c97f2119-0ee3-495f-9b58-dd6ee2cd1a2d","parameters":{"amount":15},"typeVersion":1.1},{"id":"b7765150-a147-4ee8-adee-b3aeba2f13ed","name":"get_image_url","type":"n8n-nodes-base.httpRequest","position":[-760,520],"parameters":{"url":"=https://api.us1.bfl.ai/v1/get_result?id={{ $('generate image (flux)').item.json.id }}","options":{},"sendHeaders":true,"headerParameters":{"parameters":[{"name":"x-key","value":"\"your-key\""}]}},"typeVersion":4.2},{"id":"55428fc5-0b6f-4ea2-9281-9a77af413a5c","name":"get_image","type":"n8n-nodes-base.httpRequest","position":[-560,520],"parameters":{"url":"={{ $json.result.sample }}","options":{"response":{"response":{"fullResponse":true,"responseFormat":"file"}}},"sendHeaders":true,"headerParameters":{"parameters":[{"name":"auth","value":"\"your-api-key\""}]}},"typeVersion":4.2},{"id":"a95d01cd-aae3-4634-83fb-ff2652eb6ca7","name":"upload to kraken","type":"n8n-nodes-base.httpRequest","position":[-380,520],"parameters":{"url":"https://api.kraken.io/v1/upload","method":"POST","options":{"redirect":{"redirect":{}}},"sendBody":true,"contentType":"multipart-form-data","bodyParameters":{"parameters":[{"name":"data","value":"{\"auth\":{\"api_key\": \"your_api_key\", \"api_secret\": \"your_api_secret\"}, \"wait\":true}"},{"name":"upload","parameterType":"formBinaryData","inputDataFieldName":"data"}]}},"typeVersion":4.2},{"id":"779f794a-656a-4f3e-8cbe-b0f418c2c05f","name":"When clicking ‘Test workflow’","type":"n8n-nodes-base.manualTrigger","position":[-760,280],"parameters":{},"typeVersion":1},{"id":"c4c0c0e8-a830-4905-9983-86002785b9b1","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-860,200],"parameters":{"color":5,"width":740,"height":520,"content":"## Generate Image: Using Flux (Blackforest labs Option)"},"typeVersion":1},{"id":"16d9dc4b-a29f-482a-8d4a-cdec3a9771f7","name":"Get Image3","type":"n8n-nodes-base.httpRequest","position":[500,280],"parameters":{"url":"={{ $json.final_result[0].origin }}","options":{},"sendHeaders":true,"headerParameters":{"parameters":[{"name":"x-rapidapi-key","value":"\"your-rapid-api-key\""}]}},"typeVersion":4.2},{"id":"6949ea7b-f242-49c6-9857-68baa196c31a","name":"upload to kraken1","type":"n8n-nodes-base.httpRequest","position":[680,280],"parameters":{"url":"https://api.kraken.io/v1/upload","method":"POST","options":{"redirect":{"redirect":{}}},"sendBody":true,"contentType":"multipart-form-data","bodyParameters":{"parameters":[{"name":"data","value":"{\"auth\":{\"api_key\": \"your_api_key\", \"api_secret\": \"your_api_secret\"}, \"wait\":true}"},{"name":"upload","parameterType":"formBinaryData","inputDataFieldName":"data"}]}},"typeVersion":4.2},{"id":"ee9492ec-0c71-4961-88c1-18e365a7dc54","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[200,200],"parameters":{"color":6,"width":740,"height":260,"content":"## Flux (Rapid API Endpoint)"},"typeVersion":1},{"id":"f317d698-6218-4507-b864-7e42f3bbec40","name":"Get Video Generation Status1","type":"n8n-nodes-base.httpRequest","position":[680,600],"parameters":{"url":"https://runwayml.p.rapidapi.com/status","options":{},"sendQuery":true,"sendHeaders":true,"queryParameters":{"parameters":[{"name":"uuid","value":"={{ $json.uuid }}"}]},"headerParameters":{"parameters":[{"name":"x-rapidapi-host","value":"runwayml.p.rapidapi.com"},{"name":"x-rapidapi-key","value":"\"your-rapid-api-key\""}]}},"typeVersion":4.2},{"id":"520eb9eb-4207-4c3e-b741-8e1176904e33","name":"Confirm Generation Status","type":"n8n-nodes-base.switch","position":[500,760],"parameters":{"rules":{"values":[{"outputKey":"completed","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"86af9233-1825-4ce0-a39f-4665a244b0a5","operator":{"type":"string","operation":"contains"},"leftValue":"={{ $json.status }}","rightValue":"success"}]},"renameOutput":true},{"outputKey":"pending","conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"3f431dfc-ce04-40f0-83b8-93e7df665340","operator":{"type":"string","operation":"notContains"},"leftValue":"={{ $json.status }}","rightValue":"success"}]},"renameOutput":true}]},"options":{}},"typeVersion":3.2},{"id":"809bacea-b6ec-4b5d-876e-34591ed0138a","name":"1 minute3","type":"n8n-nodes-base.wait","position":[500,600],"webhookId":"912371bb-33b4-4879-81b2-8674cd25be9c","parameters":{"unit":"minutes","amount":1},"typeVersion":1.1},{"id":"40497b66-2d13-439e-a7c5-a7fcd52f1e3b","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[200,500],"parameters":{"color":6,"width":740,"height":520,"content":"## Image to Video: Using Runway (Rapid API)"},"typeVersion":1},{"id":"d9e6ab4c-2ba9-4e83-9564-d5389ed5850f","name":"1 minute2","type":"n8n-nodes-base.wait","position":[-560,800],"webhookId":"51231920-f912-4593-af70-52c5f2fa2e14","parameters":{"unit":"minutes","amount":1},"typeVersion":1.1},{"id":"259f3a3d-adba-4320-82c6-8b16941ef71d","name":"Sticky Note10","type":"n8n-nodes-base.stickyNote","position":[-860,740],"parameters":{"color":5,"width":740,"height":280,"content":"## Image to Video: Using Runway (official api)"},"typeVersion":1},{"id":"449f8334-99e8-4f95-8d61-ff844e600d28","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[140,140],"parameters":{"color":3,"width":860,"height":940,"content":"## Using Rapid API Endpoints"},"typeVersion":1},{"id":"7063bd58-019f-46c4-a863-0057ba139a6f","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[-920,140],"parameters":{"color":4,"width":860,"height":940,"content":"## Using official APIs"},"typeVersion":1},{"id":"fed6f706-cfa2-4f8e-bace-d6376394ffaf","name":"Download Video","type":"n8n-nodes-base.httpRequest","onError":"continueErrorOutput","position":[-380,800],"parameters":{"url":"=https://api.dev.runwayml.com/v1/tasks/{{ $json.id }}","options":{},"sendHeaders":true,"headerParameters":{"parameters":[{"name":"X-Runway-Version","value":"2024-11-06"},{"name":"Authorization","value":"\"your-bearer-key\""}]}},"typeVersion":4.2},{"id":"69d02b6f-0ada-4997-8b74-e79cc16d35ad","name":"generate image (flux)","type":"n8n-nodes-base.httpRequest","position":[-560,280],"parameters":{"url":"https://api.us1.bfl.ai/v1/flux-pro-1.1","method":"POST","options":{},"jsonBody":"={\n  \"prompt\" : \"your_text_to_image_prompt\",\n  \"width\": 768,\n  \"height\": 1024,\n  \"prompt_upsampling\": false,\n  \"seed\": 42,\n  \"safety_tolerance\": 2,\n  \"output_format\": \"jpeg\"\n}","sendBody":true,"sendHeaders":true,"specifyBody":"json","headerParameters":{"parameters":[{"name":"x-key","value":"\"your-key\""}]}},"typeVersion":4.2},{"id":"6dc28e39-fbc1-46c6-a344-c1c4af8b8f96","name":"generate image (flux-rapid-api)","type":"n8n-nodes-base.httpRequest","position":[300,280],"parameters":{"url":"https://ai-text-to-image-generator-flux-free-api.p.rapidapi.com/aaaaaaaaaaaaaaaaaiimagegenerator/quick.php","method":"POST","options":{},"sendBody":true,"sendHeaders":true,"bodyParameters":{"parameters":[{"name":"prompt","value":"=\"your_text_to_image_prompt\""},{"name":"style_id","value":"1"},{"name":"size","value":"1-1"}]},"headerParameters":{"parameters":[{"name":"x-rapidapi-host","value":"ai-text-to-image-generator-flux-free-api.p.rapidapi.com"},{"name":"x-rapidapi-key","value":"\"your-rapid-api-key\""}]}},"typeVersion":4.2},{"id":"b1c4710e-d99a-42bc-8de2-477b2fca84da","name":"image to video (runway-rapid-api)","type":"n8n-nodes-base.httpRequest","position":[300,600],"parameters":{"url":"https://runwayml.p.rapidapi.com/generate/imageDescription","method":"POST","options":{},"sendBody":true,"sendHeaders":true,"bodyParameters":{"parameters":[{"name":"text_prompt","value":"=\"your_image_to_video_prompt\""},{"name":"img_prompt","value":"={{ $json.kraked_url }}"},{"name":"model","value":"gen3"},{"name":"image_as_end_frame","value":"false"},{"name":"flip","value":"true"},{"name":"motion","value":"5"},{"name":"seed","value":"0"},{"name":"time","value":"10"}]},"headerParameters":{"parameters":[{"name":"x-rapidapi-host","value":"runwayml.p.rapidapi.com"},{"name":"x-rapidapi-key","value":"\"your-rapid-api-key\""}]}},"typeVersion":4.2},{"id":"82ed20f3-15ba-4369-80c0-1b5913ddccfa","name":"image to video (runway)","type":"n8n-nodes-base.httpRequest","position":[-760,800],"parameters":{"url":"https://api.dev.runwayml.com/v1/image_to_video","method":"POST","options":{},"sendBody":true,"sendHeaders":true,"bodyParameters":{"parameters":[{"name":"promptImage","value":"={{ $json.kraked_url }}"},{"name":"model","value":"gen3a_turbo"},{"name":"ratio","value":"768:1280"},{"name":"duration","value":"10"},{"name":"promptText","value":"=\"your_image_to_video_prompt\""}]},"headerParameters":{"parameters":[{"name":"X-Runway-Version","value":"2024-11-06"},{"name":"Authorization","value":"\"Your-bearer-key\""}]}},"typeVersion":4.2}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"716e405d-b8bc-4c61-a23c-427bedf7ea7f","connections":{"Wait":{"main":[[{"node":"get_image_url","type":"main","index":0}]]},"1 minute2":{"main":[[{"node":"Download Video","type":"main","index":0}]]},"1 minute3":{"main":[[{"node":"Get Video Generation Status1","type":"main","index":0}]]},"get_image":{"main":[[{"node":"upload to kraken","type":"main","index":0}]]},"Get Image3":{"main":[[{"node":"upload to kraken1","type":"main","index":0}]]},"get_image_url":{"main":[[{"node":"get_image","type":"main","index":0}]]},"Download Video":{"main":[[],[{"node":"1 minute2","type":"main","index":0}]]},"upload to kraken":{"main":[[{"node":"image to video (runway)","type":"main","index":0}]]},"upload to kraken1":{"main":[[{"node":"image to video (runway-rapid-api)","type":"main","index":0}]]},"generate image (flux)":{"main":[[{"node":"Wait","type":"main","index":0}]]},"image to video (runway)":{"main":[[{"node":"1 minute2","type":"main","index":0}]]},"Confirm Generation Status":{"main":[[],[{"node":"1 minute3","type":"main","index":0}]]},"Get Video Generation Status1":{"main":[[{"node":"Confirm Generation Status","type":"main","index":0}]]},"generate image (flux-rapid-api)":{"main":[[{"node":"Get Image3","type":"main","index":0}]]},"When clicking ‘Test workflow’":{"main":[[{"node":"generate image (flux)","type":"main","index":0}]]},"image to video (runway-rapid-api)":{"main":[[{"node":"1 minute3","type":"main","index":0}]]}}}


name: Auto-Respond to Gmail Enquiries using GPT-4o, Dumpling AI & LangChain Agent
author_name: Yang
author_username: yang
categories: []
created_at: 2025-05-14T21:06:14.263Z
updated_at: 2025-05-14T21:06:14.263Z
url: https://n8n.io/workflows/4057
scraped_at: 2025-06-19 22:48:59
description:
  Who is this for?

  This workflow is perfect for customer support teams, sales departments, or solopreneurs who receive frequent email enquiries and want to automate the initial response process using AI. If you spend too much time answering similar questions, this system helps respond faster and more intelligently—without writing a single line of code.

  What problem is this workflow solving?

  Manually responding to repeated customer enquiries slows productivity and increases delay. This workflow classifies if an incoming email is a real enquiry, analyzes the content with a LangChain-powered agent, fetches helpful context using Dumpling AI, and sends a personalized reply using Gmail—all within minutes.

  What this workflow does

  Listens for new incoming Gmail messages using the Gmail Trigger node.  
  Classifies whether the email is an enquiry using a GPT-4o classification prompt.  
  Uses a Filter node to continue only if the email was classified as an enquiry.  
  Passes the email content to a LangChain Agent, enhanced with memory, AI tools, and Dumpling AI to search for relevant information.  
  The agent constructs a smart, relevant response, then sends it to the original sender via Gmail.

  Setup

  Connect Gmail  
     Use the Gmail Trigger node to connect to the Gmail account that receives enquiries.  
     Make sure Gmail OAuth2 credentials are authenticated.

  Configure Dumpling AI Agent  
     Sign up at Dumpling AI.  
     Create an agent trained to search your help docs, site content, or FAQs.  
     Copy your Dumpling agent ID and API key.  
     Paste it in the Dumpling AI Agent – Search for Relevant Info HTTP Request node.

  Set Up LangChain Agent  
     No extra setup needed beyond connecting OpenAI credentials.  
     GPT-4o is used for classification and reply generation.

  Enable Gmail Reply Node  
     The final Send Email Response via Gmail node will send the AI-generated reply back to the same thread.

  How to customize this workflow to your needs

  Change the classification prompt to include other email types like “support”, “complaint”, or “sales”.  
  Add additional logic if you want to CC someone or forward certain types of enquiries.  
  Add a Notion or Google Sheets node to log the conversation for analytics.  
  Replace Gmail with Outlook or another email provider by switching the nodes.  
  Improve context by adding more AI tools like database queries or preloaded FAQs.

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

workflow_json:
  {"id":"uQTqLH5At9PZOy2g","meta":{"instanceId":"a1ae5c8dc6c65e674f9c3947d083abcc749ef2546dff9f4ff01de4d6a36ebfe6","templateCredsSetupCompleted":true},"name":"Auto-Respond to Gmail Enquiries using GPT-4o, Dumpling AI & LangChain Agent","tags":[],"nodes":[{"id":"149c7dd9-9f5f-4c5b-8342-7c907eb52402","name":"Watch Gmail for New Incoming Emails","type":"n8n-nodes-base.gmailTrigger","position":[-2300,-340],"parameters":{"filters":{},"pollTimes":{"item":[{"mode":"everyMinute"}]}},"credentials":{"gmailOAuth2":{"id":"j70r3RTMED1pgN3R","name":"Gmail account 2"}},"typeVersion":1.2},{"id":"8a0de384-9028-47e3-86e5-b5bf6476ae0c","name":"Classify Email Type with GPT-4o","type":"@n8n/n8n-nodes-langchain.openAi","position":[-2080,-340],"parameters":{"modelId":{"__rl":true,"mode":"list","value":"gpt-4o","cachedResultName":"GPT-4O"},"options":{},"messages":{"values":[{"content":"=Classify the following email content. Determine if it is an enquiry.\nIf it is an enquiry, return only this word: enquiry\nIf it is not an enquiry, return only this word: false\nDo not explain or add any other text. Only return the result.\nHere is the email body: {{ $json.snippet }}"}]}},"credentials":{"openAiApi":{"id":"fdhWALG84tBLgSZT","name":"OpenAi account"}},"typeVersion":1.8},{"id":"57756cd3-9009-4189-8cba-e2edba87554f","name":" Only Proceed if Email is an Enquiry","type":"n8n-nodes-base.filter","position":[-1704,-340],"parameters":{"options":{},"conditions":{"options":{"version":2,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"e6019006-0980-4cd6-8e5d-3f618fbca13a","operator":{"name":"filter.operator.equals","type":"string","operation":"equals"},"leftValue":"={{ $json.message.content }}","rightValue":"enquiry"}]}},"typeVersion":2.2},{"id":"64e851b8-7ff1-4b4c-9828-7c764594f1ea","name":"GPT-4o Chat Model","type":"@n8n/n8n-nodes-langchain.lmChatOpenAi","position":[-1484,-120],"parameters":{"model":{"__rl":true,"mode":"list","value":"gpt-4o-mini"},"options":{}},"credentials":{"openAiApi":{"id":"fdhWALG84tBLgSZT","name":"OpenAi account"}},"typeVersion":1.2},{"id":"2957c6ad-5e7b-4692-a96f-5c4fb5b8203c","name":"Memory Buffer (Past 10 Interactions)","type":"@n8n/n8n-nodes-langchain.memoryBufferWindow","position":[-1364,-120],"parameters":{"contextWindowLength":10},"typeVersion":1.3},{"id":"9e8617f1-cd89-4de5-9d44-ded155779745","name":"Dumpling AI Agent – Search for Relevant Info","type":"@n8n/n8n-nodes-langchain.toolHttpRequest","position":[-1244,-120],"parameters":{"url":"https://app.dumplingai.com/api/v1/agents/generate-completion","method":"POST","jsonBody":"={\n  \"messages\": [\n    {\n      \"role\": \"user\",\n      \"content\":\"{{ $('Watch Gmail for New Incoming Emails').item.json.snippet }}\"\n    }\n  ],\n  \"agentId\": \"a88a9b6c-1578-4da2-800b-561327367713\",\n  \"parseJson\": \"True\"\n  }","sendBody":true,"specifyBody":"json","authentication":"genericCredentialType","genericAuthType":"httpHeaderAuth"},"credentials":{"httpHeaderAuth":{"id":"5CBvzXCLjwWzCJRE","name":"n8n_integration"}},"typeVersion":1.1},{"id":"da474406-a6e3-427d-b21b-3e7e00ebe910","name":"Send Email Response via Gmail","type":"n8n-nodes-base.gmailTool","position":[-1124,-120],"webhookId":"b39f740b-77d1-426a-a07a-186a9ff0c1af","parameters":{"sendTo":"","message":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Message', ``, 'string') }}","options":{},"subject":"={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Subject', ``, 'string') }}"},"credentials":{"gmailOAuth2":{"id":"j70r3RTMED1pgN3R","name":"Gmail account 2"}},"typeVersion":2.1},{"id":"03882650-9272-43c3-b1bc-15adae456881","name":"LangChain Agent Handles Reply Logic","type":"@n8n/n8n-nodes-langchain.agent","position":[-1392,-340],"parameters":{"text":"={{ $('Watch Gmail for New Incoming Emails').item.json.snippet }}","options":{"systemMessage":"You are a helpful assistant, use the search for information tool to search for users information.\n\nuse Gmail tool to send email"},"promptType":"define"},"typeVersion":1.8},{"id":"52bb3b65-0b7f-4206-87c9-1f91997a44dd","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-1500,-560],"parameters":{"width":480,"height":240,"content":"### ✉️ Sticky Note 2: Website Scraping, Email Generation, and Sending\n\nFor leads with complete data, Dumpling AI scrapes the content of the lead’s company website. This content, combined with scraped details, is structured into a prompt using the Set node. GPT-4o processes the prompt and generates a personalized cold email. The email is then sent to the lead using Gmail. This automates targeted cold outreach using scraped insights and AI-generated messaging.\n"},"typeVersion":1},{"id":"3a6df2e9-1d1a-4cab-889c-c323f876b98f","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[-2320,-540],"parameters":{"width":540,"height":220,"content":"### Sticky Note 1: Apollo Link Sourcing & Contact Scraping\n\nThis section begins the workflow manually. The Apollo lead URLs are pulled from a Google Sheet. Each link is passed to Apify which scrapes key lead details such as name, email, company website, and other contact data. After scraping, a filter checks that both an email and website were found for the lead before moving forward. This ensures only complete lead data is used for outreach.\n\n"},"typeVersion":1}],"active":false,"pinData":{},"settings":{"executionOrder":"v1"},"versionId":"0f1d6a0b-eb13-4e1a-be9e-3f22eb17e66e","connections":{"GPT-4o Chat Model":{"ai_languageModel":[[{"node":"LangChain Agent Handles Reply Logic","type":"ai_languageModel","index":0}]]},"Send Email Response via Gmail":{"ai_tool":[[{"node":"LangChain Agent Handles Reply Logic","type":"ai_tool","index":0}]]},"Classify Email Type with GPT-4o":{"main":[[{"node":" Only Proceed if Email is an Enquiry","type":"main","index":0}]]},"LangChain Agent Handles Reply Logic":{"main":[[]]},"Watch Gmail for New Incoming Emails":{"main":[[{"node":"Classify Email Type with GPT-4o","type":"main","index":0}]]}," Only Proceed if Email is an Enquiry":{"main":[[{"node":"LangChain Agent Handles Reply Logic","type":"main","index":0}]]},"Memory Buffer (Past 10 Interactions)":{"ai_memory":[[{"node":"LangChain Agent Handles Reply Logic","type":"ai_memory","index":0}]]},"Dumpling AI Agent – Search for Relevant Info":{"ai_tool":[[{"node":"LangChain Agent Handles Reply Logic","type":"ai_tool","index":0}]]}}}


name: Extract and Save Invoice Data from Google Drive to Sheets with Dumpling AI
author_name: Yang
author_username: yang
categories: []
created_at: 2025-05-14T21:31:31.196Z
updated_at: 2025-05-14T21:31:31.196Z
url: https://n8n.io/workflows/4059
scraped_at: 2025-06-19 22:50:37
description:
  Who is this for?

  This workflow is perfect for operations teams, accountants, e-commerce businesses, or finance managers who regularly process digital invoices and need to automate data extraction and record-keeping.

  What problem is this workflow solving?

  Manually reading invoice PDFs, extracting relevant data, and entering it into spreadsheets is time-consuming and error-prone. This workflow automates that process—watching a Google Drive folder, extracting structured invoice data using Dumpling AI, and saving the results into Google Sheets.

  What this workflow does

  Watches a specific Google Drive folder for new invoices.
  Downloads the uploaded invoice file.
  Converts the file into a Base64 format.
  Sends the file to Dumpling AI’s extract-document endpoint with a detailed parsing prompt.
  Parses Dumpling AI’s JSON response using a Code node.
  Splits the items array into individual rows using the Split Out node.
  Appends each invoice item to a preformatted Google Sheet along with the full header metadata (order number, PO, addresses, etc.).

  Setup

  Google Drive Setup
     Create or select a folder in Google Drive and place the folder ID in the trigger node.
     Make sure your n8n Google Drive credentials are authorized for access.

  Google Sheets
     Create a Google Sheet with the following headers:
       Order number, Document Date, Po_number, Sold to name, Sold to address, Ship to name, Ship to address, Model, Description, Quantity, Unity price, Total price
     Paste the Sheet ID and sheet name (Sheet1) into the Google Sheets node.

  Dumpling AI
     Sign up at Dumpling AI
     Go to your account settings and generate your API key.
     Paste this key into the HTTP header of the Dumpling AI request node.
     The endpoint used is: https://app.dumplingai.com/api/v1/extract-document

  Prompt (already included)
     This prompt extracts: order number, document date, PO number, shipping/billing details, and detailed line items (model, quantity, unit price, total).

  How to customize this workflow to your needs

  Adjust the Google Sheet fields to fit your invoice structure.
  Modify the Dumpling AI prompt if your invoices have additional or different data points.
  Add filtering logic if you want to handle different invoice types differently.
  Replace Google Sheets with Airtable or a database if preferred.
  Use a different trigger like an email attachment if invoices come via email.

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

workflow_json:
  {"id":"Q9K6tDu4TJpqtRQ1","meta":{"instanceId":"a1ae5c8dc6c65e674f9c3947d083abcc749ef2546dff9f4ff01de4d6a36ebfe6","templateCredsSetupCompleted":true},"name":"Extract and Save Invoice Data from Google Drive to Sheets with Dumpling AI","tags":[],"nodes":[{"id":"4cdec8f8-9e08-433f-832d-18a9af3f4531","name":"Google Drive Trigger – Watch Folder for New Files","type":"n8n-nodes-base.googleDriveTrigger","position":[-160,-180],"parameters":{"event":"fileCreated","options":{},"pollTimes":{"item":[{"mode":"everyMinute"}]},"triggerOn":"specificFolder","folderToWatch":{"__rl":true,"mode":"list","value":"","cachedResultUrl":"https://drive.google.com/drive/folders/1Dquh3PguyBImKvHlbkp55NBvYoB8IKr5","cachedResultName":"invoice-n8n"}},"credentials":{"googleDriveOAuth2Api":{"id":"8JSukfcGbpywgEUz","name":"n8n"}},"typeVersion":1},{"id":"b67aea52-5f39-4fce-b476-d3b991b30519","name":"Download Invoice File","type":"n8n-nodes-base.googleDrive","position":[60,-180],"parameters":{"fileId":{"__rl":true,"mode":"id","value":"={{ $json.id }}"},"options":{},"operation":"download"},"credentials":{"googleDriveOAuth2Api":{"id":"8JSukfcGbpywgEUz","name":"n8n"}},"typeVersion":3},{"id":"94ccaf02-0070-4200-b778-139ea075949a","name":"Convert invoice File to Base64","type":"n8n-nodes-base.extractFromFile","position":[280,-180],"parameters":{"options":{},"operation":"binaryToPropery"},"typeVersion":1},{"id":"760f6b02-65b6-4a28-af70-53602f8e2724","name":"Send file to Dumpling AI for Data Extraction","type":"n8n-nodes-base.httpRequest","position":[500,-180],"parameters":{"url":"https://app.dumplingai.com/api/v1/extract-document","method":"POST","options":{},"jsonBody":"={\n  \"inputMethod\": \"base64\",\n  \"files\": [\"{{ $json.data }}\"], \n  \"prompt\": \"Extract the order number, document date, PO number, sold to name and address, ship to name and address, list of items with model, quantity, unit price, and total price, and the final total amount including tax.\", \n  \"jsonMode\": \"true\"\n}","sendBody":true,"specifyBody":"json","authentication":"genericCredentialType","genericAuthType":"httpHeaderAuth"},"credentials":{"httpHeaderAuth":{"id":"xamyMqCpAech5BeT","name":"Header Auth account"}},"typeVersion":4.2},{"id":"b5545cf6-8ebb-4c0e-903b-5a14af7de087","name":"Parse Dumpling AI JSON Response","type":"n8n-nodes-base.code","position":[720,-180],"parameters":{"jsCode":"const raw = $input.first().json.results;\nconst parsed = JSON.parse(raw);\nreturn [{ json: parsed }];\n"},"typeVersion":2},{"id":"84318159-a0ce-4049-a7db-2ac0fa79b8d4","name":"Split line Items from Invoice","type":"n8n-nodes-base.splitOut","position":[940,-180],"parameters":{"options":{},"fieldToSplitOut":"items"},"typeVersion":1},{"id":"834d6b99-cd0e-4633-949d-40e53ba06324","name":"Save Data to Google Sheet","type":"n8n-nodes-base.googleSheets","position":[1140,-180],"parameters":{"columns":{"value":{"Model":"={{ $json.model }}","Quantity":"={{ $json.quantity }}","Po_number":"={{ $('Parse Dumpling AI JSON Response').item.json.PO_number }}","Description":"={{ $json.description }}","Total price":"={{ $json.total_price }}","Unity price":"={{ $json.unit_price }}","Order number":"={{ $('Parse Dumpling AI JSON Response').item.json.order_number }}","Ship to name":"={{ $('Parse Dumpling AI JSON Response').item.json.ship_to_name }}","Sold to name":"={{ $('Parse Dumpling AI JSON Response').item.json.sold_to_name }}","Document Date":"={{ $('Parse Dumpling AI JSON Response').item.json.document_date }}","Ship to address":"={{ $('Parse Dumpling AI JSON Response').item.json.ship_to_address }}","Sold to address":"={{ $('Parse Dumpling AI JSON Response').item.json.sold_to_address }}"},"schema":[{"id":"Order number","type":"string","display":true,"required":false,"displayName":"Order number","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Document Date","type":"string","display":true,"required":false,"displayName":"Document Date","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Po_number","type":"string","display":true,"required":false,"displayName":"Po_number","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Sold to name","type":"string","display":true,"required":false,"displayName":"Sold to name","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Sold to address","type":"string","display":true,"required":false,"displayName":"Sold to address","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Ship to name","type":"string","display":true,"required":false,"displayName":"Ship to name","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Ship to address","type":"string","display":true,"required":false,"displayName":"Ship to address","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Model","type":"string","display":true,"required":false,"displayName":"Model","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Description","type":"string","display":true,"required":false,"displayName":"Description","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Quantity","type":"string","display":true,"required":false,"displayName":"Quantity","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Unity price","type":"string","display":true,"required":false,"displayName":"Unity price","defaultMatch":false,"canBeUsedToMatch":true},{"id":"Total price","type":"string","display":true,"required":false,"displayName":"Total price","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"append","sheetName":{"__rl":true,"mode":"list","value":"","cachedResultUrl":"https://docs.google.com/spreadsheets/d/170eyZdmRUNXlpSZmcl5PiHTUKjukd-soDQq2cAe6FQo/edit#gid=0","cachedResultName":"Sheet1"},"documentId":{"__rl":true,"mode":"list","value":"","cachedResultUrl":"https://docs.google.com/spreadsheets/d/170eyZdmRUNXlpSZmcl5PiHTUKjukd-soDQq2cAe6FQo/edit?usp=drivesdk","cachedResultName":"my invoice"}},"credentials":{"googleSheetsOAuth2Api":{"id":"GaJqJHuS5mQxap7q","name":"Google Sheets account"}},"typeVersion":4.5},{"id":"f98684d0-6c7b-4ba2-b820-4b30e9ff10c1","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[-740,-400],"parameters":{"width":540,"height":500,"content":"### 📌 **Workflow Overview: Extract & Save Invoice Data from Google Drive with Dumpling AI**\n\n#### This workflow monitors a Google Drive folder for new files (invoices), extracts structured invoice data using Dumpling AI, and appends it to a Google Sheet.\n---\n🔹 **Node Breakdown:**\n\n1. **Google Drive Trigger** – Watches a folder for new invoice files.  \n2. **Download Invoice File** – Retrieves the uploaded file from Drive.  \n3. **Extract Base64** – Converts the downloaded file to base64 format.  \n4. **Dumpling AI Extraction** – Sends the base64 file with a prompt to Dumpling AI for invoice parsing.  \n5. **Parse AI Response** – Converts the returned JSON string into readable structured data.  \n6. **Split Line Items** – Breaks the `items` array into individual invoice entries.  \n7. **Append to Google Sheet** – Saves the invoice data row by row into the target spreadsheet.\n\n✅ Make sure you have your Dumpling AI API key and correct Google Sheet ID in place before running the workflow.\n\n"},"typeVersion":1}],"active":false,"pinData":{"Split line Items from Invoice":[{"json":{"model":"AMST42CU1300","quantity":1,"unit_price":"$773.85","description":"AIR HANDLER","total_price":"$773.85"}},{"json":{"model":"GLZS4BA4210","quantity":1,"unit_price":"$1,508.85","description":"14.3 SEER2 HP R32, 3.5 TON","total_price":"$1,508.85"}},{"json":{"model":"HKTSD15XB","quantity":1,"unit_price":"$156.00","description":"ELECTRIC HEAT KIT, 15 KW","total_price":"$156.00"}},{"json":{"model":"83615","quantity":1,"unit_price":"$15.39","description":"MARS 60A NON-FUSED DISCONNECT","total_price":"$15.39"}},{"json":{"model":"6RSR048118","quantity":1,"unit_price":"$11.22","description":"INSULTUBE TITAN 1/2\"X1-1/8\"X 6'","total_price":"$11.22"}},{"json":{"model":"SB-2","quantity":1,"unit_price":"$0.67","description":"2\" SEALANT BRUSH","total_price":"$0.67"}},{"json":{"model":"6RX048078","quantity":2,"unit_price":"$3.18","total_price":"$6.36"}},{"json":{"model":"CADS-1G","quantity":1,"unit_price":"$14.36","description":"FIBER DUCT SEALANT GRAY 1 GAL","total_price":"$14.36"}},{"json":{"model":"599390-EC","quantity":1,"unit_price":"$63.91","description":"20X20 1-2\" F/C FILTER BASE","total_price":"$63.91"}},{"json":{"model":"CCF-8-2020-1","quantity":1,"unit_price":"$4.09","description":"CC M8 PLEAT FILTER 20X20X1","total_price":"$4.09"}},{"json":{"model":"TH1110DH1003","quantity":1,"unit_price":"$38.21","description":"PRO1000 1H/1C NON-PROG HORIZON","total_price":"$38.21"}},{"json":{"model":"401-007BC","quantity":1,"unit_price":"$0.62","description":"PVC 3/4 TEE SLIP","total_price":"$0.62"}},{"json":{"model":"436-007BC","quantity":2,"unit_price":"$0.49","description":"PVC 3/4 MALE ADPT MIPTXS","total_price":"$0.98"}},{"json":{"model":"406-007BC","quantity":2,"unit_price":"$0.46","description":"PVC 3/4 90 ELB SXS","total_price":"$0.92"}},{"json":{"model":"429-007BC","quantity":3,"unit_price":"$0.45","description":"PVC 3/4 COUP SLIP","total_price":"$1.34"}},{"json":{"model":"97085","quantity":1,"unit_price":"$33.31","description":"SAFE-T-SWITCH SS1-GEN3","total_price":"$33.31"}},{"json":{"model":"304100-HC","quantity":1,"unit_price":"$31.84","description":"MASTIC TAPE 3\" X 100'","total_price":"$31.84"}},{"json":{"model":"84137","quantity":1,"unit_price":"$25.78","description":"WHIP 3/4 X 6' 8GA NONMETALLIC","total_price":"$25.78"}}],"Parse Dumpling AI JSON Response":[{"json":{"tax":"$221.74","items":[{"model":"AMST42CU1300","quantity":1,"unit_price":"$773.85","description":"AIR HANDLER","total_price":"$773.85"},{"model":"GLZS4BA4210","quantity":1,"unit_price":"$1,508.85","description":"14.3 SEER2 HP R32, 3.5 TON","total_price":"$1,508.85"},{"model":"HKTSD15XB","quantity":1,"unit_price":"$156.00","description":"ELECTRIC HEAT KIT, 15 KW","total_price":"$156.00"},{"model":"83615","quantity":1,"unit_price":"$15.39","description":"MARS 60A NON-FUSED DISCONNECT","total_price":"$15.39"},{"model":"6RSR048118","quantity":1,"unit_price":"$11.22","description":"INSULTUBE TITAN 1/2\"X1-1/8\"X 6'","total_price":"$11.22"},{"model":"SB-2","quantity":1,"unit_price":"$0.67","description":"2\" SEALANT BRUSH","total_price":"$0.67"},{"model":"6RX048078","quantity":2,"unit_price":"$3.18","total_price":"$6.36"},{"model":"CADS-1G","quantity":1,"unit_price":"$14.36","description":"FIBER DUCT SEALANT GRAY 1 GAL","total_price":"$14.36"},{"model":"599390-EC","quantity":1,"unit_price":"$63.91","description":"20X20 1-2\" F/C FILTER BASE","total_price":"$63.91"},{"model":"CCF-8-2020-1","quantity":1,"unit_price":"$4.09","description":"CC M8 PLEAT FILTER 20X20X1","total_price":"$4.09"},{"model":"TH1110DH1003","quantity":1,"unit_price":"$38.21","description":"PRO1000 1H/1C NON-PROG HORIZON","total_price":"$38.21"},{"model":"401-007BC","quantity":1,"unit_price":"$0.62","description":"PVC 3/4 TEE SLIP","total_price":"$0.62"},{"model":"436-007BC","quantity":2,"unit_price":"$0.49","description":"PVC 3/4 MALE ADPT MIPTXS","total_price":"$0.98"},{"model":"406-007BC","quantity":2,"unit_price":"$0.46","description":"PVC 3/4 90 ELB SXS","total_price":"$0.92"},{"model":"429-007BC","quantity":3,"unit_price":"$0.45","description":"PVC 3/4 COUP SLIP","total_price":"$1.34"},{"model":"97085","quantity":1,"unit_price":"$33.31","description":"SAFE-T-SWITCH SS1-GEN3","total_price":"$33.31"},{"model":"304100-HC","quantity":1,"unit_price":"$31.84","description":"MASTIC TAPE 3\" X 100'","total_price":"$31.84"},{"model":"84137","quantity":1,"unit_price":"$25.78","description":"WHIP 3/4 X 6' 8GA NONMETALLIC","total_price":"$25.78"}],"PO_number":"ASHLEY OAK","order_number":"FN29709","ship_to_name":"CARNES & SONS LLC","sold_to_name":"CARNES & SONS LLC","total_amount":"$2,909.44","document_date":"08/23/2024","ship_to_address":"DAIKIN COMFORT TECHNOLOGY #364, 4980 EISENHAUER RD, SUITE 206 SAN ANTONIO TX 78218","sold_to_address":"9988 MACAWAY RD, ADKINS TX 78101"}}],"Send file to Dumpling AI for Data Extraction":[{"json":{"pages":4,"prompt":"Extract the order number, document date, PO number, sold to name and address, ship to name and address, list of items with model, quantity, unit price, and total price, and the final total amount including tax.","results":"{\n  \"order_number\": \"FN29709\",\n  \"document_date\": \"08/23/2024\",\n  \"PO_number\": \"ASHLEY OAK\",\n  \"sold_to_name\": \"CARNES & SONS LLC\",\n  \"sold_to_address\": \"9988 MACAWAY RD, ADKINS TX 78101\",\n  \"ship_to_name\": \"CARNES & SONS LLC\",\n  \"ship_to_address\": \"DAIKIN COMFORT TECHNOLOGY #364, 4980 EISENHAUER RD, SUITE 206 SAN ANTONIO TX 78218\",\n  \"items\": [\n    {\n      \"model\": \"AMST42CU1300\",\n      \"description\": \"AIR HANDLER\",\n      \"quantity\": 1,\n      \"unit_price\": \"$773.85\",\n      \"total_price\": \"$773.85\"\n    },\n    {\n      \"model\": \"GLZS4BA4210\",\n      \"description\": \"14.3 SEER2 HP R32, 3.5 TON\",\n      \"quantity\": 1,\n      \"unit_price\": \"$1,508.85\",\n      \"total_price\": \"$1,508.85\"\n    },\n    {\n      \"model\": \"HKTSD15XB\",\n      \"description\": \"ELECTRIC HEAT KIT, 15 KW\",\n      \"quantity\": 1,\n      \"unit_price\": \"$156.00\",\n      \"total_price\": \"$156.00\"\n    },\n    {\n      \"model\": \"83615\",\n      \"description\": \"MARS 60A NON-FUSED DISCONNECT\",\n      \"quantity\": 1,\n      \"unit_price\": \"$15.39\",\n      \"total_price\": \"$15.39\"\n    },\n    {\n      \"model\": \"6RSR048118\",\n      \"description\": \"INSULTUBE TITAN 1/2\\\"X1-1/8\\\"X 6'\",\n      \"quantity\": 1,\n      \"unit_price\": \"$11.22\",\n      \"total_price\": \"$11.22\"\n    },\n    {\n      \"model\": \"SB-2\",\n      \"description\": \"2\\\" SEALANT BRUSH\",\n      \"quantity\": 1,\n      \"unit_price\": \"$0.67\",\n      \"total_price\": \"$0.67\"\n    },\n    {\n      \"model\": \"6RX048078\",\n      \"quantity\": 2,\n      \"unit_price\": \"$3.18\",\n      \"total_price\": \"$6.36\"\n    },\n    {\n      \"model\": \"CADS-1G\",\n      \"description\": \"FIBER DUCT SEALANT GRAY 1 GAL\",\n      \"quantity\": 1,\n      \"unit_price\": \"$14.36\",\n      \"total_price\": \"$14.36\"\n    },\n    {\n      \"model\": \"599390-EC\",\n      \"description\": \"20X20 1-2\\\" F/C FILTER BASE\",\n      \"quantity\": 1,\n      \"unit_price\": \"$63.91\",\n      \"total_price\": \"$63.91\"\n    },\n    {\n      \"model\": \"CCF-8-2020-1\",\n      \"description\": \"CC M8 PLEAT FILTER 20X20X1\",\n      \"quantity\": 1,\n      \"unit_price\": \"$4.09\",\n      \"total_price\": \"$4.09\"\n    },\n    {\n      \"model\": \"TH1110DH1003\",\n      \"description\": \"PRO1000 1H/1C NON-PROG HORIZON\",\n      \"quantity\": 1,\n      \"unit_price\": \"$38.21\",\n      \"total_price\": \"$38.21\"\n    },\n    {\n      \"model\": \"401-007BC\",\n      \"description\": \"PVC 3/4 TEE SLIP\",\n      \"quantity\": 1,\n      \"unit_price\": \"$0.62\",\n      \"total_price\": \"$0.62\"\n    },\n    {\n      \"model\": \"436-007BC\",\n      \"description\": \"PVC 3/4 MALE ADPT MIPTXS\",\n      \"quantity\": 2,\n      \"unit_price\": \"$0.49\",\n      \"total_price\": \"$0.98\"\n    },\n    {\n      \"model\": \"406-007BC\",\n      \"description\": \"PVC 3/4 90 ELB SXS\",\n      \"quantity\": 2,\n      \"unit_price\": \"$0.46\",\n      \"total_price\": \"$0.92\"\n    },\n    {\n      \"model\": \"429-007BC\",\n      \"description\": \"PVC 3/4 COUP SLIP\",\n      \"quantity\": 3,\n      \"unit_price\": \"$0.45\",\n      \"total_price\": \"$1.34\"\n    },\n    {\n      \"model\": \"97085\",\n      \"description\": \"SAFE-T-SWITCH SS1-GEN3\",\n      \"quantity\": 1,\n      \"unit_price\": \"$33.31\",\n      \"total_price\": \"$33.31\"\n    },\n    {\n      \"model\": \"304100-HC\",\n      \"description\": \"MASTIC TAPE 3\\\" X 100'\",\n      \"quantity\": 1,\n      \"unit_price\": \"$31.84\",\n      \"total_price\": \"$31.84\"\n    },\n    {\n      \"model\": \"84137\",\n      \"description\": \"WHIP 3/4 X 6' 8GA NONMETALLIC\",\n      \"quantity\": 1,\n      \"unit_price\": \"$25.78\",\n      \"total_price\": \"$25.78\"\n    }\n  ],\n  \"total_amount\": \"$2,909.44\",\n  \"tax\": \"$221.74\"\n}","fileCount":1,"creditUsage":14}}]},"settings":{"executionOrder":"v1"},"versionId":"d618bc19-f2a6-454b-bbce-9833eca14022","connections":{"Download Invoice File":{"main":[[{"node":"Convert invoice File to Base64","type":"main","index":0}]]},"Split line Items from Invoice":{"main":[[{"node":"Save Data to Google Sheet","type":"main","index":0}]]},"Convert invoice File to Base64":{"main":[[{"node":"Send file to Dumpling AI for Data Extraction","type":"main","index":0}]]},"Parse Dumpling AI JSON Response":{"main":[[{"node":"Split line Items from Invoice","type":"main","index":0}]]},"Send file to Dumpling AI for Data Extraction":{"main":[[{"node":"Parse Dumpling AI JSON Response","type":"main","index":0}]]},"Google Drive Trigger – Watch Folder for New Files":{"main":[[{"node":"Download Invoice File","type":"main","index":0}]]}}}


