AutomationFlowsAI & RAG › Notify Users When Features Ship with Semantic Search From Tally to Gmail

Notify Users When Features Ship with Semantic Search From Tally to Gmail

ByEhsan @ehsan-z on n8n.io

This workflow is for Product Managers, Indie Hackers, and Customer Success teams who collect feature requests but struggle to notify specific users when those features actually ship. It helps you turn old feedback into customer loyalty and potential upsells.

Event trigger★★★★☆ complexityAI-powered27 nodesN8N Nodes TallyformsSupabase Vector StoreOpenAI EmbeddingsDocument Default Data LoaderRss Feed Read TriggerHTTP RequestGmailOutput Parser Structured
AI & RAG Trigger: Event Nodes: 27 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #11369 — we link there as the canonical source.

This workflow follows the Agent → Documentdefaultdataloader recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "8EEBlolGxhSkmvy9",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "feature request closer v2",
  "tags": [],
  "nodes": [
    {
      "id": "fa71b41d-03f0-4c2f-8057-48c8ef12350f",
      "name": "Tally Trigger",
      "type": "n8n-nodes-tallyforms.tallyTrigger",
      "disabled": true,
      "position": [
        -480,
        48
      ],
      "parameters": {
        "formId": "gDbZ6P"
      },
      "typeVersion": 1
    },
    {
      "id": "d6e0920b-4d08-4921-ba6f-3e1bc6f39c3e",
      "name": "Data Cleaner",
      "type": "n8n-nodes-base.set",
      "position": [
        -192,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "81db54ad-88ad-4159-896e-5d50e606a325",
              "name": "user_name",
              "type": "string",
              "value": "={{ $json.question_aaaDDD }}"
            },
            {
              "id": "4eda0e05-d795-4535-9537-f351c313be52",
              "name": "user_email",
              "type": "string",
              "value": "={{ $json.question_bbbEEE }}"
            },
            {
              "id": "20d22061-2a21-423f-b975-547c466c2883",
              "name": "original_text",
              "type": "string",
              "value": "={{ $json.question_cccFFF }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fa1e4e46-cf5b-4a58-a593-abe62cf8c438",
      "name": "Supabase Vector Store",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "position": [
        192,
        16
      ],
      "parameters": {
        "mode": "insert",
        "options": {},
        "tableName": {
          "__rl": true,
          "mode": "list",
          "value": "feature_requests",
          "cachedResultName": "feature_requests"
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "a6c61c6e-7d64-481b-bdbc-26d0f61298bf",
      "name": "Embeddings OpenAI",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "position": [
        160,
        256
      ],
      "parameters": {
        "model": "nomic-embed-text:latest",
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "1afaec7e-a3df-4cd9-a60f-53416f7d3901",
      "name": "Default Data Loader",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "position": [
        336,
        224
      ],
      "parameters": {
        "options": {
          "metadata": {
            "metadataValues": [
              {
                "name": "user_name",
                "value": "={{ $json.user_name }}"
              },
              {
                "name": "user_email",
                "value": "={{ $json.user_email }}"
              }
            ]
          }
        },
        "jsonData": "={{ $json.original_text }}",
        "jsonMode": "expressionData"
      },
      "typeVersion": 1.1
    },
    {
      "id": "3998b60d-7cc8-444a-85ba-c5b6c9776b5f",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -688,
        -400
      ],
      "parameters": {
        "color": 7,
        "width": 1312,
        "height": 896,
        "content": "## \ud83d\udce5 1. Capture & Memorize\nThis section cleans form data, maps fields (Name/Email), creates embeddings, and stores them in Supabase."
      },
      "typeVersion": 1
    },
    {
      "id": "84b7e470-486f-4d4d-ba79-c126efc664aa",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        816,
        -32
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "3fc0fc03-caf4-4ceb-b928-c3eec8e2cf35",
      "name": "RSS Feed Trigger",
      "type": "n8n-nodes-base.rssFeedReadTrigger",
      "position": [
        832,
        144
      ],
      "parameters": {
        "feedUrl": "https://your_blog.url/rss/",
        "pollTimes": {
          "item": [
            {
              "mode": "everyWeek"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "aa3d1034-ffb0-43a5-9a0c-53f4ec7f776b",
      "name": "Generate Embedding (Ollama)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1584,
        64
      ],
      "parameters": {
        "url": "http://host.docker.internal:11434/api/embeddings",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "model",
              "value": "nomic-embed-text"
            },
            {
              "name": "prompt",
              "value": "={{ $json.feature_text }}"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "71da9827-231b-4e16-9ead-e3080a35885d",
      "name": "Loop Matches",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2272,
        48
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "52c852f4-311c-4737-a995-66971c453258",
      "name": "Create Draft",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2880,
        64
      ],
      "parameters": {
        "message": "={{ $json.output.body }}",
        "options": {},
        "subject": "={{ $json.output.subject }} - to:{{ $('Loop Matches').item.json.user_email }}",
        "resource": "draft"
      },
      "typeVersion": 2.1
    },
    {
      "id": "1688ef73-f02e-495d-9a0d-551cda7b27e4",
      "name": "Done!",
      "type": "n8n-nodes-base.noOp",
      "position": [
        3216,
        -352
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "9fdae0c7-328b-4b13-9d36-61715af713f5",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        2688,
        288
      ],
      "parameters": {
        "jsonSchemaExample": "{ \"subject\": \"...\", \"body\": \"...\" }"
      },
      "typeVersion": 1.3
    },
    {
      "id": "8dd4140a-33de-445b-9a18-c52f27d69871",
      "name": "OpenAI Chat Model3",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2544,
        320
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "id",
          "value": "command-r7b:7b-12-2024-q8_0"
        },
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "9804ceed-770a-4522-9e39-b266051b38a9",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        656,
        -400
      ],
      "parameters": {
        "color": 7,
        "width": 1456,
        "height": 896,
        "content": "## \ud83d\udd0d 2. Trigger & Search\nTriggers on a new feature launch (RSS or Manual), embeds the description, and finds semantically similar users."
      },
      "typeVersion": 1
    },
    {
      "id": "5fe4f8d2-960a-496a-9be3-f0839538311b",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1344,
        -400
      ],
      "parameters": {
        "width": 592,
        "height": 656,
        "content": "# \ud83c\udfa3 Close the Loop: Tally to Gmail\nTurn old feature requests into new revenue by notifying users when you ship what they asked for.\n\n## How it works\n1. **Listen:** Captures Tally form submissions.\n2. **Embed:** Converts text to vectors (using Nomic/Ollama).\n3. **Store:** Saves user info & vectors to Supabase.\n4. **Match:** When a feature launches, searches Supabase for matching requests.\n5. **Act:** AI drafts a personal Gmail reply.\n\n## Setup\n* **IMPORTANT:** Copy the SQL script from the **Template Description** and run it in Supabase first.\n* Update the **HTTP Request** node with your Supabase URL."
      },
      "typeVersion": 1
    },
    {
      "id": "9abaaecb-e456-41eb-a0d7-a39f8f8a60ea",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2160,
        -400
      ],
      "parameters": {
        "color": 7,
        "width": 960,
        "height": 896,
        "content": "## \u270d\ufe0f 3. Draft Personal Emails\nIn the loops through every match and AI writes a custom email connecting their specific request to your new feature.\n* **Gmail:** Creates a DRAFT (does not send automatically)."
      },
      "typeVersion": 1
    },
    {
      "id": "d71b3d53-8556-445d-8086-56f6a08cf30d",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3152,
        -400
      ],
      "parameters": {
        "color": 4,
        "width": 496,
        "height": 384,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n# \ud83c\udf89 Done!\n\nIf the workflow reaches here, you have successfully:\n1. Found a user who felt ignored.\n2. Drafted an email showing you listened.\n3. Potentially reduced churn or gained an upsell.\n\n**Next Step:** Check your Gmail Drafts folder! \ud83d\udcee"
      },
      "typeVersion": 1
    },
    {
      "id": "14898e59-d92a-4d60-b115-218bb19032e4",
      "name": "Lunch description",
      "type": "n8n-nodes-base.set",
      "position": [
        1024,
        -32
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "5bceab7a-7012-4e90-a16b-ec6b04ca9a6b",
              "name": "description",
              "type": "string",
              "value": "we lunched dark mode"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "2808f864-51ae-4d38-bdd1-c80fca189ea8",
      "name": "Manage input - Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        1296,
        64
      ],
      "parameters": {
        "jsCode": "// 1. Get the input data (works for both Manual and RSS)\nconst input = $input.first().json;\n\n// 2. prioritize manual input, then RSS description, then RSS title\nconst text = input.contentSnippet || input.description || input.title || input.first().json.description || input.manual_text;\n\nreturn { feature_text: text };"
      },
      "typeVersion": 2
    },
    {
      "id": "bc326d78-86d3-4d96-909e-49106e027309",
      "name": "HTTP Request - Supabase Search",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1856,
        64
      ],
      "parameters": {
        "url": "https://your_link_to.supabase.co/rest/v1/rpc/match_feature_requests",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "query_embedding",
              "value": "={{ $json.embedding }}"
            },
            {
              "name": "match_threshold",
              "value": "0.70"
            },
            {
              "name": "match_count",
              "value": "10"
            }
          ]
        },
        "nodeCredentialType": "supabaseApi"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "e511c78a-1219-42ae-9ac1-68f346ff5507",
      "name": "AI Agent - Draft text maker",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "onError": "continueRegularOutput",
      "position": [
        2496,
        64
      ],
      "parameters": {
        "text": "=You are a helpful product manager.\n\nContext:\n- User: {{ $json.user_name }}\n- They asked for: \"{{ $json.content }}\"\n- We launched: \"{{ $('Lunch description').item.json.description }}\"\n\nWrite a JSON object with a subject line and a short, friendly HTML email body telling them the feature is here.\n\nFormat: { \"subject\": \"...\", \"body\": \"...\" }",
        "options": {},
        "promptType": "define",
        "needsFallback": true,
        "hasOutputParser": true
      },
      "retryOnFail": true,
      "typeVersion": 2.2,
      "waitBetweenTries": 3000
    },
    {
      "id": "043f9d06-d296-40a0-af46-c3c4f6d68091",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -272,
        -208
      ],
      "parameters": {
        "color": 5,
        "width": 352,
        "height": 432,
        "content": "### \u2699\ufe0f How to Configure:\n**Data Cleaner (Important):** Open this node!\n   - Map your form's \"Name\" field to `user_name`\n   - Map your form's \"Email\" field to `user_email`\n   - Map the \"Request\" field to `original_text`\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7c075856-1adf-41b1-bdd6-c6d255ffc27c",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        -208
      ],
      "parameters": {
        "color": 5,
        "width": 304,
        "height": 432,
        "content": "### \u2699\ufe0f How to Configure:\n**Tally Trigger:** Connect your form credential."
      },
      "typeVersion": 1
    },
    {
      "id": "7ea208dc-7755-4cf6-8b5c-1d8f1227bf9f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        112,
        -208
      ],
      "parameters": {
        "color": 5,
        "width": 448,
        "height": 608,
        "content": "### \u2699\ufe0f How to Configure:\nCopy the SQL script from the **Template Description** and run it in Supabase first.\n\nThis node:\n1. **Embed:** Converts text to vectors (using Nomic/Ollama).\n2. **Store:** Saves user info & vectors to Supabase."
      },
      "typeVersion": 1
    },
    {
      "id": "517cfc80-4a11-4293-8657-3ab93f3ebd38",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        -160
      ],
      "parameters": {
        "color": 6,
        "width": 464,
        "height": 544,
        "content": "### Dual Triggers\n- **RSS Feed:** Checks your changelog weekly. If you post your product lunch it triggers.\n- **Manual:** Great for testing! Type a phrase in the 'Lunch description' node to test the search and click \"Execute\" ."
      },
      "typeVersion": 1
    },
    {
      "id": "0e8ff8fa-c79d-40ac-9b27-361e2df67b6e",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        -160
      ],
      "parameters": {
        "color": 6,
        "width": 592,
        "height": 544,
        "content": "### The Vector Search\n- **Embedding:** Converts your announcement into numbers (768 dimensions).\n- **HTTP Request:** Sends those numbers to Supabase to find the nearest semantic match.\n  - *Setup:* Update the **URL** in this node to your Supabase Project URL.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f2314c07-fb05-4418-b6f2-6030874f3a83",
  "connections": {
    "Create Draft": {
      "main": [
        [
          {
            "node": "Loop Matches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Data Cleaner": {
      "main": [
        [
          {
            "node": "Supabase Vector Store",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Matches": {
      "main": [
        [
          {
            "node": "Done!",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "AI Agent - Draft text maker",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tally Trigger": {
      "main": [
        [
          {
            "node": "Data Cleaner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS Feed Trigger": {
      "main": [
        [
          {
            "node": "Manage input - Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings OpenAI": {
      "ai_embedding": [
        [
          {
            "node": "Supabase Vector Store",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Lunch description": {
      "main": [
        [
          {
            "node": "Manage input - Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model3": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent - Draft text maker",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "AI Agent - Draft text maker",
            "type": "ai_languageModel",
            "index": 1
          }
        ]
      ]
    },
    "Default Data Loader": {
      "ai_document": [
        [
          {
            "node": "Supabase Vector Store",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent - Draft text maker",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent - Draft text maker": {
      "main": [
        [
          {
            "node": "Create Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Embedding (Ollama)": {
      "main": [
        [
          {
            "node": "HTTP Request - Supabase Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request - Supabase Search": {
      "main": [
        [
          {
            "node": "Loop Matches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manage input - Code in JavaScript": {
      "main": [
        [
          {
            "node": "Generate Embedding (Ollama)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Lunch description",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow is for Product Managers, Indie Hackers, and Customer Success teams who collect feature requests but struggle to notify specific users when those features actually ship. It helps you turn old feedback into customer loyalty and potential upsells.

Source: https://n8n.io/workflows/11369/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Your AI workforce is ready. Are you?

Google Sheets Tool, Mcp Trigger, Google Drive +29
AI & RAG

This intelligent chatbot leverages cutting-edge financial APIs and AI-driven analysis to deliver comprehensive stock research reports. Get instant access to professional-grade investment analysis that

Tool Think, Supabase Vector Store, OpenAI Embeddings +15
AI & RAG

This advanced n8n workflow automates the full lead enrichment, qualification, and personalized outreach process tailored specifically for the B2B real estate sector. Integrating top platforms like Api

N8N Nodes Fillout, OpenAI Chat, Pinecone Vector Store +11
AI & RAG

This n8n template automatically classifies incoming emails (Sales, Support, Internal, Finance, Promotions) and routes them to a dedicated OpenAI LLM Agent for processing. Depending on the category, th

OpenAI, Gmail, Text Classifier +16
AI & RAG

Who is this for? This workflow is ideal for HR teams, startups, and enterprises that want to handle employee interactions through WhatsApp and automate responses using LLM (OpenAI) and intelligent rou

WhatsApp Trigger, OpenAI, OpenAI Chat +13